Update docs
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59
60 #include "qtatomparser.h"
61 #include "qtdemux_types.h"
62 #include "qtdemux_dump.h"
63 #include "fourcc.h"
64 #include "descriptors.h"
65 #include "qtdemux_lang.h"
66 #include "qtdemux.h"
67 #include "qtpalette.h"
68
69 #include "gst/riff/riff-media.h"
70 #include "gst/riff/riff-read.h"
71
72 #include <gst/pbutils/pbutils.h>
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 GST_DEBUG_CATEGORY (qtdemux_debug);
104 #define GST_CAT_DEFAULT qtdemux_debug
105
106 typedef struct _QtDemuxSegment QtDemuxSegment;
107 typedef struct _QtDemuxSample QtDemuxSample;
108
109 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
110
111 struct _QtDemuxSample
112 {
113   guint32 size;
114   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
115   guint64 offset;
116   guint64 timestamp;            /* DTS In mov time */
117   guint32 duration;             /* In mov time */
118   gboolean keyframe;            /* TRUE when this packet is a keyframe */
119 };
120
121 /* Macros for converting to/from timescale */
122 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
123 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
124
125 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
126 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
127
128 /* timestamp is the DTS */
129 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
130 /* timestamp + offset + cslg_shift is the outgoing PTS */
131 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
132 /* timestamp + offset is the PTS used for internal seek calcuations */
133 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
134 /* timestamp + duration - dts is the duration */
135 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
136
137 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
138
139 /*
140  * Quicktime has tracks and segments. A track is a continuous piece of
141  * multimedia content. The track is not always played from start to finish but
142  * instead, pieces of the track are 'cut out' and played in sequence. This is
143  * what the segments do.
144  *
145  * Inside the track we have keyframes (K) and delta frames. The track has its
146  * own timing, which starts from 0 and extends to end. The position in the track
147  * is called the media_time.
148  *
149  * The segments now describe the pieces that should be played from this track
150  * and are basically tuples of media_time/duration/rate entries. We can have
151  * multiple segments and they are all played after one another. An example:
152  *
153  * segment 1: media_time: 1 second, duration: 1 second, rate 1
154  * segment 2: media_time: 3 second, duration: 2 second, rate 2
155  *
156  * To correctly play back this track, one must play: 1 second of media starting
157  * from media_time 1 followed by 2 seconds of media starting from media_time 3
158  * at a rate of 2.
159  *
160  * Each of the segments will be played at a specific time, the first segment at
161  * time 0, the second one after the duration of the first one, etc.. Note that
162  * the time in resulting playback is not identical to the media_time of the
163  * track anymore.
164  *
165  * Visually, assuming the track has 4 second of media_time:
166  *
167  *                (a)                   (b)          (c)              (d)
168  *         .-----------------------------------------------------------.
169  * track:  | K.....K.........K........K.......K.......K...........K... |
170  *         '-----------------------------------------------------------'
171  *         0              1              2              3              4
172  *           .------------^              ^   .----------^              ^
173  *          /              .-------------'  /       .------------------'
174  *         /              /          .-----'       /
175  *         .--------------.         .--------------.
176  *         | segment 1    |         | segment 2    |
177  *         '--------------'         '--------------'
178  *
179  * The challenge here is to cut out the right pieces of the track for each of
180  * the playback segments. This fortunately can easily be done with the SEGMENT
181  * events of GStreamer.
182  *
183  * For playback of segment 1, we need to provide the decoder with the keyframe
184  * (a), in the above figure, but we must instruct it only to output the decoded
185  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
186  * position set to the time of the segment: 0.
187  *
188  * We then proceed to push data from keyframe (a) to frame (b). The decoder
189  * decodes but clips all before media_time 1.
190  *
191  * After finishing a segment, we push out a new SEGMENT event with the clipping
192  * boundaries of the new data.
193  *
194  * This is a good usecase for the GStreamer accumulated SEGMENT events.
195  */
196
197 struct _QtDemuxSegment
198 {
199   /* global time and duration, all gst time */
200   GstClockTime time;
201   GstClockTime stop_time;
202   GstClockTime duration;
203   /* media time of trak, all gst time */
204   GstClockTime media_start;
205   GstClockTime media_stop;
206   gdouble rate;
207   /* Media start time in trak timescale units */
208   guint32 trak_media_start;
209 };
210
211 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
212
213 /* Used with fragmented MP4 files (mfra atom) */
214 typedef struct
215 {
216   GstClockTime ts;
217   guint64 moof_offset;
218 } QtDemuxRandomAccessEntry;
219
220 typedef struct _QtDemuxStreamStsdEntry
221 {
222   GstCaps *caps;
223   guint32 fourcc;
224   gboolean sparse;
225
226   /* video info */
227   gint width;
228   gint height;
229   gint par_w;
230   gint par_h;
231   /* Numerator/denominator framerate */
232   gint fps_n;
233   gint fps_d;
234   GstVideoColorimetry colorimetry;
235   guint16 bits_per_sample;
236   guint16 color_table_id;
237   GstMemory *rgb8_palette;
238   guint interlace_mode;
239   guint field_order;
240
241   /* audio info */
242   gdouble rate;
243   gint n_channels;
244   guint samples_per_packet;
245   guint samples_per_frame;
246   guint bytes_per_packet;
247   guint bytes_per_sample;
248   guint bytes_per_frame;
249   guint compression;
250
251   /* if we use chunks or samples */
252   gboolean sampled;
253   guint padding;
254
255 } QtDemuxStreamStsdEntry;
256
257 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
258
259 struct _QtDemuxStream
260 {
261   GstPad *pad;
262
263   QtDemuxStreamStsdEntry *stsd_entries;
264   guint stsd_entries_length;
265   guint cur_stsd_entry_index;
266
267   /* stream type */
268   guint32 subtype;
269
270   gboolean new_caps;            /* If TRUE, caps need to be generated (by
271                                  * calling _configure_stream()) This happens
272                                  * for MSS and fragmented streams */
273
274   gboolean new_stream;          /* signals that a stream_start is required */
275   gboolean on_keyframe;         /* if this stream last pushed buffer was a
276                                  * keyframe. This is important to identify
277                                  * where to stop pushing buffers after a
278                                  * segment stop time */
279
280   /* if the stream has a redirect URI in its headers, we store it here */
281   gchar *redirect_uri;
282
283   /* track id */
284   guint track_id;
285
286   /* duration/scale */
287   guint64 duration;             /* in timescale units */
288   guint32 timescale;
289
290   /* language */
291   gchar lang_id[4];             /* ISO 639-2T language code */
292
293   /* our samples */
294   guint32 n_samples;
295   QtDemuxSample *samples;
296   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
297   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
298                                    the framerate */
299   guint32 n_samples_moof;       /* sample count in a moof */
300   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
301                                  * the framerate of fragmented format stream */
302   guint64 duration_last_moof;
303
304   guint32 offset_in_sample;     /* Offset in the current sample, used for
305                                  * streams which have got exceedingly big
306                                  * sample size (such as 24s of raw audio).
307                                  * Only used when max_buffer_size is non-NULL */
308   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
309                                  * Currently only set for raw audio streams*/
310
311   /* video info */
312   /* aspect ratio */
313   gint display_width;
314   gint display_height;
315
316   /* allocation */
317   gboolean use_allocator;
318   GstAllocator *allocator;
319   GstAllocationParams params;
320
321   gsize alignment;
322
323   /* when a discontinuity is pending */
324   gboolean discont;
325
326   /* list of buffers to push first */
327   GSList *buffers;
328
329   /* if we need to clip this buffer. This is only needed for uncompressed
330    * data */
331   gboolean need_clip;
332
333   /* buffer needs some custom processing, e.g. subtitles */
334   gboolean need_process;
335
336   /* current position */
337   guint32 segment_index;
338   guint32 sample_index;
339   GstClockTime time_position;   /* in gst time */
340   guint64 accumulated_base;
341
342   /* the Gst segment we are processing out, used for clipping */
343   GstSegment segment;
344
345   /* quicktime segments */
346   guint32 n_segments;
347   QtDemuxSegment *segments;
348   gboolean dummy_segment;
349   guint32 from_sample;
350   guint32 to_sample;
351
352   gboolean sent_eos;
353   GstTagList *stream_tags;
354   gboolean send_global_tags;
355
356   GstEvent *pending_event;
357
358   GstByteReader stco;
359   GstByteReader stsz;
360   GstByteReader stsc;
361   GstByteReader stts;
362   GstByteReader stss;
363   GstByteReader stps;
364   GstByteReader ctts;
365
366   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
367   gint64 stbl_index;
368   /* stco */
369   guint co_size;
370   GstByteReader co_chunk;
371   guint32 first_chunk;
372   guint32 current_chunk;
373   guint32 last_chunk;
374   guint32 samples_per_chunk;
375   guint32 stsd_sample_description_id;
376   guint32 stco_sample_index;
377   /* stsz */
378   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
379   /* stsc */
380   guint32 stsc_index;
381   guint32 n_samples_per_chunk;
382   guint32 stsc_chunk_index;
383   guint32 stsc_sample_index;
384   guint64 chunk_offset;
385   /* stts */
386   guint32 stts_index;
387   guint32 stts_samples;
388   guint32 n_sample_times;
389   guint32 stts_sample_index;
390   guint64 stts_time;
391   guint32 stts_duration;
392   /* stss */
393   gboolean stss_present;
394   guint32 n_sample_syncs;
395   guint32 stss_index;
396   /* stps */
397   gboolean stps_present;
398   guint32 n_sample_partial_syncs;
399   guint32 stps_index;
400   QtDemuxRandomAccessEntry *ra_entries;
401   guint n_ra_entries;
402
403   const QtDemuxRandomAccessEntry *pending_seek;
404
405   /* ctts */
406   gboolean ctts_present;
407   guint32 n_composition_times;
408   guint32 ctts_index;
409   guint32 ctts_sample_index;
410   guint32 ctts_count;
411   gint32 ctts_soffset;
412
413   /* cslg */
414   guint32 cslg_shift;
415
416   /* fragmented */
417   gboolean parsed_trex;
418   guint32 def_sample_description_index; /* index is 1-based */
419   guint32 def_sample_duration;
420   guint32 def_sample_size;
421   guint32 def_sample_flags;
422
423   gboolean disabled;
424
425   /* stereoscopic video streams */
426   GstVideoMultiviewMode multiview_mode;
427   GstVideoMultiviewFlags multiview_flags;
428
429   /* protected streams */
430   gboolean protected;
431   guint32 protection_scheme_type;
432   guint32 protection_scheme_version;
433   gpointer protection_scheme_info;      /* specific to the protection scheme */
434   GQueue protection_scheme_event_queue;
435 };
436
437 /* Contains properties and cryptographic info for a set of samples from a
438  * track protected using Common Encryption (cenc) */
439 struct _QtDemuxCencSampleSetInfo
440 {
441   GstStructure *default_properties;
442
443   /* @crypto_info holds one GstStructure per sample */
444   GPtrArray *crypto_info;
445 };
446
447 static const gchar *
448 qt_demux_state_string (enum QtDemuxState state)
449 {
450   switch (state) {
451     case QTDEMUX_STATE_INITIAL:
452       return "<INITIAL>";
453     case QTDEMUX_STATE_HEADER:
454       return "<HEADER>";
455     case QTDEMUX_STATE_MOVIE:
456       return "<MOVIE>";
457     case QTDEMUX_STATE_BUFFER_MDAT:
458       return "<BUFFER_MDAT>";
459     default:
460       return "<UNKNOWN>";
461   }
462 }
463
464 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
465 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
466     guint32 fourcc, GstByteReader * parser);
467 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
468 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
469     guint32 fourcc, GstByteReader * parser);
470
471 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
472
473 static GstStaticPadTemplate gst_qtdemux_sink_template =
474     GST_STATIC_PAD_TEMPLATE ("sink",
475     GST_PAD_SINK,
476     GST_PAD_ALWAYS,
477     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
478         "application/x-3gp")
479     );
480
481 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
482 GST_STATIC_PAD_TEMPLATE ("video_%u",
483     GST_PAD_SRC,
484     GST_PAD_SOMETIMES,
485     GST_STATIC_CAPS_ANY);
486
487 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
488 GST_STATIC_PAD_TEMPLATE ("audio_%u",
489     GST_PAD_SRC,
490     GST_PAD_SOMETIMES,
491     GST_STATIC_CAPS_ANY);
492
493 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
494 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
495     GST_PAD_SRC,
496     GST_PAD_SOMETIMES,
497     GST_STATIC_CAPS_ANY);
498
499 #define gst_qtdemux_parent_class parent_class
500 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
501
502 static void gst_qtdemux_dispose (GObject * object);
503
504 static guint32
505 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
506     GstClockTime media_time);
507 static guint32
508 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
509     QtDemuxStream * str, gint64 media_offset);
510
511 #if 0
512 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
513 static GstIndex *gst_qtdemux_get_index (GstElement * element);
514 #endif
515 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
516     GstStateChange transition);
517 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
518 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
519     GstObject * parent, GstPadMode mode, gboolean active);
520
521 static void gst_qtdemux_loop (GstPad * pad);
522 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
523     GstBuffer * inbuf);
524 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
525     GstEvent * event);
526 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
527 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
528     QtDemuxStream * stream);
529 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
530     QtDemuxStream * stream);
531 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
532     gboolean force);
533
534 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
535     const guint8 * buffer, guint length);
536 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
537     const guint8 * buffer, guint length);
538 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
539 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
540     GNode * udta);
541
542 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
543     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
544     GstTagList * list);
545 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
546     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
547     const guint8 * stsd_entry_data, gchar ** codec_name);
548 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
549     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
550     const guint8 * data, int len, gchar ** codec_name);
551 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
552     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
553     gchar ** codec_name);
554 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
555     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
556     const guint8 * stsd_entry_data, gchar ** codec_name);
557
558 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
559     QtDemuxStream * stream, guint32 n);
560 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
561 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
562     QtDemuxStream * stream);
563 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
564     QtDemuxStream * stream);
565 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
566 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
567 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
568     QtDemuxStream * stream);
569 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
570     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
571 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
572     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
573     GstClockTime * _start, GstClockTime * _stop);
574 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
575     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
576
577 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
578 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
579
580 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
581
582 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
583     QtDemuxStream * stream, guint sample_index);
584 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
585     const gchar * id);
586 static void qtdemux_gst_structure_free (GstStructure * gststructure);
587
588 static void
589 gst_qtdemux_class_init (GstQTDemuxClass * klass)
590 {
591   GObjectClass *gobject_class;
592   GstElementClass *gstelement_class;
593
594   gobject_class = (GObjectClass *) klass;
595   gstelement_class = (GstElementClass *) klass;
596
597   parent_class = g_type_class_peek_parent (klass);
598
599   gobject_class->dispose = gst_qtdemux_dispose;
600
601   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
602 #if 0
603   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
604   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
605 #endif
606
607   gst_tag_register_musicbrainz_tags ();
608
609   gst_element_class_add_static_pad_template (gstelement_class,
610       &gst_qtdemux_sink_template);
611   gst_element_class_add_static_pad_template (gstelement_class,
612       &gst_qtdemux_videosrc_template);
613   gst_element_class_add_static_pad_template (gstelement_class,
614       &gst_qtdemux_audiosrc_template);
615   gst_element_class_add_static_pad_template (gstelement_class,
616       &gst_qtdemux_subsrc_template);
617   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
618       "Codec/Demuxer",
619       "Demultiplex a QuickTime file into audio and video streams",
620       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
621
622   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
623
624 }
625
626 static void
627 gst_qtdemux_init (GstQTDemux * qtdemux)
628 {
629   qtdemux->sinkpad =
630       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
631   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
632   gst_pad_set_activatemode_function (qtdemux->sinkpad,
633       qtdemux_sink_activate_mode);
634   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
635   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
636   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
637
638   qtdemux->state = QTDEMUX_STATE_INITIAL;
639   qtdemux->pullbased = FALSE;
640   qtdemux->posted_redirect = FALSE;
641   qtdemux->neededbytes = 16;
642   qtdemux->todrop = 0;
643   qtdemux->adapter = gst_adapter_new ();
644   qtdemux->offset = 0;
645   qtdemux->first_mdat = -1;
646   qtdemux->got_moov = FALSE;
647   qtdemux->mdatoffset = -1;
648   qtdemux->mdatbuffer = NULL;
649   qtdemux->restoredata_buffer = NULL;
650   qtdemux->restoredata_offset = -1;
651   qtdemux->fragment_start = -1;
652   qtdemux->fragment_start_offset = -1;
653   qtdemux->media_caps = NULL;
654   qtdemux->exposed = FALSE;
655   qtdemux->mss_mode = FALSE;
656   qtdemux->pending_newsegment = NULL;
657   qtdemux->upstream_format_is_time = FALSE;
658   qtdemux->have_group_id = FALSE;
659   qtdemux->group_id = G_MAXUINT;
660   qtdemux->cenc_aux_info_offset = 0;
661   qtdemux->cenc_aux_info_sizes = NULL;
662   qtdemux->cenc_aux_sample_count = 0;
663   qtdemux->protection_system_ids = NULL;
664   g_queue_init (&qtdemux->protection_event_queue);
665   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
666   qtdemux->tag_list = gst_tag_list_new_empty ();
667   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
668   qtdemux->flowcombiner = gst_flow_combiner_new ();
669
670   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
671 }
672
673 static void
674 gst_qtdemux_dispose (GObject * object)
675 {
676   GstQTDemux *qtdemux = GST_QTDEMUX (object);
677
678   if (qtdemux->adapter) {
679     g_object_unref (G_OBJECT (qtdemux->adapter));
680     qtdemux->adapter = NULL;
681   }
682   gst_tag_list_unref (qtdemux->tag_list);
683   gst_flow_combiner_free (qtdemux->flowcombiner);
684   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
685       NULL);
686   g_queue_clear (&qtdemux->protection_event_queue);
687
688   g_free (qtdemux->cenc_aux_info_sizes);
689   qtdemux->cenc_aux_info_sizes = NULL;
690
691   G_OBJECT_CLASS (parent_class)->dispose (object);
692 }
693
694 static void
695 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
696 {
697   if (qtdemux->posted_redirect) {
698     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
699         (_("This file contains no playable streams.")),
700         ("no known streams found, a redirect message has been posted"));
701   } else {
702     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
703         (_("This file contains no playable streams.")),
704         ("no known streams found"));
705   }
706 }
707
708 static GstBuffer *
709 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
710 {
711   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
712       mem, size, 0, size, mem, free_func);
713 }
714
715 static GstFlowReturn
716 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
717     GstBuffer ** buf)
718 {
719   GstFlowReturn flow;
720   GstMapInfo map;
721   gsize bsize;
722
723   if (G_UNLIKELY (size == 0)) {
724     GstFlowReturn ret;
725     GstBuffer *tmp = NULL;
726
727     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
728     if (ret != GST_FLOW_OK)
729       return ret;
730
731     gst_buffer_map (tmp, &map, GST_MAP_READ);
732     size = QT_UINT32 (map.data);
733     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
734
735     gst_buffer_unmap (tmp, &map);
736     gst_buffer_unref (tmp);
737   }
738
739   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
740   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
741     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
742       /* we're pulling header but already got most interesting bits,
743        * so never mind the rest (e.g. tags) (that much) */
744       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
745           size);
746       return GST_FLOW_EOS;
747     } else {
748       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
749           (_("This file is invalid and cannot be played.")),
750           ("atom has bogus size %" G_GUINT64_FORMAT, size));
751       return GST_FLOW_ERROR;
752     }
753   }
754
755   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
756
757   if (G_UNLIKELY (flow != GST_FLOW_OK))
758     return flow;
759
760   bsize = gst_buffer_get_size (*buf);
761   /* Catch short reads - we don't want any partial atoms */
762   if (G_UNLIKELY (bsize < size)) {
763     GST_WARNING_OBJECT (qtdemux,
764         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
765     gst_buffer_unref (*buf);
766     *buf = NULL;
767     return GST_FLOW_EOS;
768   }
769
770   return flow;
771 }
772
773 #if 1
774 static gboolean
775 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
776     GstFormat src_format, gint64 src_value, GstFormat dest_format,
777     gint64 * dest_value)
778 {
779   gboolean res = TRUE;
780   QtDemuxStream *stream = gst_pad_get_element_private (pad);
781   gint32 index;
782
783   if (stream->subtype != FOURCC_vide) {
784     res = FALSE;
785     goto done;
786   }
787
788   switch (src_format) {
789     case GST_FORMAT_TIME:
790       switch (dest_format) {
791         case GST_FORMAT_BYTES:{
792           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
793           if (-1 == index) {
794             res = FALSE;
795             goto done;
796           }
797
798           *dest_value = stream->samples[index].offset;
799
800           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
801               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
802               GST_TIME_ARGS (src_value), *dest_value);
803           break;
804         }
805         default:
806           res = FALSE;
807           break;
808       }
809       break;
810     case GST_FORMAT_BYTES:
811       switch (dest_format) {
812         case GST_FORMAT_TIME:{
813           index =
814               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
815               stream, src_value);
816
817           if (-1 == index) {
818             res = FALSE;
819             goto done;
820           }
821
822           *dest_value =
823               QTSTREAMTIME_TO_GSTTIME (stream,
824               stream->samples[index].timestamp);
825           GST_DEBUG_OBJECT (qtdemux,
826               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
827               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
828           break;
829         }
830         default:
831           res = FALSE;
832           break;
833       }
834       break;
835     default:
836       res = FALSE;
837       break;
838   }
839
840 done:
841   return res;
842 }
843 #endif
844
845 static gboolean
846 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
847 {
848   gboolean res = FALSE;
849
850   *duration = GST_CLOCK_TIME_NONE;
851
852   if (qtdemux->duration != 0 &&
853       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
854     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
855     res = TRUE;
856   } else {
857     *duration = GST_CLOCK_TIME_NONE;
858   }
859
860   return res;
861 }
862
863 static gboolean
864 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
865     GstQuery * query)
866 {
867   gboolean res = FALSE;
868   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
869
870   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
871
872   switch (GST_QUERY_TYPE (query)) {
873     case GST_QUERY_POSITION:{
874       GstFormat fmt;
875
876       gst_query_parse_position (query, &fmt, NULL);
877       if (fmt == GST_FORMAT_TIME
878           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
879         gst_query_set_position (query, GST_FORMAT_TIME,
880             qtdemux->segment.position);
881         res = TRUE;
882       }
883     }
884       break;
885     case GST_QUERY_DURATION:{
886       GstFormat fmt;
887
888       gst_query_parse_duration (query, &fmt, NULL);
889       if (fmt == GST_FORMAT_TIME) {
890         /* First try to query upstream */
891         res = gst_pad_query_default (pad, parent, query);
892         if (!res) {
893           GstClockTime duration;
894           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
895             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
896             res = TRUE;
897           }
898         }
899       }
900       break;
901     }
902     case GST_QUERY_CONVERT:{
903       GstFormat src_fmt, dest_fmt;
904       gint64 src_value, dest_value = 0;
905
906       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
907
908       res = gst_qtdemux_src_convert (qtdemux, pad,
909           src_fmt, src_value, dest_fmt, &dest_value);
910       if (res)
911         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
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 = GST_SEQNUM_INVALID;
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 != GST_SEQNUM_INVALID)
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 != GST_SEQNUM_INVALID)
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 != GST_SEQNUM_INVALID)
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 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1828  *
1829  * If @fw is false, the coding order is explored backwards.
1830  *
1831  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1832  * sample is found for that track.
1833  *
1834  * The stream and sample index of the sample with the minimum offset in the direction explored
1835  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1836  *
1837  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1838  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1839  * @_stream and @_index. */
1840 static void
1841 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1842     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1843 {
1844   gint i, n, index;
1845   gint64 time, min_time;
1846   QtDemuxStream *stream;
1847
1848   min_time = -1;
1849   stream = NULL;
1850   index = -1;
1851
1852   for (n = 0; n < qtdemux->n_streams; ++n) {
1853     QtDemuxStream *str;
1854     gint inc;
1855     gboolean set_sample;
1856
1857     str = qtdemux->streams[n];
1858     set_sample = !set;
1859
1860     if (fw) {
1861       i = 0;
1862       inc = 1;
1863     } else {
1864       i = str->n_samples - 1;
1865       inc = -1;
1866     }
1867
1868     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1869       if (str->samples[i].size == 0)
1870         continue;
1871
1872       if (fw && (str->samples[i].offset < byte_pos))
1873         continue;
1874
1875       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1876         continue;
1877
1878       /* move stream to first available sample */
1879       if (set) {
1880         gst_qtdemux_move_stream (qtdemux, str, i);
1881         set_sample = TRUE;
1882       }
1883
1884       /* avoid index from sparse streams since they might be far away */
1885       if (!CUR_STREAM (str)->sparse) {
1886         /* determine min/max time */
1887         time = QTSAMPLE_PTS (str, &str->samples[i]);
1888         if (min_time == -1 || (!fw && time > min_time) ||
1889             (fw && time < min_time)) {
1890           min_time = time;
1891         }
1892
1893         /* determine stream with leading sample, to get its position */
1894         if (!stream ||
1895             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1896             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1897           stream = str;
1898           index = i;
1899         }
1900       }
1901       break;
1902     }
1903
1904     /* no sample for this stream, mark eos */
1905     if (!set_sample)
1906       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1907   }
1908
1909   if (_time)
1910     *_time = min_time;
1911   if (_stream)
1912     *_stream = stream;
1913   if (_index)
1914     *_index = index;
1915 }
1916
1917 static QtDemuxStream *
1918 _create_stream (void)
1919 {
1920   QtDemuxStream *stream;
1921
1922   stream = g_new0 (QtDemuxStream, 1);
1923   /* new streams always need a discont */
1924   stream->discont = TRUE;
1925   /* we enable clipping for raw audio/video streams */
1926   stream->need_clip = FALSE;
1927   stream->need_process = FALSE;
1928   stream->segment_index = -1;
1929   stream->time_position = 0;
1930   stream->sample_index = -1;
1931   stream->offset_in_sample = 0;
1932   stream->new_stream = TRUE;
1933   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1934   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1935   stream->protected = FALSE;
1936   stream->protection_scheme_type = 0;
1937   stream->protection_scheme_version = 0;
1938   stream->protection_scheme_info = NULL;
1939   stream->n_samples_moof = 0;
1940   stream->duration_moof = 0;
1941   stream->duration_last_moof = 0;
1942   stream->alignment = 1;
1943   stream->stream_tags = gst_tag_list_new_empty ();
1944   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1945   g_queue_init (&stream->protection_scheme_event_queue);
1946   return stream;
1947 }
1948
1949 static gboolean
1950 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1951 {
1952   GstStructure *structure;
1953   const gchar *variant;
1954   const GstCaps *mediacaps = NULL;
1955
1956   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1957
1958   structure = gst_caps_get_structure (caps, 0);
1959   variant = gst_structure_get_string (structure, "variant");
1960
1961   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1962     QtDemuxStream *stream;
1963     const GValue *value;
1964
1965     demux->fragmented = TRUE;
1966     demux->mss_mode = TRUE;
1967
1968     if (demux->n_streams > 1) {
1969       /* can't do this, we can only renegotiate for another mss format */
1970       return FALSE;
1971     }
1972
1973     value = gst_structure_get_value (structure, "media-caps");
1974     /* create stream */
1975     if (value) {
1976       const GValue *timescale_v;
1977
1978       /* TODO update when stream changes during playback */
1979
1980       if (demux->n_streams == 0) {
1981         stream = _create_stream ();
1982         demux->streams[demux->n_streams] = stream;
1983         demux->n_streams = 1;
1984         /* mss has no stsd/stsd entry, use id 0 as default */
1985         stream->stsd_entries_length = 1;
1986         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1987         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1988       } else {
1989         stream = demux->streams[0];
1990       }
1991
1992       timescale_v = gst_structure_get_value (structure, "timescale");
1993       if (timescale_v) {
1994         stream->timescale = g_value_get_uint64 (timescale_v);
1995       } else {
1996         /* default mss timescale */
1997         stream->timescale = 10000000;
1998       }
1999       demux->timescale = stream->timescale;
2000
2001       mediacaps = gst_value_get_caps (value);
2002       if (!CUR_STREAM (stream)->caps
2003           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2004         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2005             mediacaps);
2006         stream->new_caps = TRUE;
2007       }
2008       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2009       structure = gst_caps_get_structure (mediacaps, 0);
2010       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2011         stream->subtype = FOURCC_vide;
2012
2013         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2014         gst_structure_get_int (structure, "height",
2015             &CUR_STREAM (stream)->height);
2016         gst_structure_get_fraction (structure, "framerate",
2017             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2018       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2019         gint rate = 0;
2020         stream->subtype = FOURCC_soun;
2021         gst_structure_get_int (structure, "channels",
2022             &CUR_STREAM (stream)->n_channels);
2023         gst_structure_get_int (structure, "rate", &rate);
2024         CUR_STREAM (stream)->rate = rate;
2025       }
2026     }
2027     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2028   } else {
2029     demux->mss_mode = FALSE;
2030   }
2031
2032   return TRUE;
2033 }
2034
2035 static void
2036 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2037 {
2038   gint n;
2039
2040   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2041   gst_pad_stop_task (qtdemux->sinkpad);
2042
2043   if (hard || qtdemux->upstream_format_is_time) {
2044     qtdemux->state = QTDEMUX_STATE_INITIAL;
2045     qtdemux->neededbytes = 16;
2046     qtdemux->todrop = 0;
2047     qtdemux->pullbased = FALSE;
2048     qtdemux->posted_redirect = FALSE;
2049     qtdemux->first_mdat = -1;
2050     qtdemux->header_size = 0;
2051     qtdemux->mdatoffset = -1;
2052     qtdemux->restoredata_offset = -1;
2053     if (qtdemux->mdatbuffer)
2054       gst_buffer_unref (qtdemux->mdatbuffer);
2055     if (qtdemux->restoredata_buffer)
2056       gst_buffer_unref (qtdemux->restoredata_buffer);
2057     qtdemux->mdatbuffer = NULL;
2058     qtdemux->restoredata_buffer = NULL;
2059     qtdemux->mdatleft = 0;
2060     qtdemux->mdatsize = 0;
2061     if (qtdemux->comp_brands)
2062       gst_buffer_unref (qtdemux->comp_brands);
2063     qtdemux->comp_brands = NULL;
2064     qtdemux->last_moov_offset = -1;
2065     if (qtdemux->moov_node_compressed) {
2066       g_node_destroy (qtdemux->moov_node_compressed);
2067       if (qtdemux->moov_node)
2068         g_free (qtdemux->moov_node->data);
2069     }
2070     qtdemux->moov_node_compressed = NULL;
2071     if (qtdemux->moov_node)
2072       g_node_destroy (qtdemux->moov_node);
2073     qtdemux->moov_node = NULL;
2074     if (qtdemux->tag_list)
2075       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2076     qtdemux->tag_list = gst_tag_list_new_empty ();
2077     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2078 #if 0
2079     if (qtdemux->element_index)
2080       gst_object_unref (qtdemux->element_index);
2081     qtdemux->element_index = NULL;
2082 #endif
2083     qtdemux->major_brand = 0;
2084     if (qtdemux->pending_newsegment)
2085       gst_event_unref (qtdemux->pending_newsegment);
2086     qtdemux->pending_newsegment = NULL;
2087     qtdemux->upstream_format_is_time = FALSE;
2088     qtdemux->upstream_seekable = FALSE;
2089     qtdemux->upstream_size = 0;
2090
2091     qtdemux->fragment_start = -1;
2092     qtdemux->fragment_start_offset = -1;
2093     qtdemux->duration = 0;
2094     qtdemux->moof_offset = 0;
2095     qtdemux->chapters_track_id = 0;
2096     qtdemux->have_group_id = FALSE;
2097     qtdemux->group_id = G_MAXUINT;
2098
2099     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2100         NULL);
2101     g_queue_clear (&qtdemux->protection_event_queue);
2102   }
2103   qtdemux->offset = 0;
2104   gst_adapter_clear (qtdemux->adapter);
2105   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2106   qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2107
2108   if (hard) {
2109     for (n = 0; n < qtdemux->n_streams; n++) {
2110       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2111       qtdemux->streams[n] = NULL;
2112     }
2113     qtdemux->n_streams = 0;
2114     qtdemux->n_video_streams = 0;
2115     qtdemux->n_audio_streams = 0;
2116     qtdemux->n_sub_streams = 0;
2117     qtdemux->exposed = FALSE;
2118     qtdemux->fragmented = FALSE;
2119     qtdemux->mss_mode = FALSE;
2120     gst_caps_replace (&qtdemux->media_caps, NULL);
2121     qtdemux->timescale = 0;
2122     qtdemux->got_moov = FALSE;
2123     if (qtdemux->protection_system_ids) {
2124       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2125       qtdemux->protection_system_ids = NULL;
2126     }
2127   } else if (qtdemux->mss_mode) {
2128     gst_flow_combiner_reset (qtdemux->flowcombiner);
2129     for (n = 0; n < qtdemux->n_streams; n++)
2130       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2131   } else {
2132     gst_flow_combiner_reset (qtdemux->flowcombiner);
2133     for (n = 0; n < qtdemux->n_streams; n++) {
2134       qtdemux->streams[n]->sent_eos = FALSE;
2135       qtdemux->streams[n]->time_position = 0;
2136       qtdemux->streams[n]->accumulated_base = 0;
2137     }
2138     if (!qtdemux->pending_newsegment) {
2139       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2140       if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
2141         gst_event_set_seqnum (qtdemux->pending_newsegment,
2142             qtdemux->segment_seqnum);
2143     }
2144   }
2145 }
2146
2147
2148 /* Maps the @segment to the qt edts internal segments and pushes
2149  * the correspnding segment event.
2150  *
2151  * If it ends up being at a empty segment, a gap will be pushed and the next
2152  * edts segment will be activated in sequence.
2153  *
2154  * To be used in push-mode only */
2155 static void
2156 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2157 {
2158   gint n, i;
2159
2160   for (n = 0; n < qtdemux->n_streams; n++) {
2161     QtDemuxStream *stream = qtdemux->streams[n];
2162
2163     stream->time_position = segment->start;
2164
2165     /* in push mode we should be guaranteed that we will have empty segments
2166      * at the beginning and then one segment after, other scenarios are not
2167      * supported and are discarded when parsing the edts */
2168     for (i = 0; i < stream->n_segments; i++) {
2169       if (stream->segments[i].stop_time > segment->start) {
2170         gst_qtdemux_activate_segment (qtdemux, stream, i,
2171             stream->time_position);
2172         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2173           /* push the empty segment and move to the next one */
2174           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2175               stream->time_position);
2176           continue;
2177         }
2178
2179         g_assert (i == stream->n_segments - 1);
2180       }
2181     }
2182   }
2183 }
2184
2185 static gboolean
2186 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2187     GstEvent * event)
2188 {
2189   GstQTDemux *demux = GST_QTDEMUX (parent);
2190   gboolean res = TRUE;
2191
2192   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2193
2194   switch (GST_EVENT_TYPE (event)) {
2195     case GST_EVENT_SEGMENT:
2196     {
2197       gint64 offset = 0;
2198       QtDemuxStream *stream;
2199       gint idx;
2200       GstSegment segment;
2201
2202       /* some debug output */
2203       gst_event_copy_segment (event, &segment);
2204       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2205           &segment);
2206
2207       /* erase any previously set segment */
2208       gst_event_replace (&demux->pending_newsegment, NULL);
2209
2210       if (segment.format == GST_FORMAT_TIME) {
2211         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2212         gst_event_replace (&demux->pending_newsegment, event);
2213         demux->upstream_format_is_time = TRUE;
2214       } else {
2215         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2216             "not in time format");
2217
2218         /* chain will send initial newsegment after pads have been added */
2219         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2220           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2221           goto exit;
2222         }
2223       }
2224
2225       /* check if this matches a time seek we received previously
2226        * FIXME for backwards compatibility reasons we use the
2227        * seek_offset here to compare. In the future we might want to
2228        * change this to use the seqnum as it uniquely should identify
2229        * the segment that corresponds to the seek. */
2230       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2231           ", received segment offset %" G_GINT64_FORMAT,
2232           demux->seek_offset, segment.start);
2233       if (segment.format == GST_FORMAT_BYTES
2234           && demux->seek_offset == segment.start) {
2235         GST_OBJECT_LOCK (demux);
2236         offset = segment.start;
2237
2238         segment.format = GST_FORMAT_TIME;
2239         segment.start = demux->push_seek_start;
2240         segment.stop = demux->push_seek_stop;
2241         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2242             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2243             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2244         GST_OBJECT_UNLOCK (demux);
2245       }
2246
2247       /* we only expect a BYTE segment, e.g. following a seek */
2248       if (segment.format == GST_FORMAT_BYTES) {
2249         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2250           offset = segment.start;
2251
2252           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2253               NULL, (gint64 *) & segment.start);
2254           if ((gint64) segment.start < 0)
2255             segment.start = 0;
2256         }
2257         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2258           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2259               NULL, (gint64 *) & segment.stop);
2260           /* keyframe seeking should already arrange for start >= stop,
2261            * but make sure in other rare cases */
2262           segment.stop = MAX (segment.stop, segment.start);
2263         }
2264       } else if (segment.format == GST_FORMAT_TIME) {
2265         /* push all data on the adapter before starting this
2266          * new segment */
2267         gst_qtdemux_process_adapter (demux, TRUE);
2268       } else {
2269         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2270         goto exit;
2271       }
2272
2273       /* We shouldn't modify upstream driven TIME FORMAT segment */
2274       if (!demux->upstream_format_is_time) {
2275         /* accept upstream's notion of segment and distribute along */
2276         segment.format = GST_FORMAT_TIME;
2277         segment.position = segment.time = segment.start;
2278         segment.duration = demux->segment.duration;
2279         segment.base = gst_segment_to_running_time (&demux->segment,
2280             GST_FORMAT_TIME, demux->segment.position);
2281       }
2282
2283       gst_segment_copy_into (&segment, &demux->segment);
2284       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2285
2286       /* map segment to internal qt segments and push on each stream */
2287       if (demux->n_streams) {
2288         if (demux->fragmented) {
2289           GstEvent *segment_event = gst_event_new_segment (&segment);
2290
2291           gst_event_replace (&demux->pending_newsegment, NULL);
2292           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2293           gst_qtdemux_push_event (demux, segment_event);
2294         } else {
2295           gst_event_replace (&demux->pending_newsegment, NULL);
2296           gst_qtdemux_map_and_push_segments (demux, &segment);
2297         }
2298       }
2299
2300       /* clear leftover in current segment, if any */
2301       gst_adapter_clear (demux->adapter);
2302
2303       /* set up streaming thread */
2304       demux->offset = offset;
2305       if (demux->upstream_format_is_time) {
2306         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2307             "set values to restart reading from a new atom");
2308         demux->neededbytes = 16;
2309         demux->todrop = 0;
2310       } else {
2311         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2312             NULL);
2313         if (stream) {
2314           demux->todrop = stream->samples[idx].offset - offset;
2315           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2316         } else {
2317           /* set up for EOS */
2318           demux->neededbytes = -1;
2319           demux->todrop = 0;
2320         }
2321       }
2322     exit:
2323       gst_event_unref (event);
2324       res = TRUE;
2325       goto drop;
2326     }
2327     case GST_EVENT_FLUSH_START:
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_FLUSH_STOP:
2336     {
2337       guint64 dur;
2338
2339       dur = demux->segment.duration;
2340       gst_qtdemux_reset (demux, FALSE);
2341       demux->segment.duration = dur;
2342
2343       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2344         gst_event_unref (event);
2345         goto drop;
2346       }
2347       break;
2348     }
2349     case GST_EVENT_EOS:
2350       /* If we are in push mode, and get an EOS before we've seen any streams,
2351        * then error out - we have nowhere to send the EOS */
2352       if (!demux->pullbased) {
2353         gint i;
2354         gboolean has_valid_stream = FALSE;
2355         for (i = 0; i < demux->n_streams; i++) {
2356           if (demux->streams[i]->pad != NULL) {
2357             has_valid_stream = TRUE;
2358             break;
2359           }
2360         }
2361         if (!has_valid_stream)
2362           gst_qtdemux_post_no_playable_stream_error (demux);
2363         else {
2364           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2365               (guint) gst_adapter_available (demux->adapter));
2366           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2367             res = FALSE;
2368           }
2369         }
2370       }
2371       break;
2372     case GST_EVENT_CAPS:{
2373       GstCaps *caps = NULL;
2374
2375       gst_event_parse_caps (event, &caps);
2376       gst_qtdemux_setcaps (demux, caps);
2377       res = TRUE;
2378       gst_event_unref (event);
2379       goto drop;
2380     }
2381     case GST_EVENT_PROTECTION:
2382     {
2383       const gchar *system_id = NULL;
2384
2385       gst_event_parse_protection (event, &system_id, NULL, NULL);
2386       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2387           system_id);
2388       gst_qtdemux_append_protection_system_id (demux, system_id);
2389       /* save the event for later, for source pads that have not been created */
2390       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2391       /* send it to all pads that already exist */
2392       gst_qtdemux_push_event (demux, event);
2393       res = TRUE;
2394       goto drop;
2395     }
2396     default:
2397       break;
2398   }
2399
2400   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2401
2402 drop:
2403   return res;
2404 }
2405
2406 #if 0
2407 static void
2408 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2409 {
2410   GstQTDemux *demux = GST_QTDEMUX (element);
2411
2412   GST_OBJECT_LOCK (demux);
2413   if (demux->element_index)
2414     gst_object_unref (demux->element_index);
2415   if (index) {
2416     demux->element_index = gst_object_ref (index);
2417   } else {
2418     demux->element_index = NULL;
2419   }
2420   GST_OBJECT_UNLOCK (demux);
2421   /* object lock might be taken again */
2422   if (index)
2423     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2424   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2425       demux->element_index, demux->index_id);
2426 }
2427
2428 static GstIndex *
2429 gst_qtdemux_get_index (GstElement * element)
2430 {
2431   GstIndex *result = NULL;
2432   GstQTDemux *demux = GST_QTDEMUX (element);
2433
2434   GST_OBJECT_LOCK (demux);
2435   if (demux->element_index)
2436     result = gst_object_ref (demux->element_index);
2437   GST_OBJECT_UNLOCK (demux);
2438
2439   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2440
2441   return result;
2442 }
2443 #endif
2444
2445 static void
2446 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2447 {
2448   g_free ((gpointer) stream->stco.data);
2449   stream->stco.data = NULL;
2450   g_free ((gpointer) stream->stsz.data);
2451   stream->stsz.data = NULL;
2452   g_free ((gpointer) stream->stsc.data);
2453   stream->stsc.data = NULL;
2454   g_free ((gpointer) stream->stts.data);
2455   stream->stts.data = NULL;
2456   g_free ((gpointer) stream->stss.data);
2457   stream->stss.data = NULL;
2458   g_free ((gpointer) stream->stps.data);
2459   stream->stps.data = NULL;
2460   g_free ((gpointer) stream->ctts.data);
2461   stream->ctts.data = NULL;
2462 }
2463
2464 static void
2465 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2466     QtDemuxStream * stream)
2467 {
2468   g_free (stream->segments);
2469   stream->segments = NULL;
2470   stream->segment_index = -1;
2471   stream->accumulated_base = 0;
2472 }
2473
2474 static void
2475 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2476     QtDemuxStream * stream)
2477 {
2478   g_free (stream->samples);
2479   stream->samples = NULL;
2480   gst_qtdemux_stbl_free (stream);
2481
2482   /* fragments */
2483   g_free (stream->ra_entries);
2484   stream->ra_entries = NULL;
2485   stream->n_ra_entries = 0;
2486
2487   stream->sample_index = -1;
2488   stream->stbl_index = -1;
2489   stream->n_samples = 0;
2490   stream->time_position = 0;
2491
2492   stream->n_samples_moof = 0;
2493   stream->duration_moof = 0;
2494   stream->duration_last_moof = 0;
2495 }
2496
2497 static void
2498 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2499 {
2500   gint i;
2501   if (stream->allocator)
2502     gst_object_unref (stream->allocator);
2503   while (stream->buffers) {
2504     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2505     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2506   }
2507   for (i = 0; i < stream->stsd_entries_length; i++) {
2508     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2509     if (entry->rgb8_palette) {
2510       gst_memory_unref (entry->rgb8_palette);
2511       entry->rgb8_palette = NULL;
2512     }
2513     entry->sparse = FALSE;
2514   }
2515
2516   gst_tag_list_unref (stream->stream_tags);
2517   stream->stream_tags = gst_tag_list_new_empty ();
2518   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2519   g_free (stream->redirect_uri);
2520   stream->redirect_uri = NULL;
2521   stream->sent_eos = FALSE;
2522   stream->protected = FALSE;
2523   if (stream->protection_scheme_info) {
2524     if (stream->protection_scheme_type == FOURCC_cenc) {
2525       QtDemuxCencSampleSetInfo *info =
2526           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2527       if (info->default_properties)
2528         gst_structure_free (info->default_properties);
2529       if (info->crypto_info)
2530         g_ptr_array_free (info->crypto_info, TRUE);
2531     }
2532     g_free (stream->protection_scheme_info);
2533     stream->protection_scheme_info = NULL;
2534   }
2535   stream->protection_scheme_type = 0;
2536   stream->protection_scheme_version = 0;
2537   g_queue_foreach (&stream->protection_scheme_event_queue,
2538       (GFunc) gst_event_unref, NULL);
2539   g_queue_clear (&stream->protection_scheme_event_queue);
2540   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2541   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2542 }
2543
2544 static void
2545 gst_qtdemux_stream_reset (GstQTDemux * qtdemux, QtDemuxStream * stream)
2546 {
2547   gint i;
2548   gst_qtdemux_stream_clear (qtdemux, stream);
2549   for (i = 0; i < stream->stsd_entries_length; i++) {
2550     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2551     if (entry->caps) {
2552       gst_caps_unref (entry->caps);
2553       entry->caps = NULL;
2554     }
2555   }
2556   g_free (stream->stsd_entries);
2557   stream->stsd_entries = NULL;
2558   stream->stsd_entries_length = 0;
2559 }
2560
2561
2562 static void
2563 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2564 {
2565   gst_qtdemux_stream_reset (qtdemux, stream);
2566   gst_tag_list_unref (stream->stream_tags);
2567   if (stream->pad) {
2568     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2569     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2570   }
2571   g_free (stream);
2572 }
2573
2574 static void
2575 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2576 {
2577   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2578
2579   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2580   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2581   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2582   qtdemux->n_streams--;
2583 }
2584
2585 static GstStateChangeReturn
2586 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2587 {
2588   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2589   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2590
2591   switch (transition) {
2592     case GST_STATE_CHANGE_PAUSED_TO_READY:
2593       break;
2594     default:
2595       break;
2596   }
2597
2598   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2599
2600   switch (transition) {
2601     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2602       gst_qtdemux_reset (qtdemux, TRUE);
2603       break;
2604     }
2605     default:
2606       break;
2607   }
2608
2609   return result;
2610 }
2611
2612 static void
2613 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2614 {
2615   /* counts as header data */
2616   qtdemux->header_size += length;
2617
2618   /* only consider at least a sufficiently complete ftyp atom */
2619   if (length >= 20) {
2620     GstBuffer *buf;
2621
2622     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2623     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2624         GST_FOURCC_ARGS (qtdemux->major_brand));
2625     if (qtdemux->comp_brands)
2626       gst_buffer_unref (qtdemux->comp_brands);
2627     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2628     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2629   }
2630 }
2631
2632 static void
2633 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2634     GstTagList * xmptaglist)
2635 {
2636   /* Strip out bogus fields */
2637   if (xmptaglist) {
2638     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2639       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2640       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2641     } else {
2642       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2643     }
2644
2645     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2646
2647     /* prioritize native tags using _KEEP mode */
2648     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2649     gst_tag_list_unref (xmptaglist);
2650   }
2651 }
2652
2653 static void
2654 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2655     guint offset)
2656 {
2657   GstByteReader br;
2658   guint8 version;
2659   guint32 flags = 0;
2660   guint i;
2661   guint8 iv_size = 8;
2662   QtDemuxStream *stream;
2663   GstStructure *structure;
2664   QtDemuxCencSampleSetInfo *ss_info = NULL;
2665   const gchar *system_id;
2666   gboolean uses_sub_sample_encryption = FALSE;
2667
2668   if (qtdemux->n_streams == 0)
2669     return;
2670
2671   stream = qtdemux->streams[0];
2672
2673   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2674   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2675     GST_WARNING_OBJECT (qtdemux,
2676         "Attempting PIFF box parsing on an unencrypted stream.");
2677     return;
2678   }
2679
2680   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2681       G_TYPE_STRING, &system_id, NULL);
2682   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2683
2684   stream->protected = TRUE;
2685   stream->protection_scheme_type = FOURCC_cenc;
2686
2687   if (!stream->protection_scheme_info)
2688     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2689
2690   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2691
2692   if (ss_info->default_properties)
2693     gst_structure_free (ss_info->default_properties);
2694
2695   ss_info->default_properties =
2696       gst_structure_new ("application/x-cenc",
2697       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2698
2699   if (ss_info->crypto_info) {
2700     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2701     g_ptr_array_free (ss_info->crypto_info, TRUE);
2702     ss_info->crypto_info = NULL;
2703   }
2704
2705   /* skip UUID */
2706   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2707
2708   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2709     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2710     return;
2711   }
2712
2713   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2714     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2715     return;
2716   }
2717
2718   if ((flags & 0x000001)) {
2719     guint32 algorithm_id = 0;
2720     const guint8 *kid;
2721     GstBuffer *kid_buf;
2722     gboolean is_encrypted = TRUE;
2723
2724     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2725       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2726       return;
2727     }
2728
2729     algorithm_id >>= 8;
2730     if (algorithm_id == 0) {
2731       is_encrypted = FALSE;
2732     } else if (algorithm_id == 1) {
2733       /* FIXME: maybe store this in properties? */
2734       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2735     } else if (algorithm_id == 2) {
2736       /* FIXME: maybe store this in properties? */
2737       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2738     }
2739
2740     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2741       return;
2742
2743     if (!gst_byte_reader_get_data (&br, 16, &kid))
2744       return;
2745
2746     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2747     gst_buffer_fill (kid_buf, 0, kid, 16);
2748     if (ss_info->default_properties)
2749       gst_structure_free (ss_info->default_properties);
2750     ss_info->default_properties =
2751         gst_structure_new ("application/x-cenc",
2752         "iv_size", G_TYPE_UINT, iv_size,
2753         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2754         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2755     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2756         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2757     gst_buffer_unref (kid_buf);
2758   } else if ((flags & 0x000002)) {
2759     uses_sub_sample_encryption = TRUE;
2760   }
2761
2762   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2763     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2764     return;
2765   }
2766
2767   ss_info->crypto_info =
2768       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2769       (GDestroyNotify) qtdemux_gst_structure_free);
2770
2771   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2772     GstStructure *properties;
2773     guint8 *data;
2774     GstBuffer *buf;
2775
2776     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2777     if (properties == NULL) {
2778       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2779       return;
2780     }
2781
2782     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2783       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2784       gst_structure_free (properties);
2785       return;
2786     }
2787     buf = gst_buffer_new_wrapped (data, iv_size);
2788     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2789     gst_buffer_unref (buf);
2790
2791     if (uses_sub_sample_encryption) {
2792       guint16 n_subsamples;
2793
2794       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2795           || n_subsamples == 0) {
2796         GST_ERROR_OBJECT (qtdemux,
2797             "failed to get subsample count for sample %u", i);
2798         gst_structure_free (properties);
2799         return;
2800       }
2801       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2802       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2803         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2804             i);
2805         gst_structure_free (properties);
2806         return;
2807       }
2808       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2809       gst_structure_set (properties,
2810           "subsample_count", G_TYPE_UINT, n_subsamples,
2811           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2812       gst_buffer_unref (buf);
2813     } else {
2814       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2815     }
2816
2817     g_ptr_array_add (ss_info->crypto_info, properties);
2818   }
2819 }
2820
2821 static void
2822 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2823 {
2824   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2825     0x97, 0xA9, 0x42, 0xE8,
2826     0x9C, 0x71, 0x99, 0x94,
2827     0x91, 0xE3, 0xAF, 0xAC
2828   };
2829   static const guint8 playready_uuid[] = {
2830     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2831     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2832   };
2833
2834   static const guint8 piff_sample_encryption_uuid[] = {
2835     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2836     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2837   };
2838
2839   guint offset;
2840
2841   /* counts as header data */
2842   qtdemux->header_size += length;
2843
2844   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2845
2846   if (length <= offset + 16) {
2847     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2848     return;
2849   }
2850
2851   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2852     GstBuffer *buf;
2853     GstTagList *taglist;
2854
2855     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2856         length - offset - 16, NULL);
2857     taglist = gst_tag_list_from_xmp_buffer (buf);
2858     gst_buffer_unref (buf);
2859
2860     /* make sure we have a usable taglist */
2861     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2862
2863     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2864
2865   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2866     int len;
2867     const gunichar2 *s_utf16;
2868     char *contents;
2869
2870     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2871     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2872     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2873     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2874
2875     g_free (contents);
2876
2877     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2878         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2879         (NULL));
2880   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2881     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2882   } else {
2883     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2884         GST_READ_UINT32_LE (buffer + offset),
2885         GST_READ_UINT32_LE (buffer + offset + 4),
2886         GST_READ_UINT32_LE (buffer + offset + 8),
2887         GST_READ_UINT32_LE (buffer + offset + 12));
2888   }
2889 }
2890
2891 static void
2892 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2893 {
2894   GstSidxParser sidx_parser;
2895   GstIsoffParserResult res;
2896   guint consumed;
2897
2898   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2899
2900   res =
2901       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2902       &consumed);
2903   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2904   if (res == GST_ISOFF_QT_PARSER_DONE) {
2905     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2906   }
2907   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2908 }
2909
2910 /* caller verifies at least 8 bytes in buf */
2911 static void
2912 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2913     guint64 * plength, guint32 * pfourcc)
2914 {
2915   guint64 length;
2916   guint32 fourcc;
2917
2918   length = QT_UINT32 (data);
2919   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2920   fourcc = QT_FOURCC (data + 4);
2921   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2922
2923   if (length == 0) {
2924     length = G_MAXUINT64;
2925   } else if (length == 1 && size >= 16) {
2926     /* this means we have an extended size, which is the 64 bit value of
2927      * the next 8 bytes */
2928     length = QT_UINT64 (data + 8);
2929     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2930   }
2931
2932   if (plength)
2933     *plength = length;
2934   if (pfourcc)
2935     *pfourcc = fourcc;
2936 }
2937
2938 static gboolean
2939 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2940 {
2941   guint32 version = 0;
2942   GstClockTime duration = 0;
2943
2944   if (!gst_byte_reader_get_uint32_be (br, &version))
2945     goto failed;
2946
2947   version >>= 24;
2948   if (version == 1) {
2949     if (!gst_byte_reader_get_uint64_be (br, &duration))
2950       goto failed;
2951   } else {
2952     guint32 dur = 0;
2953
2954     if (!gst_byte_reader_get_uint32_be (br, &dur))
2955       goto failed;
2956     duration = dur;
2957   }
2958
2959   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2960   qtdemux->duration = duration;
2961
2962   return TRUE;
2963
2964 failed:
2965   {
2966     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2967     return FALSE;
2968   }
2969 }
2970
2971 static gboolean
2972 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2973     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2974 {
2975   if (!stream->parsed_trex && qtdemux->moov_node) {
2976     GNode *mvex, *trex;
2977     GstByteReader trex_data;
2978
2979     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2980     if (mvex) {
2981       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2982           &trex_data);
2983       while (trex) {
2984         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
2985
2986         /* skip version/flags */
2987         if (!gst_byte_reader_skip (&trex_data, 4))
2988           goto next;
2989         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2990           goto next;
2991         if (id != stream->track_id)
2992           goto next;
2993         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
2994           goto next;
2995         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2996           goto next;
2997         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2998           goto next;
2999         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3000           goto next;
3001
3002         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3003             "duration %d,  size %d, flags 0x%x", stream->track_id,
3004             dur, size, flags);
3005
3006         stream->parsed_trex = TRUE;
3007         stream->def_sample_description_index = sdi;
3008         stream->def_sample_duration = dur;
3009         stream->def_sample_size = size;
3010         stream->def_sample_flags = flags;
3011
3012       next:
3013         /* iterate all siblings */
3014         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3015             &trex_data);
3016       }
3017     }
3018   }
3019
3020   *ds_duration = stream->def_sample_duration;
3021   *ds_size = stream->def_sample_size;
3022   *ds_flags = stream->def_sample_flags;
3023
3024   /* even then, above values are better than random ... */
3025   if (G_UNLIKELY (!stream->parsed_trex)) {
3026     GST_WARNING_OBJECT (qtdemux,
3027         "failed to find fragment defaults for stream %d", stream->track_id);
3028     return FALSE;
3029   }
3030
3031   return TRUE;
3032 }
3033
3034 /* This method should be called whenever a more accurate duration might
3035  * have been found. It will update all relevant variables if/where needed
3036  */
3037 static void
3038 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3039 {
3040   guint i;
3041   guint64 movdur;
3042   GstClockTime prevdur;
3043
3044   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3045
3046   if (movdur > qtdemux->duration) {
3047     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3048     GST_DEBUG_OBJECT (qtdemux,
3049         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3050         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3051     qtdemux->duration = movdur;
3052     GST_DEBUG_OBJECT (qtdemux,
3053         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3054         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3055         GST_TIME_ARGS (qtdemux->segment.stop));
3056     if (qtdemux->segment.duration == prevdur) {
3057       /* If the current segment has duration/stop identical to previous duration
3058        * update them also (because they were set at that point in time with
3059        * the wrong duration */
3060       /* We convert the value *from* the timescale version to avoid rounding errors */
3061       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3062       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3063       qtdemux->segment.duration = fixeddur;
3064       qtdemux->segment.stop = fixeddur;
3065     }
3066   }
3067   for (i = 0; i < qtdemux->n_streams; i++) {
3068     QtDemuxStream *stream = qtdemux->streams[i];
3069     if (stream) {
3070       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3071       if (movdur > stream->duration) {
3072         GST_DEBUG_OBJECT (qtdemux,
3073             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3074             GST_TIME_ARGS (duration));
3075         stream->duration = movdur;
3076         /* internal duration tracking state has been updated above, so */
3077         /* preserve an open-ended dummy segment rather than repeatedly updating
3078          * it and spamming downstream accordingly with segment events */
3079         if (stream->dummy_segment &&
3080             GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3081           /* Update all dummy values to new duration */
3082           stream->segments[0].stop_time = duration;
3083           stream->segments[0].duration = duration;
3084           stream->segments[0].media_stop = duration;
3085
3086           /* let downstream know we possibly have a new stop time */
3087           if (stream->segment_index != -1) {
3088             GstClockTime pos;
3089
3090             if (qtdemux->segment.rate >= 0) {
3091               pos = stream->segment.start;
3092             } else {
3093               pos = stream->segment.stop;
3094             }
3095
3096             gst_qtdemux_stream_update_segment (qtdemux, stream,
3097                 stream->segment_index, pos, NULL, NULL);
3098           }
3099         }
3100       }
3101     }
3102   }
3103 }
3104
3105 static gboolean
3106 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3107     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3108     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3109     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3110     gboolean has_tfdt)
3111 {
3112   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3113   guint64 timestamp;
3114   gint32 data_offset = 0;
3115   guint32 flags = 0, first_flags = 0, samples_count = 0;
3116   gint i;
3117   guint8 *data;
3118   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3119   QtDemuxSample *sample;
3120   gboolean ismv = FALSE;
3121   gint64 initial_offset;
3122
3123   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3124       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3125       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3126       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3127
3128   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3129     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3130     return TRUE;
3131   }
3132
3133   /* presence of stss or not can't really tell us much,
3134    * and flags and so on tend to be marginally reliable in these files */
3135   if (stream->subtype == FOURCC_soun) {
3136     GST_DEBUG_OBJECT (qtdemux,
3137         "sound track in fragmented file; marking all keyframes");
3138     stream->all_keyframe = TRUE;
3139   }
3140
3141   if (!gst_byte_reader_skip (trun, 1) ||
3142       !gst_byte_reader_get_uint24_be (trun, &flags))
3143     goto fail;
3144
3145   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3146     goto fail;
3147
3148   if (flags & TR_DATA_OFFSET) {
3149     /* note this is really signed */
3150     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3151       goto fail;
3152     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3153     /* default base offset = first byte of moof */
3154     if (*base_offset == -1) {
3155       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3156       *base_offset = moof_offset;
3157     }
3158     *running_offset = *base_offset + data_offset;
3159   } else {
3160     /* if no offset at all, that would mean data starts at moof start,
3161      * which is a bit wrong and is ismv crappy way, so compensate
3162      * assuming data is in mdat following moof */
3163     if (*base_offset == -1) {
3164       *base_offset = moof_offset + moof_length + 8;
3165       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3166       ismv = TRUE;
3167     }
3168     if (*running_offset == -1)
3169       *running_offset = *base_offset;
3170   }
3171
3172   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3173       *running_offset);
3174   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3175       data_offset, flags, samples_count);
3176
3177   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3178     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3179       GST_DEBUG_OBJECT (qtdemux,
3180           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3181       flags ^= TR_FIRST_SAMPLE_FLAGS;
3182     } else {
3183       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3184         goto fail;
3185       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3186     }
3187   }
3188
3189   /* FIXME ? spec says other bits should also be checked to determine
3190    * entry size (and prefix size for that matter) */
3191   entry_size = 0;
3192   dur_offset = size_offset = 0;
3193   if (flags & TR_SAMPLE_DURATION) {
3194     GST_LOG_OBJECT (qtdemux, "entry duration present");
3195     dur_offset = entry_size;
3196     entry_size += 4;
3197   }
3198   if (flags & TR_SAMPLE_SIZE) {
3199     GST_LOG_OBJECT (qtdemux, "entry size present");
3200     size_offset = entry_size;
3201     entry_size += 4;
3202   }
3203   if (flags & TR_SAMPLE_FLAGS) {
3204     GST_LOG_OBJECT (qtdemux, "entry flags present");
3205     flags_offset = entry_size;
3206     entry_size += 4;
3207   }
3208   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3209     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3210     ct_offset = entry_size;
3211     entry_size += 4;
3212   }
3213
3214   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3215     goto fail;
3216   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3217
3218   if (stream->n_samples + samples_count >=
3219       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3220     goto index_too_big;
3221
3222   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3223       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3224       (stream->n_samples + samples_count) *
3225       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3226
3227   /* create a new array of samples if it's the first sample parsed */
3228   if (stream->n_samples == 0) {
3229     g_assert (stream->samples == NULL);
3230     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3231     /* or try to reallocate it with space enough to insert the new samples */
3232   } else
3233     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3234         stream->n_samples + samples_count);
3235   if (stream->samples == NULL)
3236     goto out_of_memory;
3237
3238   if (qtdemux->fragment_start != -1) {
3239     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3240     qtdemux->fragment_start = -1;
3241   } else {
3242     if (stream->n_samples == 0) {
3243       if (decode_ts > 0) {
3244         timestamp = decode_ts;
3245       } else if (stream->pending_seek != NULL) {
3246         /* if we don't have a timestamp from a tfdt box, we'll use the one
3247          * from the mfra seek table */
3248         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3249             GST_TIME_ARGS (stream->pending_seek->ts));
3250
3251         /* FIXME: this is not fully correct, the timestamp refers to the random
3252          * access sample refered to in the tfra entry, which may not necessarily
3253          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3254         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3255       } else {
3256         timestamp = 0;
3257       }
3258
3259       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3260       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3261           GST_TIME_ARGS (gst_ts));
3262     } else {
3263       /* subsequent fragments extend stream */
3264       timestamp =
3265           stream->samples[stream->n_samples - 1].timestamp +
3266           stream->samples[stream->n_samples - 1].duration;
3267
3268       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3269        * difference (1 sec.) between decode_ts and timestamp, prefer the
3270        * former */
3271       if (has_tfdt && !qtdemux->upstream_format_is_time
3272           && ABSDIFF (decode_ts, timestamp) >
3273           MAX (stream->duration_last_moof / 2,
3274               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3275         GST_INFO_OBJECT (qtdemux,
3276             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3277             ") are significantly different (more than %" GST_TIME_FORMAT
3278             "), using decode_ts",
3279             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3280             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3281             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3282                     MAX (stream->duration_last_moof / 2,
3283                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3284         timestamp = decode_ts;
3285       }
3286
3287       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3288       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3289           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3290     }
3291   }
3292
3293   initial_offset = *running_offset;
3294
3295   sample = stream->samples + stream->n_samples;
3296   for (i = 0; i < samples_count; i++) {
3297     guint32 dur, size, sflags, ct;
3298
3299     /* first read sample data */
3300     if (flags & TR_SAMPLE_DURATION) {
3301       dur = QT_UINT32 (data + dur_offset);
3302     } else {
3303       dur = d_sample_duration;
3304     }
3305     if (flags & TR_SAMPLE_SIZE) {
3306       size = QT_UINT32 (data + size_offset);
3307     } else {
3308       size = d_sample_size;
3309     }
3310     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3311       if (i == 0) {
3312         sflags = first_flags;
3313       } else {
3314         sflags = d_sample_flags;
3315       }
3316     } else if (flags & TR_SAMPLE_FLAGS) {
3317       sflags = QT_UINT32 (data + flags_offset);
3318     } else {
3319       sflags = d_sample_flags;
3320     }
3321     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3322       ct = QT_UINT32 (data + ct_offset);
3323     } else {
3324       ct = 0;
3325     }
3326     data += entry_size;
3327
3328     /* fill the sample information */
3329     sample->offset = *running_offset;
3330     sample->pts_offset = ct;
3331     sample->size = size;
3332     sample->timestamp = timestamp;
3333     sample->duration = dur;
3334     /* sample-is-difference-sample */
3335     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3336      * now idea how it relates to bitfield other than massive LE/BE confusion */
3337     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3338     *running_offset += size;
3339     timestamp += dur;
3340     stream->duration_moof += dur;
3341     sample++;
3342   }
3343
3344   /* Update total duration if needed */
3345   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3346
3347   /* Pre-emptively figure out size of mdat based on trun information.
3348    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3349    * size, else we will still be able to use this when dealing with gap'ed
3350    * input */
3351   qtdemux->mdatleft = *running_offset - initial_offset;
3352   qtdemux->mdatoffset = initial_offset;
3353   qtdemux->mdatsize = qtdemux->mdatleft;
3354
3355   stream->n_samples += samples_count;
3356   stream->n_samples_moof += samples_count;
3357
3358   if (stream->pending_seek != NULL)
3359     stream->pending_seek = NULL;
3360
3361   return TRUE;
3362
3363 fail:
3364   {
3365     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3366     return FALSE;
3367   }
3368 out_of_memory:
3369   {
3370     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3371         stream->n_samples);
3372     return FALSE;
3373   }
3374 index_too_big:
3375   {
3376     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3377         "be larger than %uMB (broken file?)", stream->n_samples,
3378         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3379     return FALSE;
3380   }
3381 }
3382
3383 /* find stream with @id */
3384 static inline QtDemuxStream *
3385 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3386 {
3387   QtDemuxStream *stream;
3388   gint i;
3389
3390   /* check */
3391   if (G_UNLIKELY (!id)) {
3392     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3393     return NULL;
3394   }
3395
3396   /* try to get it fast and simple */
3397   if (G_LIKELY (id <= qtdemux->n_streams)) {
3398     stream = qtdemux->streams[id - 1];
3399     if (G_LIKELY (stream->track_id == id))
3400       return stream;
3401   }
3402
3403   /* linear search otherwise */
3404   for (i = 0; i < qtdemux->n_streams; i++) {
3405     stream = qtdemux->streams[i];
3406     if (stream->track_id == id)
3407       return stream;
3408   }
3409   if (qtdemux->mss_mode) {
3410     /* mss should have only 1 stream anyway */
3411     return qtdemux->streams[0];
3412   }
3413
3414   return NULL;
3415 }
3416
3417 static gboolean
3418 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3419     guint32 * fragment_number)
3420 {
3421   if (!gst_byte_reader_skip (mfhd, 4))
3422     goto fail;
3423   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3424     goto fail;
3425   return TRUE;
3426 fail:
3427   {
3428     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3429     return FALSE;
3430   }
3431 }
3432
3433 static gboolean
3434 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3435     QtDemuxStream ** stream, guint32 * default_sample_duration,
3436     guint32 * default_sample_size, guint32 * default_sample_flags,
3437     gint64 * base_offset)
3438 {
3439   guint32 flags = 0;
3440   guint32 track_id = 0;
3441
3442   if (!gst_byte_reader_skip (tfhd, 1) ||
3443       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3444     goto invalid_track;
3445
3446   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3447     goto invalid_track;
3448
3449   *stream = qtdemux_find_stream (qtdemux, track_id);
3450   if (G_UNLIKELY (!*stream))
3451     goto unknown_stream;
3452
3453   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3454     *base_offset = qtdemux->moof_offset;
3455
3456   if (flags & TF_BASE_DATA_OFFSET)
3457     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3458       goto invalid_track;
3459
3460   /* obtain stream defaults */
3461   qtdemux_parse_trex (qtdemux, *stream,
3462       default_sample_duration, default_sample_size, default_sample_flags);
3463
3464   (*stream)->stsd_sample_description_id =
3465       (*stream)->def_sample_description_index - 1;
3466
3467   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3468     guint32 sample_description_index;
3469     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3470       goto invalid_track;
3471     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3472   }
3473
3474   if (qtdemux->mss_mode) {
3475     /* mss has no stsd entry */
3476     (*stream)->stsd_sample_description_id = 0;
3477   }
3478
3479   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3480     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3481       goto invalid_track;
3482
3483   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3484     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3485       goto invalid_track;
3486
3487   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3488     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3489       goto invalid_track;
3490
3491   return TRUE;
3492
3493 invalid_track:
3494   {
3495     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3496     return FALSE;
3497   }
3498 unknown_stream:
3499   {
3500     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3501     return TRUE;
3502   }
3503 }
3504
3505 static gboolean
3506 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3507     guint64 * decode_time)
3508 {
3509   guint32 version = 0;
3510
3511   if (!gst_byte_reader_get_uint32_be (br, &version))
3512     return FALSE;
3513
3514   version >>= 24;
3515   if (version == 1) {
3516     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3517       goto failed;
3518   } else {
3519     guint32 dec_time = 0;
3520     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3521       goto failed;
3522     *decode_time = dec_time;
3523   }
3524
3525   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3526       *decode_time);
3527
3528   return TRUE;
3529
3530 failed:
3531   {
3532     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3533     return FALSE;
3534   }
3535 }
3536
3537 /* Returns a pointer to a GstStructure containing the properties of
3538  * the stream sample identified by @sample_index. The caller must unref
3539  * the returned object after use. Returns NULL if unsuccessful. */
3540 static GstStructure *
3541 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3542     QtDemuxStream * stream, guint sample_index)
3543 {
3544   QtDemuxCencSampleSetInfo *info = NULL;
3545
3546   g_return_val_if_fail (stream != NULL, NULL);
3547   g_return_val_if_fail (stream->protected, NULL);
3548   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3549
3550   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3551
3552   /* Currently, cenc properties for groups of samples are not supported, so
3553    * simply return a copy of the default sample properties */
3554   return gst_structure_copy (info->default_properties);
3555 }
3556
3557 /* Parses the sizes of sample auxiliary information contained within a stream,
3558  * as given in a saiz box. Returns array of sample_count guint8 size values,
3559  * or NULL on failure */
3560 static guint8 *
3561 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3562     GstByteReader * br, guint32 * sample_count)
3563 {
3564   guint32 flags = 0;
3565   guint8 *info_sizes;
3566   guint8 default_info_size;
3567
3568   g_return_val_if_fail (qtdemux != NULL, NULL);
3569   g_return_val_if_fail (stream != NULL, NULL);
3570   g_return_val_if_fail (br != NULL, NULL);
3571   g_return_val_if_fail (sample_count != NULL, NULL);
3572
3573   if (!gst_byte_reader_get_uint32_be (br, &flags))
3574     return NULL;
3575
3576   if (flags & 0x1) {
3577     /* aux_info_type and aux_info_type_parameter are ignored */
3578     if (!gst_byte_reader_skip (br, 8))
3579       return NULL;
3580   }
3581
3582   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3583     return NULL;
3584   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3585
3586   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3587     return NULL;
3588   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3589
3590
3591   if (default_info_size == 0) {
3592     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3593       return NULL;
3594     }
3595   } else {
3596     info_sizes = g_new (guint8, *sample_count);
3597     memset (info_sizes, default_info_size, *sample_count);
3598   }
3599
3600   return info_sizes;
3601 }
3602
3603 /* Parses the offset of sample auxiliary information contained within a stream,
3604  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3605 static gboolean
3606 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3607     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3608     guint64 * offset)
3609 {
3610   guint8 version = 0;
3611   guint32 flags = 0;
3612   guint32 aux_info_type = 0;
3613   guint32 aux_info_type_parameter = 0;
3614   guint32 entry_count;
3615   guint32 off_32;
3616   guint64 off_64;
3617   const guint8 *aux_info_type_data = NULL;
3618
3619   g_return_val_if_fail (qtdemux != NULL, FALSE);
3620   g_return_val_if_fail (stream != NULL, FALSE);
3621   g_return_val_if_fail (br != NULL, FALSE);
3622   g_return_val_if_fail (offset != NULL, FALSE);
3623
3624   if (!gst_byte_reader_get_uint8 (br, &version))
3625     return FALSE;
3626
3627   if (!gst_byte_reader_get_uint24_be (br, &flags))
3628     return FALSE;
3629
3630   if (flags & 0x1) {
3631
3632     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3633       return FALSE;
3634     aux_info_type = QT_FOURCC (aux_info_type_data);
3635
3636     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3637       return FALSE;
3638   } else if (stream->protected) {
3639     aux_info_type = stream->protection_scheme_type;
3640   } else {
3641     aux_info_type = CUR_STREAM (stream)->fourcc;
3642   }
3643
3644   if (info_type)
3645     *info_type = aux_info_type;
3646   if (info_type_parameter)
3647     *info_type_parameter = aux_info_type_parameter;
3648
3649   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3650       "aux_info_type_parameter:  %#06x",
3651       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3652
3653   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3654     return FALSE;
3655
3656   if (entry_count != 1) {
3657     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3658     return FALSE;
3659   }
3660
3661   if (version == 0) {
3662     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3663       return FALSE;
3664     *offset = (guint64) off_32;
3665   } else {
3666     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3667       return FALSE;
3668     *offset = off_64;
3669   }
3670
3671   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3672   return TRUE;
3673 }
3674
3675 static void
3676 qtdemux_gst_structure_free (GstStructure * gststructure)
3677 {
3678   if (gststructure) {
3679     gst_structure_free (gststructure);
3680   }
3681 }
3682
3683 /* Parses auxiliary information relating to samples protected using Common
3684  * Encryption (cenc); the format of this information is defined in
3685  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3686 static gboolean
3687 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3688     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3689 {
3690   QtDemuxCencSampleSetInfo *ss_info = NULL;
3691   guint8 size;
3692   gint i;
3693   GPtrArray *old_crypto_info = NULL;
3694   guint old_entries = 0;
3695
3696   g_return_val_if_fail (qtdemux != NULL, FALSE);
3697   g_return_val_if_fail (stream != NULL, FALSE);
3698   g_return_val_if_fail (br != NULL, FALSE);
3699   g_return_val_if_fail (stream->protected, FALSE);
3700   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3701
3702   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3703
3704   if (ss_info->crypto_info) {
3705     old_crypto_info = ss_info->crypto_info;
3706     /* Count number of non-null entries remaining at the tail end */
3707     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3708       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3709         break;
3710       old_entries++;
3711     }
3712   }
3713
3714   ss_info->crypto_info =
3715       g_ptr_array_new_full (sample_count + old_entries,
3716       (GDestroyNotify) qtdemux_gst_structure_free);
3717
3718   /* We preserve old entries because we parse the next moof in advance
3719    * of consuming all samples from the previous moof, and otherwise
3720    * we'd discard the corresponding crypto info for the samples
3721    * from the previous fragment. */
3722   if (old_entries) {
3723     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3724         old_entries);
3725     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3726       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3727               i));
3728       g_ptr_array_index (old_crypto_info, i) = NULL;
3729     }
3730   }
3731
3732   if (old_crypto_info) {
3733     /* Everything now belongs to the new array */
3734     g_ptr_array_free (old_crypto_info, TRUE);
3735   }
3736
3737   for (i = 0; i < sample_count; ++i) {
3738     GstStructure *properties;
3739     guint16 n_subsamples = 0;
3740     guint8 *data;
3741     guint iv_size;
3742     GstBuffer *buf;
3743
3744     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3745     if (properties == NULL) {
3746       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3747       return FALSE;
3748     }
3749     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3750       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3751       gst_structure_free (properties);
3752       return FALSE;
3753     }
3754     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3755       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3756       gst_structure_free (properties);
3757       return FALSE;
3758     }
3759     buf = gst_buffer_new_wrapped (data, iv_size);
3760     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3761     gst_buffer_unref (buf);
3762     size = info_sizes[i];
3763     if (size > iv_size) {
3764       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3765           || !(n_subsamples > 0)) {
3766         gst_structure_free (properties);
3767         GST_ERROR_OBJECT (qtdemux,
3768             "failed to get subsample count for sample %u", i);
3769         return FALSE;
3770       }
3771       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3772       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3773         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3774             i);
3775         gst_structure_free (properties);
3776         return FALSE;
3777       }
3778       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3779       if (!buf) {
3780         gst_structure_free (properties);
3781         return FALSE;
3782       }
3783       gst_structure_set (properties,
3784           "subsample_count", G_TYPE_UINT, n_subsamples,
3785           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3786       gst_buffer_unref (buf);
3787     } else {
3788       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3789     }
3790     g_ptr_array_add (ss_info->crypto_info, properties);
3791   }
3792   return TRUE;
3793 }
3794
3795 /* Converts a UUID in raw byte form to a string representation, as defined in
3796  * RFC 4122. The caller takes ownership of the returned string and is
3797  * responsible for freeing it after use. */
3798 static gchar *
3799 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3800 {
3801   const guint8 *uuid = (const guint8 *) uuid_bytes;
3802
3803   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3804       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3805       uuid[0], uuid[1], uuid[2], uuid[3],
3806       uuid[4], uuid[5], uuid[6], uuid[7],
3807       uuid[8], uuid[9], uuid[10], uuid[11],
3808       uuid[12], uuid[13], uuid[14], uuid[15]);
3809 }
3810
3811 /* Parses a Protection System Specific Header box (pssh), as defined in the
3812  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3813  * information needed by a specific content protection system in order to
3814  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3815  * otherwise. */
3816 static gboolean
3817 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3818 {
3819   gchar *sysid_string;
3820   guint32 pssh_size = QT_UINT32 (node->data);
3821   GstBuffer *pssh = NULL;
3822   GstEvent *event = NULL;
3823   guint32 parent_box_type;
3824   gint i;
3825
3826   if (G_UNLIKELY (pssh_size < 32U)) {
3827     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3828     return FALSE;
3829   }
3830
3831   sysid_string =
3832       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3833
3834   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3835
3836   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3837   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3838       gst_buffer_get_size (pssh));
3839
3840   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3841
3842   /* Push an event containing the pssh box onto the queues of all streams. */
3843   event = gst_event_new_protection (sysid_string, pssh,
3844       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3845   for (i = 0; i < qtdemux->n_streams; ++i) {
3846     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3847         gst_event_ref (event));
3848   }
3849   g_free (sysid_string);
3850   gst_event_unref (event);
3851   gst_buffer_unref (pssh);
3852   return TRUE;
3853 }
3854
3855 static gboolean
3856 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3857     guint64 moof_offset, QtDemuxStream * stream)
3858 {
3859   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3860   GNode *uuid_node;
3861   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3862   GNode *saiz_node, *saio_node, *pssh_node;
3863   GstByteReader saiz_data, saio_data;
3864   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3865   gint64 base_offset, running_offset;
3866   guint32 frag_num;
3867
3868   /* NOTE @stream ignored */
3869
3870   moof_node = g_node_new ((guint8 *) buffer);
3871   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3872   qtdemux_node_dump (qtdemux, moof_node);
3873
3874   /* Get fragment number from mfhd and check it's valid */
3875   mfhd_node =
3876       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3877   if (mfhd_node == NULL)
3878     goto missing_mfhd;
3879   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3880     goto fail;
3881   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3882
3883   /* unknown base_offset to start with */
3884   base_offset = running_offset = -1;
3885   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3886   while (traf_node) {
3887     guint64 decode_time = 0;
3888
3889     /* Fragment Header node */
3890     tfhd_node =
3891         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3892         &tfhd_data);
3893     if (!tfhd_node)
3894       goto missing_tfhd;
3895     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3896             &ds_size, &ds_flags, &base_offset))
3897       goto missing_tfhd;
3898
3899     /* The following code assumes at most a single set of sample auxiliary
3900      * data in the fragment (consisting of a saiz box and a corresponding saio
3901      * box); in theory, however, there could be multiple sets of sample
3902      * auxiliary data in a fragment. */
3903     saiz_node =
3904         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3905         &saiz_data);
3906     if (saiz_node) {
3907       guint32 info_type = 0;
3908       guint64 offset = 0;
3909       guint32 info_type_parameter = 0;
3910
3911       g_free (qtdemux->cenc_aux_info_sizes);
3912
3913       qtdemux->cenc_aux_info_sizes =
3914           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3915           &qtdemux->cenc_aux_sample_count);
3916       if (qtdemux->cenc_aux_info_sizes == NULL) {
3917         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3918         goto fail;
3919       }
3920       saio_node =
3921           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3922           &saio_data);
3923       if (!saio_node) {
3924         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3925         g_free (qtdemux->cenc_aux_info_sizes);
3926         qtdemux->cenc_aux_info_sizes = NULL;
3927         goto fail;
3928       }
3929
3930       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3931                   &info_type, &info_type_parameter, &offset))) {
3932         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3933         g_free (qtdemux->cenc_aux_info_sizes);
3934         qtdemux->cenc_aux_info_sizes = NULL;
3935         goto fail;
3936       }
3937       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3938         offset += (guint64) (base_offset - qtdemux->moof_offset);
3939       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3940         GstByteReader br;
3941         if (offset > length) {
3942           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3943           qtdemux->cenc_aux_info_offset = offset;
3944         } else {
3945           gst_byte_reader_init (&br, buffer + offset, length - offset);
3946           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3947                   qtdemux->cenc_aux_info_sizes,
3948                   qtdemux->cenc_aux_sample_count)) {
3949             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3950             g_free (qtdemux->cenc_aux_info_sizes);
3951             qtdemux->cenc_aux_info_sizes = NULL;
3952             goto fail;
3953           }
3954         }
3955       }
3956     }
3957
3958     tfdt_node =
3959         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3960         &tfdt_data);
3961     if (tfdt_node) {
3962       /* We'll use decode_time to interpolate timestamps
3963        * in case the input timestamps are missing */
3964       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3965
3966       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3967           " (%" GST_TIME_FORMAT ")", decode_time,
3968           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
3969                   decode_time) : GST_CLOCK_TIME_NONE));
3970
3971       /* Discard the fragment buffer timestamp info to avoid using it.
3972        * Rely on tfdt instead as it is more accurate than the timestamp
3973        * that is fetched from a manifest/playlist and is usually
3974        * less accurate. */
3975       qtdemux->fragment_start = -1;
3976     }
3977
3978     if (G_UNLIKELY (!stream)) {
3979       /* we lost track of offset, we'll need to regain it,
3980        * but can delay complaining until later or avoid doing so altogether */
3981       base_offset = -2;
3982       goto next;
3983     }
3984     if (G_UNLIKELY (base_offset < -1))
3985       goto lost_offset;
3986
3987     if (qtdemux->upstream_format_is_time)
3988       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3989
3990     /* initialise moof sample data */
3991     stream->n_samples_moof = 0;
3992     stream->duration_last_moof = stream->duration_moof;
3993     stream->duration_moof = 0;
3994
3995     /* Track Run node */
3996     trun_node =
3997         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3998         &trun_data);
3999     while (trun_node) {
4000       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4001           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4002           &running_offset, decode_time, (tfdt_node != NULL));
4003       /* iterate all siblings */
4004       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4005           &trun_data);
4006     }
4007
4008     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4009     if (uuid_node) {
4010       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4011       guint32 box_length = QT_UINT32 (uuid_buffer);
4012
4013       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4014     }
4015
4016     /* if no new base_offset provided for next traf,
4017      * base is end of current traf */
4018     base_offset = running_offset;
4019     running_offset = -1;
4020
4021     if (stream->n_samples_moof && stream->duration_moof)
4022       stream->new_caps = TRUE;
4023
4024   next:
4025     /* iterate all siblings */
4026     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4027   }
4028
4029   /* parse any protection system info */
4030   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4031   while (pssh_node) {
4032     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4033     qtdemux_parse_pssh (qtdemux, pssh_node);
4034     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4035   }
4036
4037   g_node_destroy (moof_node);
4038   return TRUE;
4039
4040 missing_tfhd:
4041   {
4042     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4043     goto fail;
4044   }
4045 missing_mfhd:
4046   {
4047     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4048     goto fail;
4049   }
4050 lost_offset:
4051   {
4052     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4053     goto fail;
4054   }
4055 fail:
4056   {
4057     g_node_destroy (moof_node);
4058     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4059         (_("This file is corrupt and cannot be played.")), (NULL));
4060     return FALSE;
4061   }
4062 }
4063
4064 #if 0
4065 /* might be used if some day we actually use mfra & co
4066  * for random access to fragments,
4067  * but that will require quite some modifications and much less relying
4068  * on a sample array */
4069 #endif
4070
4071 static gboolean
4072 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4073 {
4074   QtDemuxStream *stream;
4075   guint32 ver_flags, track_id, len, num_entries, i;
4076   guint value_size, traf_size, trun_size, sample_size;
4077   guint64 time = 0, moof_offset = 0;
4078 #if 0
4079   GstBuffer *buf = NULL;
4080   GstFlowReturn ret;
4081 #endif
4082   GstByteReader tfra;
4083
4084   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4085
4086   if (!gst_byte_reader_skip (&tfra, 8))
4087     return FALSE;
4088
4089   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4090     return FALSE;
4091
4092   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4093       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4094       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4095     return FALSE;
4096
4097   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4098
4099   stream = qtdemux_find_stream (qtdemux, track_id);
4100   if (stream == NULL)
4101     goto unknown_trackid;
4102
4103   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4104   sample_size = (len & 3) + 1;
4105   trun_size = ((len & 12) >> 2) + 1;
4106   traf_size = ((len & 48) >> 4) + 1;
4107
4108   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4109       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4110
4111   if (num_entries == 0)
4112     goto no_samples;
4113
4114   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4115           value_size + value_size + traf_size + trun_size + sample_size))
4116     goto corrupt_file;
4117
4118   g_free (stream->ra_entries);
4119   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4120   stream->n_ra_entries = num_entries;
4121
4122   for (i = 0; i < num_entries; i++) {
4123     qt_atom_parser_get_offset (&tfra, value_size, &time);
4124     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4125     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4126     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4127     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4128
4129     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4130
4131     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4132         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4133
4134     stream->ra_entries[i].ts = time;
4135     stream->ra_entries[i].moof_offset = moof_offset;
4136
4137     /* don't want to go through the entire file and read all moofs at startup */
4138 #if 0
4139     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4140     if (ret != GST_FLOW_OK)
4141       goto corrupt_file;
4142     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4143         moof_offset, stream);
4144     gst_buffer_unref (buf);
4145 #endif
4146   }
4147
4148   check_update_duration (qtdemux, time);
4149
4150   return TRUE;
4151
4152 /* ERRORS */
4153 unknown_trackid:
4154   {
4155     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4156     return FALSE;
4157   }
4158 corrupt_file:
4159   {
4160     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4161     return FALSE;
4162   }
4163 no_samples:
4164   {
4165     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4166     return FALSE;
4167   }
4168 }
4169
4170 static gboolean
4171 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4172 {
4173   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4174   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4175   GstBuffer *mfro = NULL, *mfra = NULL;
4176   GstFlowReturn flow;
4177   gboolean ret = FALSE;
4178   GNode *mfra_node, *tfra_node;
4179   guint64 mfra_offset = 0;
4180   guint32 fourcc, mfra_size;
4181   gint64 len;
4182
4183   /* query upstream size in bytes */
4184   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4185     goto size_query_failed;
4186
4187   /* mfro box should be at the very end of the file */
4188   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4189   if (flow != GST_FLOW_OK)
4190     goto exit;
4191
4192   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4193
4194   fourcc = QT_FOURCC (mfro_map.data + 4);
4195   if (fourcc != FOURCC_mfro)
4196     goto exit;
4197
4198   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4199   if (mfro_map.size < 16)
4200     goto invalid_mfro_size;
4201
4202   mfra_size = QT_UINT32 (mfro_map.data + 12);
4203   if (mfra_size >= len)
4204     goto invalid_mfra_size;
4205
4206   mfra_offset = len - mfra_size;
4207
4208   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4209       mfra_offset, mfra_size);
4210
4211   /* now get and parse mfra box */
4212   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4213   if (flow != GST_FLOW_OK)
4214     goto broken_file;
4215
4216   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4217
4218   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4219   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4220
4221   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4222
4223   while (tfra_node) {
4224     qtdemux_parse_tfra (qtdemux, tfra_node);
4225     /* iterate all siblings */
4226     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4227   }
4228   g_node_destroy (mfra_node);
4229
4230   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4231   ret = TRUE;
4232
4233 exit:
4234
4235   if (mfro) {
4236     if (mfro_map.memory != NULL)
4237       gst_buffer_unmap (mfro, &mfro_map);
4238     gst_buffer_unref (mfro);
4239   }
4240   if (mfra) {
4241     if (mfra_map.memory != NULL)
4242       gst_buffer_unmap (mfra, &mfra_map);
4243     gst_buffer_unref (mfra);
4244   }
4245   return ret;
4246
4247 /* ERRORS */
4248 size_query_failed:
4249   {
4250     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4251     goto exit;
4252   }
4253 invalid_mfro_size:
4254   {
4255     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4256     goto exit;
4257   }
4258 invalid_mfra_size:
4259   {
4260     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4261     goto exit;
4262   }
4263 broken_file:
4264   {
4265     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4266     goto exit;
4267   }
4268 }
4269
4270 static guint64
4271 add_offset (guint64 offset, guint64 advance)
4272 {
4273   /* Avoid 64-bit overflow by clamping */
4274   if (offset > G_MAXUINT64 - advance)
4275     return G_MAXUINT64;
4276   return offset + advance;
4277 }
4278
4279 static GstFlowReturn
4280 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4281 {
4282   guint64 length = 0;
4283   guint32 fourcc = 0;
4284   GstBuffer *buf = NULL;
4285   GstFlowReturn ret = GST_FLOW_OK;
4286   guint64 cur_offset = qtdemux->offset;
4287   GstMapInfo map;
4288
4289   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4290   if (G_UNLIKELY (ret != GST_FLOW_OK))
4291     goto beach;
4292   gst_buffer_map (buf, &map, GST_MAP_READ);
4293   if (G_LIKELY (map.size >= 8))
4294     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4295   gst_buffer_unmap (buf, &map);
4296   gst_buffer_unref (buf);
4297
4298   /* maybe we already got most we needed, so only consider this eof */
4299   if (G_UNLIKELY (length == 0)) {
4300     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4301         (_("Invalid atom size.")),
4302         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4303             GST_FOURCC_ARGS (fourcc)));
4304     ret = GST_FLOW_EOS;
4305     goto beach;
4306   }
4307
4308   switch (fourcc) {
4309     case FOURCC_moof:
4310       /* record for later parsing when needed */
4311       if (!qtdemux->moof_offset) {
4312         qtdemux->moof_offset = qtdemux->offset;
4313       }
4314       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4315         /* FIXME */
4316       } else {
4317         qtdemux->offset += length;      /* skip moof and keep going */
4318       }
4319       if (qtdemux->got_moov) {
4320         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4321         ret = GST_FLOW_EOS;
4322         goto beach;
4323       }
4324       break;
4325     case FOURCC_mdat:
4326     case FOURCC_free:
4327     case FOURCC_skip:
4328     case FOURCC_wide:
4329     case FOURCC_PICT:
4330     case FOURCC_pnot:
4331     {
4332       GST_LOG_OBJECT (qtdemux,
4333           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4334           GST_FOURCC_ARGS (fourcc), cur_offset);
4335       qtdemux->offset = add_offset (qtdemux->offset, length);
4336       break;
4337     }
4338     case FOURCC_moov:
4339     {
4340       GstBuffer *moov = NULL;
4341
4342       if (qtdemux->got_moov) {
4343         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4344         qtdemux->offset = add_offset (qtdemux->offset, length);
4345         goto beach;
4346       }
4347
4348       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4349       if (ret != GST_FLOW_OK)
4350         goto beach;
4351       gst_buffer_map (moov, &map, GST_MAP_READ);
4352
4353       if (length != map.size) {
4354         /* Some files have a 'moov' atom at the end of the file which contains
4355          * a terminal 'free' atom where the body of the atom is missing.
4356          * Check for, and permit, this special case.
4357          */
4358         if (map.size >= 8) {
4359           guint8 *final_data = map.data + (map.size - 8);
4360           guint32 final_length = QT_UINT32 (final_data);
4361           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4362
4363           if (final_fourcc == FOURCC_free
4364               && map.size + final_length - 8 == length) {
4365             /* Ok, we've found that special case. Allocate a new buffer with
4366              * that free atom actually present. */
4367             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4368             gst_buffer_fill (newmoov, 0, map.data, map.size);
4369             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4370             gst_buffer_unmap (moov, &map);
4371             gst_buffer_unref (moov);
4372             moov = newmoov;
4373             gst_buffer_map (moov, &map, GST_MAP_READ);
4374           }
4375         }
4376       }
4377
4378       if (length != map.size) {
4379         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4380             (_("This file is incomplete and cannot be played.")),
4381             ("We got less than expected (received %" G_GSIZE_FORMAT
4382                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4383                 (guint) length, cur_offset));
4384         gst_buffer_unmap (moov, &map);
4385         gst_buffer_unref (moov);
4386         ret = GST_FLOW_ERROR;
4387         goto beach;
4388       }
4389       qtdemux->offset += length;
4390
4391       qtdemux_parse_moov (qtdemux, map.data, length);
4392       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4393
4394       qtdemux_parse_tree (qtdemux);
4395       if (qtdemux->moov_node_compressed) {
4396         g_node_destroy (qtdemux->moov_node_compressed);
4397         g_free (qtdemux->moov_node->data);
4398       }
4399       qtdemux->moov_node_compressed = NULL;
4400       g_node_destroy (qtdemux->moov_node);
4401       qtdemux->moov_node = NULL;
4402       gst_buffer_unmap (moov, &map);
4403       gst_buffer_unref (moov);
4404       qtdemux->got_moov = TRUE;
4405
4406       break;
4407     }
4408     case FOURCC_ftyp:
4409     {
4410       GstBuffer *ftyp = NULL;
4411
4412       /* extract major brand; might come in handy for ISO vs QT issues */
4413       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4414       if (ret != GST_FLOW_OK)
4415         goto beach;
4416       qtdemux->offset += length;
4417       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4418       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4419       gst_buffer_unmap (ftyp, &map);
4420       gst_buffer_unref (ftyp);
4421       break;
4422     }
4423     case FOURCC_uuid:
4424     {
4425       GstBuffer *uuid = NULL;
4426
4427       /* uuid are extension atoms */
4428       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4429       if (ret != GST_FLOW_OK)
4430         goto beach;
4431       qtdemux->offset += length;
4432       gst_buffer_map (uuid, &map, GST_MAP_READ);
4433       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4434       gst_buffer_unmap (uuid, &map);
4435       gst_buffer_unref (uuid);
4436       break;
4437     }
4438     case FOURCC_sidx:
4439     {
4440       GstBuffer *sidx = NULL;
4441       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4442       if (ret != GST_FLOW_OK)
4443         goto beach;
4444       qtdemux->offset += length;
4445       gst_buffer_map (sidx, &map, GST_MAP_READ);
4446       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4447       gst_buffer_unmap (sidx, &map);
4448       gst_buffer_unref (sidx);
4449       break;
4450     }
4451     default:
4452     {
4453       GstBuffer *unknown = NULL;
4454
4455       GST_LOG_OBJECT (qtdemux,
4456           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4457           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4458           cur_offset);
4459       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4460       if (ret != GST_FLOW_OK)
4461         goto beach;
4462       gst_buffer_map (unknown, &map, GST_MAP_READ);
4463       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4464       gst_buffer_unmap (unknown, &map);
4465       gst_buffer_unref (unknown);
4466       qtdemux->offset += length;
4467       break;
4468     }
4469   }
4470
4471 beach:
4472   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4473     /* digested all data, show what we have */
4474     qtdemux_prepare_streams (qtdemux);
4475     ret = qtdemux_expose_streams (qtdemux);
4476
4477     qtdemux->state = QTDEMUX_STATE_MOVIE;
4478     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4479         qtdemux->state);
4480     return ret;
4481   }
4482   return ret;
4483 }
4484
4485 /* Seeks to the previous keyframe of the indexed stream and
4486  * aligns other streams with respect to the keyframe timestamp
4487  * of indexed stream. Only called in case of Reverse Playback
4488  */
4489 static GstFlowReturn
4490 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4491 {
4492   guint8 n = 0;
4493   guint32 seg_idx = 0, k_index = 0;
4494   guint32 ref_seg_idx, ref_k_index;
4495   GstClockTime k_pos = 0, last_stop = 0;
4496   QtDemuxSegment *seg = NULL;
4497   QtDemuxStream *ref_str = NULL;
4498   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4499   guint64 target_ts;
4500
4501   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4502    * and finally align all the other streams on that timestamp with their
4503    * respective keyframes */
4504   for (n = 0; n < qtdemux->n_streams; n++) {
4505     QtDemuxStream *str = qtdemux->streams[n];
4506
4507     /* No candidate yet, take the first stream */
4508     if (!ref_str) {
4509       ref_str = str;
4510       continue;
4511     }
4512
4513     /* So that stream has a segment, we prefer video streams */
4514     if (str->subtype == FOURCC_vide) {
4515       ref_str = str;
4516       break;
4517     }
4518   }
4519
4520   if (G_UNLIKELY (!ref_str)) {
4521     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4522     goto eos;
4523   }
4524
4525   if (G_UNLIKELY (!ref_str->from_sample)) {
4526     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4527     goto eos;
4528   }
4529
4530   /* So that stream has been playing from from_sample to to_sample. We will
4531    * get the timestamp of the previous sample and search for a keyframe before
4532    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4533   if (ref_str->subtype == FOURCC_vide) {
4534     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4535         ref_str->from_sample - 1, FALSE);
4536   } else {
4537     if (ref_str->from_sample >= 10)
4538       k_index = ref_str->from_sample - 10;
4539     else
4540       k_index = 0;
4541   }
4542
4543   target_ts =
4544       ref_str->samples[k_index].timestamp +
4545       ref_str->samples[k_index].pts_offset;
4546
4547   /* get current segment for that stream */
4548   seg = &ref_str->segments[ref_str->segment_index];
4549   /* Use segment start in original timescale for comparisons */
4550   seg_media_start_mov = seg->trak_media_start;
4551
4552   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4553       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4554       k_index, target_ts, seg_media_start_mov,
4555       GST_TIME_ARGS (seg->media_start));
4556
4557   /* Crawl back through segments to find the one containing this I frame */
4558   while (target_ts < seg_media_start_mov) {
4559     GST_DEBUG_OBJECT (qtdemux,
4560         "keyframe position (sample %u) is out of segment %u " " target %"
4561         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4562         ref_str->segment_index, target_ts, seg_media_start_mov);
4563
4564     if (G_UNLIKELY (!ref_str->segment_index)) {
4565       /* Reached first segment, let's consider it's EOS */
4566       goto eos;
4567     }
4568     ref_str->segment_index--;
4569     seg = &ref_str->segments[ref_str->segment_index];
4570     /* Use segment start in original timescale for comparisons */
4571     seg_media_start_mov = seg->trak_media_start;
4572   }
4573   /* Calculate time position of the keyframe and where we should stop */
4574   k_pos =
4575       QTSTREAMTIME_TO_GSTTIME (ref_str,
4576       target_ts - seg->trak_media_start) + seg->time;
4577   last_stop =
4578       QTSTREAMTIME_TO_GSTTIME (ref_str,
4579       ref_str->samples[ref_str->from_sample].timestamp -
4580       seg->trak_media_start) + seg->time;
4581
4582   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4583       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4584       k_index, GST_TIME_ARGS (k_pos));
4585
4586   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4587   qtdemux->segment.position = last_stop;
4588   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4589       GST_TIME_ARGS (last_stop));
4590
4591   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4592     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4593     goto eos;
4594   }
4595
4596   ref_seg_idx = ref_str->segment_index;
4597   ref_k_index = k_index;
4598
4599   /* Align them all on this */
4600   for (n = 0; n < qtdemux->n_streams; n++) {
4601     guint32 index = 0;
4602     GstClockTime seg_time = 0;
4603     QtDemuxStream *str = qtdemux->streams[n];
4604
4605     /* aligning reference stream again might lead to backing up to yet another
4606      * keyframe (due to timestamp rounding issues),
4607      * potentially putting more load on downstream; so let's try to avoid */
4608     if (str == ref_str) {
4609       seg_idx = ref_seg_idx;
4610       seg = &str->segments[seg_idx];
4611       k_index = ref_k_index;
4612       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4613           "sample at index %d", n, ref_str->segment_index, k_index);
4614     } else {
4615       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4616       GST_DEBUG_OBJECT (qtdemux,
4617           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4618           seg_idx, GST_TIME_ARGS (k_pos));
4619
4620       /* get segment and time in the segment */
4621       seg = &str->segments[seg_idx];
4622       seg_time = k_pos - seg->time;
4623
4624       /* get the media time in the segment.
4625        * No adjustment for empty "filler" segments */
4626       if (seg->media_start != GST_CLOCK_TIME_NONE)
4627         seg_time += seg->media_start;
4628
4629       /* get the index of the sample with media time */
4630       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4631       GST_DEBUG_OBJECT (qtdemux,
4632           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4633           GST_TIME_ARGS (seg_time), index);
4634
4635       /* find previous keyframe */
4636       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4637     }
4638
4639     /* Remember until where we want to go */
4640     str->to_sample = str->from_sample - 1;
4641     /* Define our time position */
4642     target_ts =
4643         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4644     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4645     if (seg->media_start != GST_CLOCK_TIME_NONE)
4646       str->time_position -= seg->media_start;
4647
4648     /* Now seek back in time */
4649     gst_qtdemux_move_stream (qtdemux, str, k_index);
4650     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4651         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4652         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4653   }
4654
4655   return GST_FLOW_OK;
4656
4657 eos:
4658   return GST_FLOW_EOS;
4659 }
4660
4661 /*
4662  * Gets the current qt segment start, stop and position for the
4663  * given time offset. This is used in update_segment()
4664  */
4665 static void
4666 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4667     QtDemuxStream * stream, GstClockTime offset,
4668     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4669 {
4670   GstClockTime seg_time;
4671   GstClockTime start, stop, time;
4672   QtDemuxSegment *segment;
4673
4674   segment = &stream->segments[stream->segment_index];
4675
4676   /* get time in this segment */
4677   seg_time = (offset - segment->time) * segment->rate;
4678
4679   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4680       GST_TIME_ARGS (seg_time));
4681
4682   if (G_UNLIKELY (seg_time > segment->duration)) {
4683     GST_LOG_OBJECT (stream->pad,
4684         "seg_time > segment->duration %" GST_TIME_FORMAT,
4685         GST_TIME_ARGS (segment->duration));
4686     seg_time = segment->duration;
4687   }
4688
4689   /* qtdemux->segment.stop is in outside-time-realm, whereas
4690    * segment->media_stop is in track-time-realm.
4691    *
4692    * In order to compare the two, we need to bring segment.stop
4693    * into the track-time-realm
4694    *
4695    * FIXME - does this comment still hold? Don't see any conversion here */
4696
4697   stop = qtdemux->segment.stop;
4698   if (stop == GST_CLOCK_TIME_NONE)
4699     stop = qtdemux->segment.duration;
4700   if (stop == GST_CLOCK_TIME_NONE)
4701     stop = segment->media_stop;
4702   else
4703     stop =
4704         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4705
4706   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4707     start = segment->time + seg_time;
4708     time = offset;
4709     stop = start - seg_time + segment->duration;
4710   } else if (qtdemux->segment.rate >= 0) {
4711     start = MIN (segment->media_start + seg_time, stop);
4712     time = offset;
4713   } else {
4714     if (segment->media_start >= qtdemux->segment.start) {
4715       time = segment->time;
4716     } else {
4717       time = segment->time + (qtdemux->segment.start - segment->media_start);
4718     }
4719
4720     start = MAX (segment->media_start, qtdemux->segment.start);
4721     stop = MIN (segment->media_start + seg_time, stop);
4722   }
4723
4724   *_start = start;
4725   *_stop = stop;
4726   *_time = time;
4727 }
4728
4729 /*
4730  * Updates the qt segment used for the stream and pushes a new segment event
4731  * downstream on this stream's pad.
4732  */
4733 static gboolean
4734 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4735     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4736     GstClockTime * _stop)
4737 {
4738   QtDemuxSegment *segment;
4739   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4740   gdouble rate;
4741   GstEvent *event;
4742
4743   /* update the current segment */
4744   stream->segment_index = seg_idx;
4745
4746   /* get the segment */
4747   segment = &stream->segments[seg_idx];
4748
4749   if (G_UNLIKELY (offset < segment->time)) {
4750     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4751         GST_TIME_ARGS (segment->time));
4752     return FALSE;
4753   }
4754
4755   /* segment lies beyond total indicated duration */
4756   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4757           segment->time > qtdemux->segment.duration)) {
4758     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4759         " < segment->time %" GST_TIME_FORMAT,
4760         GST_TIME_ARGS (qtdemux->segment.duration),
4761         GST_TIME_ARGS (segment->time));
4762     return FALSE;
4763   }
4764
4765   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4766       &start, &stop, &time);
4767
4768   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4769       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4770       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4771
4772   /* combine global rate with that of the segment */
4773   rate = segment->rate * qtdemux->segment.rate;
4774
4775   /* Copy flags from main segment */
4776   stream->segment.flags = qtdemux->segment.flags;
4777
4778   /* update the segment values used for clipping */
4779   stream->segment.offset = qtdemux->segment.offset;
4780   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4781   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4782   stream->segment.rate = rate;
4783   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4784       stream->cslg_shift);
4785   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4786       stream->cslg_shift);
4787   stream->segment.time = time;
4788   stream->segment.position = stream->segment.start;
4789
4790   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4791       &stream->segment);
4792
4793   /* now prepare and send the segment */
4794   if (stream->pad) {
4795     event = gst_event_new_segment (&stream->segment);
4796     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4797       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4798     }
4799     gst_pad_push_event (stream->pad, event);
4800     /* assume we can send more data now */
4801     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4802     /* clear to send tags on this pad now */
4803     gst_qtdemux_push_tags (qtdemux, stream);
4804   }
4805
4806   if (_start)
4807     *_start = start;
4808   if (_stop)
4809     *_stop = stop;
4810
4811   return TRUE;
4812 }
4813
4814 /* activate the given segment number @seg_idx of @stream at time @offset.
4815  * @offset is an absolute global position over all the segments.
4816  *
4817  * This will push out a NEWSEGMENT event with the right values and
4818  * position the stream index to the first decodable sample before
4819  * @offset.
4820  */
4821 static gboolean
4822 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4823     guint32 seg_idx, GstClockTime offset)
4824 {
4825   QtDemuxSegment *segment;
4826   guint32 index, kf_index;
4827   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4828
4829   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4830       seg_idx, GST_TIME_ARGS (offset));
4831
4832   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4833           &start, &stop))
4834     return FALSE;
4835
4836   segment = &stream->segments[stream->segment_index];
4837
4838   /* in the fragmented case, we pick a fragment that starts before our
4839    * desired position and rely on downstream to wait for a keyframe
4840    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4841    * tfra entries tells us which trun/sample the key unit is in, but we don't
4842    * make use of this additional information at the moment) */
4843   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4844     stream->to_sample = G_MAXUINT32;
4845     return TRUE;
4846   } else {
4847     /* well, it will be taken care of below */
4848     qtdemux->fragmented_seek_pending = FALSE;
4849     /* FIXME ideally the do_fragmented_seek can be done right here,
4850      * rather than at loop level
4851      * (which might even allow handling edit lists in a fragmented file) */
4852   }
4853
4854   /* We don't need to look for a sample in push-based */
4855   if (!qtdemux->pullbased)
4856     return TRUE;
4857
4858   /* and move to the keyframe before the indicated media time of the
4859    * segment */
4860   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4861     if (qtdemux->segment.rate >= 0) {
4862       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4863       stream->to_sample = G_MAXUINT32;
4864       GST_DEBUG_OBJECT (stream->pad,
4865           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4866           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4867           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4868     } else {
4869       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4870       stream->to_sample = index;
4871       GST_DEBUG_OBJECT (stream->pad,
4872           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4873           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4874           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4875     }
4876   } else {
4877     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4878         "this is an empty segment");
4879     return TRUE;
4880   }
4881
4882   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4883    * encountered an error and printed a message so we return appropriately */
4884   if (index == -1)
4885     return FALSE;
4886
4887   /* we're at the right spot */
4888   if (index == stream->sample_index) {
4889     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4890     return TRUE;
4891   }
4892
4893   /* find keyframe of the target index */
4894   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4895
4896 /* *INDENT-OFF* */
4897 /* indent does stupid stuff with stream->samples[].timestamp */
4898
4899   /* if we move forwards, we don't have to go back to the previous
4900    * keyframe since we already sent that. We can also just jump to
4901    * the keyframe right before the target index if there is one. */
4902   if (index > stream->sample_index) {
4903     /* moving forwards check if we move past a keyframe */
4904     if (kf_index > stream->sample_index) {
4905       GST_DEBUG_OBJECT (stream->pad,
4906            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4907            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4908            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4909       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4910     } else {
4911       GST_DEBUG_OBJECT (stream->pad,
4912           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4913           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4914           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4915     }
4916   } else {
4917     GST_DEBUG_OBJECT (stream->pad,
4918         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4919         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4920         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4921     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4922   }
4923
4924 /* *INDENT-ON* */
4925
4926   return TRUE;
4927 }
4928
4929 /* prepare to get the current sample of @stream, getting essential values.
4930  *
4931  * This function will also prepare and send the segment when needed.
4932  *
4933  * Return FALSE if the stream is EOS.
4934  *
4935  * PULL-BASED
4936  */
4937 static gboolean
4938 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4939     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4940     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4941     gboolean * keyframe)
4942 {
4943   QtDemuxSample *sample;
4944   GstClockTime time_position;
4945   guint32 seg_idx;
4946
4947   g_return_val_if_fail (stream != NULL, FALSE);
4948
4949   time_position = stream->time_position;
4950   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4951     goto eos;
4952
4953   seg_idx = stream->segment_index;
4954   if (G_UNLIKELY (seg_idx == -1)) {
4955     /* find segment corresponding to time_position if we are looking
4956      * for a segment. */
4957     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4958   }
4959
4960   /* different segment, activate it, sample_index will be set. */
4961   if (G_UNLIKELY (stream->segment_index != seg_idx))
4962     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4963
4964   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4965                   segment_index]))) {
4966     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4967
4968     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4969         " prepare empty sample");
4970
4971     *empty = TRUE;
4972     *pts = *dts = time_position;
4973     *duration = seg->duration - (time_position - seg->time);
4974
4975     return TRUE;
4976   }
4977
4978   *empty = FALSE;
4979
4980   if (stream->sample_index == -1)
4981     stream->sample_index = 0;
4982
4983   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4984       stream->sample_index, stream->n_samples);
4985
4986   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4987     if (!qtdemux->fragmented)
4988       goto eos;
4989
4990     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4991     do {
4992       GstFlowReturn flow;
4993
4994       GST_OBJECT_LOCK (qtdemux);
4995       flow = qtdemux_add_fragmented_samples (qtdemux);
4996       GST_OBJECT_UNLOCK (qtdemux);
4997
4998       if (flow != GST_FLOW_OK)
4999         goto eos;
5000     }
5001     while (stream->sample_index >= stream->n_samples);
5002   }
5003
5004   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5005     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5006         stream->sample_index);
5007     return FALSE;
5008   }
5009
5010   /* now get the info for the sample we're at */
5011   sample = &stream->samples[stream->sample_index];
5012
5013   *dts = QTSAMPLE_DTS (stream, sample);
5014   *pts = QTSAMPLE_PTS (stream, sample);
5015   *offset = sample->offset;
5016   *size = sample->size;
5017   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5018   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5019
5020   return TRUE;
5021
5022   /* special cases */
5023 eos:
5024   {
5025     stream->time_position = GST_CLOCK_TIME_NONE;
5026     return FALSE;
5027   }
5028 }
5029
5030 /* move to the next sample in @stream.
5031  *
5032  * Moves to the next segment when needed.
5033  */
5034 static void
5035 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5036 {
5037   QtDemuxSample *sample;
5038   QtDemuxSegment *segment;
5039
5040   /* get current segment */
5041   segment = &stream->segments[stream->segment_index];
5042
5043   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5044     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5045     goto next_segment;
5046   }
5047
5048   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5049     /* Mark the stream as EOS */
5050     GST_DEBUG_OBJECT (qtdemux,
5051         "reached max allowed sample %u, mark EOS", stream->to_sample);
5052     stream->time_position = GST_CLOCK_TIME_NONE;
5053     return;
5054   }
5055
5056   /* move to next sample */
5057   stream->sample_index++;
5058   stream->offset_in_sample = 0;
5059
5060   /* reached the last sample, we need the next segment */
5061   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5062     goto next_segment;
5063
5064   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5065     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5066         stream->sample_index);
5067     return;
5068   }
5069
5070   /* get next sample */
5071   sample = &stream->samples[stream->sample_index];
5072
5073   /* see if we are past the segment */
5074   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5075     goto next_segment;
5076
5077   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5078     /* inside the segment, update time_position, looks very familiar to
5079      * GStreamer segments, doesn't it? */
5080     stream->time_position =
5081         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5082   } else {
5083     /* not yet in segment, time does not yet increment. This means
5084      * that we are still prerolling keyframes to the decoder so it can
5085      * decode the first sample of the segment. */
5086     stream->time_position = segment->time;
5087   }
5088   return;
5089
5090   /* move to the next segment */
5091 next_segment:
5092   {
5093     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5094
5095     if (stream->segment_index == stream->n_segments - 1) {
5096       /* are we at the end of the last segment, we're EOS */
5097       stream->time_position = GST_CLOCK_TIME_NONE;
5098     } else {
5099       /* else we're only at the end of the current segment */
5100       stream->time_position = segment->stop_time;
5101     }
5102     /* make sure we select a new segment */
5103
5104     /* accumulate previous segments */
5105     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5106       stream->accumulated_base +=
5107           (stream->segment.stop -
5108           stream->segment.start) / ABS (stream->segment.rate);
5109
5110     stream->segment_index = -1;
5111   }
5112 }
5113
5114 static void
5115 gst_qtdemux_sync_streams (GstQTDemux * demux)
5116 {
5117   gint i;
5118
5119   if (demux->n_streams <= 1)
5120     return;
5121
5122   for (i = 0; i < demux->n_streams; i++) {
5123     QtDemuxStream *stream;
5124     GstClockTime end_time;
5125
5126     stream = demux->streams[i];
5127
5128     if (!stream->pad)
5129       continue;
5130
5131     /* TODO advance time on subtitle streams here, if any some day */
5132
5133     /* some clips/trailers may have unbalanced streams at the end,
5134      * so send EOS on shorter stream to prevent stalling others */
5135
5136     /* do not mess with EOS if SEGMENT seeking */
5137     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5138       continue;
5139
5140     if (demux->pullbased) {
5141       /* loop mode is sample time based */
5142       if (!STREAM_IS_EOS (stream))
5143         continue;
5144     } else {
5145       /* push mode is byte position based */
5146       if (stream->n_samples &&
5147           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5148         continue;
5149     }
5150
5151     if (stream->sent_eos)
5152       continue;
5153
5154     /* only act if some gap */
5155     end_time = stream->segments[stream->n_segments - 1].stop_time;
5156     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5157         ", stream end: %" GST_TIME_FORMAT,
5158         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5159     if (GST_CLOCK_TIME_IS_VALID (end_time)
5160         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5161       GstEvent *event;
5162
5163       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5164           GST_PAD_NAME (stream->pad));
5165       stream->sent_eos = TRUE;
5166       event = gst_event_new_eos ();
5167       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5168         gst_event_set_seqnum (event, demux->segment_seqnum);
5169       gst_pad_push_event (stream->pad, event);
5170     }
5171   }
5172 }
5173
5174 /* EOS and NOT_LINKED need to be combined. This means that we return:
5175  *
5176  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5177  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5178  */
5179 static GstFlowReturn
5180 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5181     GstFlowReturn ret)
5182 {
5183   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5184
5185   if (stream->pad)
5186     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5187         ret);
5188   else
5189     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5190
5191   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5192   return ret;
5193 }
5194
5195 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5196  * completely clipped
5197  *
5198  * Should be used only with raw buffers */
5199 static GstBuffer *
5200 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5201     GstBuffer * buf)
5202 {
5203   guint64 start, stop, cstart, cstop, diff;
5204   GstClockTime pts, duration;
5205   gsize size, osize;
5206   gint num_rate, denom_rate;
5207   gint frame_size;
5208   gboolean clip_data;
5209   guint offset;
5210
5211   osize = size = gst_buffer_get_size (buf);
5212   offset = 0;
5213
5214   /* depending on the type, setup the clip parameters */
5215   if (stream->subtype == FOURCC_soun) {
5216     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5217     num_rate = GST_SECOND;
5218     denom_rate = (gint) CUR_STREAM (stream)->rate;
5219     clip_data = TRUE;
5220   } else if (stream->subtype == FOURCC_vide) {
5221     frame_size = size;
5222     num_rate = CUR_STREAM (stream)->fps_n;
5223     denom_rate = CUR_STREAM (stream)->fps_d;
5224     clip_data = FALSE;
5225   } else
5226     goto wrong_type;
5227
5228   if (frame_size <= 0)
5229     goto bad_frame_size;
5230
5231   /* we can only clip if we have a valid pts */
5232   pts = GST_BUFFER_PTS (buf);
5233   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5234     goto no_pts;
5235
5236   duration = GST_BUFFER_DURATION (buf);
5237
5238   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5239     duration =
5240         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5241   }
5242
5243   start = pts;
5244   stop = start + duration;
5245
5246   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5247               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5248     goto clipped;
5249
5250   /* see if some clipping happened */
5251   diff = cstart - start;
5252   if (diff > 0) {
5253     pts += diff;
5254     duration -= diff;
5255
5256     if (clip_data) {
5257       /* bring clipped time to samples and to bytes */
5258       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5259       diff *= frame_size;
5260
5261       GST_DEBUG_OBJECT (qtdemux,
5262           "clipping start to %" GST_TIME_FORMAT " %"
5263           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5264
5265       offset = diff;
5266       size -= diff;
5267     }
5268   }
5269   diff = stop - cstop;
5270   if (diff > 0) {
5271     duration -= diff;
5272
5273     if (clip_data) {
5274       /* bring clipped time to samples and then to bytes */
5275       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5276       diff *= frame_size;
5277       GST_DEBUG_OBJECT (qtdemux,
5278           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5279           " bytes", GST_TIME_ARGS (cstop), diff);
5280       size -= diff;
5281     }
5282   }
5283
5284   if (offset != 0 || size != osize)
5285     gst_buffer_resize (buf, offset, size);
5286
5287   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5288   GST_BUFFER_PTS (buf) = pts;
5289   GST_BUFFER_DURATION (buf) = duration;
5290
5291   return buf;
5292
5293   /* dropped buffer */
5294 wrong_type:
5295   {
5296     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5297     return buf;
5298   }
5299 bad_frame_size:
5300   {
5301     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5302     return buf;
5303   }
5304 no_pts:
5305   {
5306     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5307     return buf;
5308   }
5309 clipped:
5310   {
5311     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5312     gst_buffer_unref (buf);
5313     return NULL;
5314   }
5315 }
5316
5317 static GstBuffer *
5318 gst_qtdemux_align_buffer (GstQTDemux * demux,
5319     GstBuffer * buffer, gsize alignment)
5320 {
5321   GstMapInfo map;
5322
5323   gst_buffer_map (buffer, &map, GST_MAP_READ);
5324
5325   if (map.size < sizeof (guintptr)) {
5326     gst_buffer_unmap (buffer, &map);
5327     return buffer;
5328   }
5329
5330   if (((guintptr) map.data) & (alignment - 1)) {
5331     GstBuffer *new_buffer;
5332     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5333
5334     new_buffer = gst_buffer_new_allocate (NULL,
5335         gst_buffer_get_size (buffer), &params);
5336
5337     /* Copy data "by hand", so ensure alignment is kept: */
5338     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5339
5340     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5341     GST_DEBUG_OBJECT (demux,
5342         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5343         alignment);
5344
5345     gst_buffer_unmap (buffer, &map);
5346     gst_buffer_unref (buffer);
5347
5348     return new_buffer;
5349   }
5350
5351   gst_buffer_unmap (buffer, &map);
5352   return buffer;
5353 }
5354
5355 /* the input buffer metadata must be writable,
5356  * but time/duration etc not yet set and need not be preserved */
5357 static GstBuffer *
5358 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5359     GstBuffer * buf)
5360 {
5361   GstMapInfo map;
5362   guint nsize = 0;
5363   gchar *str;
5364
5365   /* not many cases for now */
5366   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5367     /* send a one time dvd clut event */
5368     if (stream->pending_event && stream->pad)
5369       gst_pad_push_event (stream->pad, stream->pending_event);
5370     stream->pending_event = NULL;
5371   }
5372
5373   if (G_UNLIKELY (stream->subtype != FOURCC_text
5374           && stream->subtype != FOURCC_sbtl &&
5375           stream->subtype != FOURCC_subp)) {
5376     return buf;
5377   }
5378
5379   gst_buffer_map (buf, &map, GST_MAP_READ);
5380
5381   /* empty buffer is sent to terminate previous subtitle */
5382   if (map.size <= 2) {
5383     gst_buffer_unmap (buf, &map);
5384     gst_buffer_unref (buf);
5385     return NULL;
5386   }
5387   if (stream->subtype == FOURCC_subp) {
5388     /* That's all the processing needed for subpictures */
5389     gst_buffer_unmap (buf, &map);
5390     return buf;
5391   }
5392
5393   nsize = GST_READ_UINT16_BE (map.data);
5394   nsize = MIN (nsize, map.size - 2);
5395
5396   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5397       nsize, map.size);
5398
5399   /* takes care of UTF-8 validation or UTF-16 recognition,
5400    * no other encoding expected */
5401   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5402   gst_buffer_unmap (buf, &map);
5403   if (str) {
5404     gst_buffer_unref (buf);
5405     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5406   } else {
5407     /* this should not really happen unless the subtitle is corrupted */
5408     gst_buffer_unref (buf);
5409     buf = NULL;
5410   }
5411
5412   /* FIXME ? convert optional subsequent style info to markup */
5413
5414   return buf;
5415 }
5416
5417 /* Sets a buffer's attributes properly and pushes it downstream.
5418  * Also checks for additional actions and custom processing that may
5419  * need to be done first.
5420  */
5421 static GstFlowReturn
5422 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5423     QtDemuxStream * stream, GstBuffer * buf,
5424     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5425     gboolean keyframe, GstClockTime position, guint64 byte_position)
5426 {
5427   GstFlowReturn ret = GST_FLOW_OK;
5428
5429   /* offset the timestamps according to the edit list */
5430
5431   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5432     gchar *url;
5433     GstMapInfo map;
5434
5435     gst_buffer_map (buf, &map, GST_MAP_READ);
5436     url = g_strndup ((gchar *) map.data, map.size);
5437     gst_buffer_unmap (buf, &map);
5438     if (url != NULL && strlen (url) != 0) {
5439       /* we have RTSP redirect now */
5440       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5441           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5442               gst_structure_new ("redirect",
5443                   "new-location", G_TYPE_STRING, url, NULL)));
5444       qtdemux->posted_redirect = TRUE;
5445     } else {
5446       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5447           "posting");
5448     }
5449     g_free (url);
5450   }
5451
5452   /* position reporting */
5453   if (qtdemux->segment.rate >= 0) {
5454     qtdemux->segment.position = position;
5455     gst_qtdemux_sync_streams (qtdemux);
5456   }
5457
5458   if (G_UNLIKELY (!stream->pad)) {
5459     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5460     gst_buffer_unref (buf);
5461     goto exit;
5462   }
5463
5464   /* send out pending buffers */
5465   while (stream->buffers) {
5466     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5467
5468     if (G_UNLIKELY (stream->discont)) {
5469       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5470       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5471       stream->discont = FALSE;
5472     } else {
5473       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5474     }
5475
5476     if (stream->alignment > 1)
5477       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5478     gst_pad_push (stream->pad, buffer);
5479
5480     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5481   }
5482
5483   /* we're going to modify the metadata */
5484   buf = gst_buffer_make_writable (buf);
5485
5486   if (G_UNLIKELY (stream->need_process))
5487     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5488
5489   if (!buf) {
5490     goto exit;
5491   }
5492
5493   GST_BUFFER_DTS (buf) = dts;
5494   GST_BUFFER_PTS (buf) = pts;
5495   GST_BUFFER_DURATION (buf) = duration;
5496   GST_BUFFER_OFFSET (buf) = -1;
5497   GST_BUFFER_OFFSET_END (buf) = -1;
5498
5499   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5500     gst_buffer_append_memory (buf,
5501         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5502
5503   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5504     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5505   }
5506 #if 0
5507   if (G_UNLIKELY (qtdemux->element_index)) {
5508     GstClockTime stream_time;
5509
5510     stream_time =
5511         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5512         timestamp);
5513     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5514       GST_LOG_OBJECT (qtdemux,
5515           "adding association %" GST_TIME_FORMAT "-> %"
5516           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5517       gst_index_add_association (qtdemux->element_index,
5518           qtdemux->index_id,
5519           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5520           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5521           GST_FORMAT_BYTES, byte_position, NULL);
5522     }
5523   }
5524 #endif
5525
5526   if (stream->need_clip)
5527     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5528
5529   if (G_UNLIKELY (buf == NULL))
5530     goto exit;
5531
5532   if (G_UNLIKELY (stream->discont)) {
5533     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5534     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5535     stream->discont = FALSE;
5536   } else {
5537     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5538   }
5539
5540   if (!keyframe) {
5541     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5542     stream->on_keyframe = FALSE;
5543   } else {
5544     stream->on_keyframe = TRUE;
5545   }
5546
5547
5548   GST_LOG_OBJECT (qtdemux,
5549       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5550       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5551       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5552       GST_PAD_NAME (stream->pad));
5553
5554   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5555     GstStructure *crypto_info;
5556     QtDemuxCencSampleSetInfo *info =
5557         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5558     gint index;
5559     GstEvent *event;
5560
5561     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5562       gst_pad_push_event (stream->pad, event);
5563     }
5564
5565     if (info->crypto_info == NULL) {
5566       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5567       gst_buffer_unref (buf);
5568       goto exit;
5569     }
5570
5571     /* The end of the crypto_info array matches our n_samples position,
5572      * so count backward from there */
5573     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5574     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5575       /* steal structure from array */
5576       crypto_info = g_ptr_array_index (info->crypto_info, index);
5577       g_ptr_array_index (info->crypto_info, index) = NULL;
5578       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5579           info->crypto_info->len);
5580       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5581         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5582     } else {
5583       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5584           index, stream->sample_index);
5585     }
5586   }
5587
5588   if (stream->alignment > 1)
5589     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5590
5591   ret = gst_pad_push (stream->pad, buf);
5592
5593   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5594     /* mark position in stream, we'll need this to know when to send GAP event */
5595     stream->segment.position = pts + duration;
5596   }
5597
5598 exit:
5599   return ret;
5600 }
5601
5602 static const QtDemuxRandomAccessEntry *
5603 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5604     GstClockTime pos, gboolean after)
5605 {
5606   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5607   guint n_entries = stream->n_ra_entries;
5608   guint i;
5609
5610   /* we assume the table is sorted */
5611   for (i = 0; i < n_entries; ++i) {
5612     if (entries[i].ts > pos)
5613       break;
5614   }
5615
5616   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5617    * probably okay to assume that the index lists the very first fragment */
5618   if (i == 0)
5619     return &entries[0];
5620
5621   if (after)
5622     return &entries[i];
5623   else
5624     return &entries[i - 1];
5625 }
5626
5627 static gboolean
5628 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5629 {
5630   const QtDemuxRandomAccessEntry *best_entry = NULL;
5631   guint i;
5632
5633   GST_OBJECT_LOCK (qtdemux);
5634
5635   g_assert (qtdemux->n_streams > 0);
5636
5637   /* first see if we can determine where to go to using mfra,
5638    * before we start clearing things */
5639   for (i = 0; i < qtdemux->n_streams; i++) {
5640     const QtDemuxRandomAccessEntry *entry;
5641     QtDemuxStream *stream;
5642     gboolean is_audio_or_video;
5643
5644     stream = qtdemux->streams[i];
5645
5646     if (stream->ra_entries == NULL)
5647       continue;
5648
5649     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5650       is_audio_or_video = TRUE;
5651     else
5652       is_audio_or_video = FALSE;
5653
5654     entry =
5655         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5656         stream->time_position, !is_audio_or_video);
5657
5658     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5659         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5660
5661     stream->pending_seek = entry;
5662
5663     /* decide position to jump to just based on audio/video tracks, not subs */
5664     if (!is_audio_or_video)
5665       continue;
5666
5667     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5668       best_entry = entry;
5669   }
5670
5671   /* no luck, will handle seek otherwise */
5672   if (best_entry == NULL) {
5673     GST_OBJECT_UNLOCK (qtdemux);
5674     return FALSE;
5675   }
5676
5677   /* ok, now we can prepare for processing as of located moof */
5678   for (i = 0; i < qtdemux->n_streams; i++) {
5679     QtDemuxStream *stream;
5680
5681     stream = qtdemux->streams[i];
5682
5683     g_free (stream->samples);
5684     stream->samples = NULL;
5685     stream->n_samples = 0;
5686     stream->stbl_index = -1;    /* no samples have yet been parsed */
5687     stream->sample_index = -1;
5688
5689     if (stream->protection_scheme_info) {
5690       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5691       if (stream->protection_scheme_type == FOURCC_cenc) {
5692         QtDemuxCencSampleSetInfo *info =
5693             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5694         if (info->crypto_info) {
5695           g_ptr_array_free (info->crypto_info, TRUE);
5696           info->crypto_info = NULL;
5697         }
5698       }
5699     }
5700   }
5701
5702   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5703       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5704       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5705       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5706
5707   qtdemux->moof_offset = best_entry->moof_offset;
5708
5709   qtdemux_add_fragmented_samples (qtdemux);
5710
5711   GST_OBJECT_UNLOCK (qtdemux);
5712   return TRUE;
5713 }
5714
5715 static GstFlowReturn
5716 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5717 {
5718   GstFlowReturn ret = GST_FLOW_OK;
5719   GstBuffer *buf = NULL;
5720   QtDemuxStream *stream;
5721   GstClockTime min_time;
5722   guint64 offset = 0;
5723   GstClockTime dts = GST_CLOCK_TIME_NONE;
5724   GstClockTime pts = GST_CLOCK_TIME_NONE;
5725   GstClockTime duration = 0;
5726   gboolean keyframe = FALSE;
5727   guint sample_size = 0;
5728   gboolean empty = 0;
5729   guint size;
5730   gint index;
5731   gint i;
5732
5733   gst_qtdemux_push_pending_newsegment (qtdemux);
5734
5735   if (qtdemux->fragmented_seek_pending) {
5736     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5737     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
5738       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5739       qtdemux->fragmented_seek_pending = FALSE;
5740     } else {
5741       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
5742     }
5743   }
5744
5745   /* Figure out the next stream sample to output, min_time is expressed in
5746    * global time and runs over the edit list segments. */
5747   min_time = G_MAXUINT64;
5748   index = -1;
5749   for (i = 0; i < qtdemux->n_streams; i++) {
5750     GstClockTime position;
5751
5752     stream = qtdemux->streams[i];
5753     position = stream->time_position;
5754
5755     /* position of -1 is EOS */
5756     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5757       min_time = position;
5758       index = i;
5759     }
5760   }
5761   /* all are EOS */
5762   if (G_UNLIKELY (index == -1)) {
5763     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5764     goto eos;
5765   }
5766
5767   /* check for segment end */
5768   if (G_UNLIKELY (qtdemux->segment.stop != -1
5769           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5770               || (qtdemux->segment.rate < 0
5771                   && qtdemux->segment.start > min_time))
5772           && qtdemux->streams[index]->on_keyframe)) {
5773     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5774     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5775     goto eos_stream;
5776   }
5777
5778   /* gap events for subtitle streams */
5779   for (i = 0; i < qtdemux->n_streams; i++) {
5780     stream = qtdemux->streams[i];
5781     if (stream->pad && (stream->subtype == FOURCC_subp
5782             || stream->subtype == FOURCC_text
5783             || stream->subtype == FOURCC_sbtl)) {
5784       /* send one second gap events until the stream catches up */
5785       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5786       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5787           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5788           stream->segment.position + GST_SECOND < min_time) {
5789         GstEvent *gap =
5790             gst_event_new_gap (stream->segment.position, GST_SECOND);
5791         gst_pad_push_event (stream->pad, gap);
5792         stream->segment.position += GST_SECOND;
5793       }
5794     }
5795   }
5796
5797   stream = qtdemux->streams[index];
5798   /* fetch info for the current sample of this stream */
5799   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5800               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5801     goto eos_stream;
5802
5803   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5804   if (stream->new_caps) {
5805     gst_qtdemux_configure_stream (qtdemux, stream);
5806     qtdemux_do_allocation (qtdemux, stream);
5807   }
5808
5809   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5810   if (G_UNLIKELY (qtdemux->
5811           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5812     if (stream->subtype == FOURCC_vide && !keyframe) {
5813       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5814       goto next;
5815     }
5816   }
5817
5818   GST_DEBUG_OBJECT (qtdemux,
5819       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5820       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5821       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5822       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5823
5824   if (G_UNLIKELY (empty)) {
5825     /* empty segment, push a gap if there's a second or more
5826      * difference and move to the next one */
5827     if ((pts + duration - stream->segment.position) >= GST_SECOND)
5828       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5829     stream->segment.position = pts + duration;
5830     goto next;
5831   }
5832
5833   /* hmm, empty sample, skip and move to next sample */
5834   if (G_UNLIKELY (sample_size <= 0))
5835     goto next;
5836
5837   /* last pushed sample was out of boundary, goto next sample */
5838   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5839     goto next;
5840
5841   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5842     size = sample_size;
5843   } else {
5844     GST_DEBUG_OBJECT (qtdemux,
5845         "size %d larger than stream max_buffer_size %d, trimming",
5846         sample_size, stream->max_buffer_size);
5847     size =
5848         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5849   }
5850
5851   if (qtdemux->cenc_aux_info_offset > 0) {
5852     GstMapInfo map;
5853     GstByteReader br;
5854     GstBuffer *aux_info = NULL;
5855
5856     /* pull the data stored before the sample */
5857     ret =
5858         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5859         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5860     if (G_UNLIKELY (ret != GST_FLOW_OK))
5861       goto beach;
5862     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5863     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5864     gst_byte_reader_init (&br, map.data + 8, map.size);
5865     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5866             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5867       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5868       gst_buffer_unmap (aux_info, &map);
5869       gst_buffer_unref (aux_info);
5870       ret = GST_FLOW_ERROR;
5871       goto beach;
5872     }
5873     gst_buffer_unmap (aux_info, &map);
5874     gst_buffer_unref (aux_info);
5875   }
5876
5877   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5878       offset);
5879
5880   if (stream->use_allocator) {
5881     /* if we have a per-stream allocator, use it */
5882     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5883   }
5884
5885   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5886       size, &buf);
5887   if (G_UNLIKELY (ret != GST_FLOW_OK))
5888     goto beach;
5889
5890   if (size != sample_size) {
5891     pts += gst_util_uint64_scale_int (GST_SECOND,
5892         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5893         stream->timescale);
5894     dts +=
5895         gst_util_uint64_scale_int (GST_SECOND,
5896         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5897         stream->timescale);
5898     duration =
5899         gst_util_uint64_scale_int (GST_SECOND,
5900         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5901   }
5902
5903   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5904       dts, pts, duration, keyframe, min_time, offset);
5905
5906   if (size != sample_size) {
5907     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5908     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5909
5910     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5911         sample->timestamp +
5912         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5913     if (time_position >= segment->media_start) {
5914       /* inside the segment, update time_position, looks very familiar to
5915        * GStreamer segments, doesn't it? */
5916       stream->time_position = (time_position - segment->media_start) +
5917           segment->time;
5918     } else {
5919       /* not yet in segment, time does not yet increment. This means
5920        * that we are still prerolling keyframes to the decoder so it can
5921        * decode the first sample of the segment. */
5922       stream->time_position = segment->time;
5923     }
5924   }
5925
5926   /* combine flows */
5927   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5928   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5929    * we have no more data for the pad to push */
5930   if (ret == GST_FLOW_EOS)
5931     ret = GST_FLOW_OK;
5932
5933   stream->offset_in_sample += size;
5934   if (stream->offset_in_sample >= sample_size) {
5935     gst_qtdemux_advance_sample (qtdemux, stream);
5936   }
5937   goto beach;
5938
5939 next:
5940   gst_qtdemux_advance_sample (qtdemux, stream);
5941
5942 beach:
5943   return ret;
5944
5945   /* special cases */
5946 eos:
5947   {
5948     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5949     ret = GST_FLOW_EOS;
5950     goto beach;
5951   }
5952 eos_stream:
5953   {
5954     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5955     /* EOS will be raised if all are EOS */
5956     ret = GST_FLOW_OK;
5957     goto beach;
5958   }
5959 }
5960
5961 static void
5962 gst_qtdemux_loop (GstPad * pad)
5963 {
5964   GstQTDemux *qtdemux;
5965   guint64 cur_offset;
5966   GstFlowReturn ret;
5967
5968   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5969
5970   cur_offset = qtdemux->offset;
5971   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5972       cur_offset, qt_demux_state_string (qtdemux->state));
5973
5974   switch (qtdemux->state) {
5975     case QTDEMUX_STATE_INITIAL:
5976     case QTDEMUX_STATE_HEADER:
5977       ret = gst_qtdemux_loop_state_header (qtdemux);
5978       break;
5979     case QTDEMUX_STATE_MOVIE:
5980       ret = gst_qtdemux_loop_state_movie (qtdemux);
5981       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5982         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5983       }
5984       break;
5985     default:
5986       /* ouch */
5987       goto invalid_state;
5988   }
5989
5990   /* if something went wrong, pause */
5991   if (ret != GST_FLOW_OK)
5992     goto pause;
5993
5994 done:
5995   gst_object_unref (qtdemux);
5996   return;
5997
5998   /* ERRORS */
5999 invalid_state:
6000   {
6001     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6002         (NULL), ("streaming stopped, invalid state"));
6003     gst_pad_pause_task (pad);
6004     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6005     goto done;
6006   }
6007 pause:
6008   {
6009     const gchar *reason = gst_flow_get_name (ret);
6010
6011     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6012
6013     gst_pad_pause_task (pad);
6014
6015     /* fatal errors need special actions */
6016     /* check EOS */
6017     if (ret == GST_FLOW_EOS) {
6018       if (qtdemux->n_streams == 0) {
6019         /* we have no streams, post an error */
6020         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6021       }
6022       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6023         gint64 stop;
6024
6025         if ((stop = qtdemux->segment.stop) == -1)
6026           stop = qtdemux->segment.duration;
6027
6028         if (qtdemux->segment.rate >= 0) {
6029           GstMessage *message;
6030           GstEvent *event;
6031
6032           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6033           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6034               GST_FORMAT_TIME, stop);
6035           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6036           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6037             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6038             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6039           }
6040           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6041           gst_qtdemux_push_event (qtdemux, event);
6042         } else {
6043           GstMessage *message;
6044           GstEvent *event;
6045
6046           /*  For Reverse Playback */
6047           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6048           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6049               GST_FORMAT_TIME, qtdemux->segment.start);
6050           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6051               qtdemux->segment.start);
6052           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6053             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6054             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6055           }
6056           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6057           gst_qtdemux_push_event (qtdemux, event);
6058         }
6059       } else {
6060         GstEvent *event;
6061
6062         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6063         event = gst_event_new_eos ();
6064         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6065           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6066         gst_qtdemux_push_event (qtdemux, event);
6067       }
6068     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6069       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6070       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6071     }
6072     goto done;
6073   }
6074 }
6075
6076 /*
6077  * has_next_entry
6078  *
6079  * Returns if there are samples to be played.
6080  */
6081 static gboolean
6082 has_next_entry (GstQTDemux * demux)
6083 {
6084   QtDemuxStream *stream;
6085   int i;
6086
6087   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6088
6089   for (i = 0; i < demux->n_streams; i++) {
6090     stream = demux->streams[i];
6091
6092     if (stream->sample_index == -1) {
6093       stream->sample_index = 0;
6094       stream->offset_in_sample = 0;
6095     }
6096
6097     if (stream->sample_index >= stream->n_samples) {
6098       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6099       continue;
6100     }
6101     GST_DEBUG_OBJECT (demux, "Found a sample");
6102     return TRUE;
6103   }
6104
6105   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6106   return FALSE;
6107 }
6108
6109 /*
6110  * next_entry_size
6111  *
6112  * Returns the size of the first entry at the current offset.
6113  * If -1, there are none (which means EOS or empty file).
6114  */
6115 static guint64
6116 next_entry_size (GstQTDemux * demux)
6117 {
6118   QtDemuxStream *stream;
6119   int i;
6120   int smallidx = -1;
6121   guint64 smalloffs = (guint64) - 1;
6122   QtDemuxSample *sample;
6123
6124   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6125       demux->offset);
6126
6127   for (i = 0; i < demux->n_streams; i++) {
6128     stream = demux->streams[i];
6129
6130     if (stream->sample_index == -1) {
6131       stream->sample_index = 0;
6132       stream->offset_in_sample = 0;
6133     }
6134
6135     if (stream->sample_index >= stream->n_samples) {
6136       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6137       continue;
6138     }
6139
6140     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6141       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6142           stream->sample_index);
6143       return -1;
6144     }
6145
6146     sample = &stream->samples[stream->sample_index];
6147
6148     GST_LOG_OBJECT (demux,
6149         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6150         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6151         sample->offset, sample->size);
6152
6153     if (((smalloffs == -1)
6154             || (sample->offset < smalloffs)) && (sample->size)) {
6155       smallidx = i;
6156       smalloffs = sample->offset;
6157     }
6158   }
6159
6160   GST_LOG_OBJECT (demux,
6161       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6162       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6163
6164   if (smallidx == -1)
6165     return -1;
6166
6167   stream = demux->streams[smallidx];
6168   sample = &stream->samples[stream->sample_index];
6169
6170   if (sample->offset >= demux->offset) {
6171     demux->todrop = sample->offset - demux->offset;
6172     return sample->size + demux->todrop;
6173   }
6174
6175   GST_DEBUG_OBJECT (demux,
6176       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6177   return -1;
6178 }
6179
6180 static void
6181 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6182 {
6183   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6184
6185   gst_element_post_message (GST_ELEMENT_CAST (demux),
6186       gst_message_new_element (GST_OBJECT_CAST (demux),
6187           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6188 }
6189
6190 static gboolean
6191 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6192 {
6193   GstEvent *event;
6194   gboolean res = 0;
6195
6196   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6197
6198   event =
6199       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6200       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6201       GST_SEEK_TYPE_NONE, -1);
6202
6203   /* store seqnum to drop flush events, they don't need to reach downstream */
6204   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6205   res = gst_pad_push_event (demux->sinkpad, event);
6206   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6207
6208   return res;
6209 }
6210
6211 /* check for seekable upstream, above and beyond a mere query */
6212 static void
6213 gst_qtdemux_check_seekability (GstQTDemux * demux)
6214 {
6215   GstQuery *query;
6216   gboolean seekable = FALSE;
6217   gint64 start = -1, stop = -1;
6218
6219   if (demux->upstream_size)
6220     return;
6221
6222   if (demux->upstream_format_is_time)
6223     return;
6224
6225   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6226   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6227     GST_DEBUG_OBJECT (demux, "seeking query failed");
6228     goto done;
6229   }
6230
6231   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6232
6233   /* try harder to query upstream size if we didn't get it the first time */
6234   if (seekable && stop == -1) {
6235     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6236     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6237   }
6238
6239   /* if upstream doesn't know the size, it's likely that it's not seekable in
6240    * practice even if it technically may be seekable */
6241   if (seekable && (start != 0 || stop <= start)) {
6242     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6243     seekable = FALSE;
6244   }
6245
6246 done:
6247   gst_query_unref (query);
6248
6249   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6250       G_GUINT64_FORMAT ")", seekable, start, stop);
6251   demux->upstream_seekable = seekable;
6252   demux->upstream_size = seekable ? stop : -1;
6253 }
6254
6255 static void
6256 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6257 {
6258   g_return_if_fail (bytes <= demux->todrop);
6259
6260   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6261   gst_adapter_flush (demux->adapter, bytes);
6262   demux->neededbytes -= bytes;
6263   demux->offset += bytes;
6264   demux->todrop -= bytes;
6265 }
6266
6267 static void
6268 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6269 {
6270   if (G_UNLIKELY (demux->pending_newsegment)) {
6271     gint i;
6272
6273     gst_qtdemux_push_pending_newsegment (demux);
6274     /* clear to send tags on all streams */
6275     for (i = 0; i < demux->n_streams; i++) {
6276       QtDemuxStream *stream;
6277       stream = demux->streams[i];
6278       gst_qtdemux_push_tags (demux, stream);
6279       if (CUR_STREAM (stream)->sparse) {
6280         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6281         gst_pad_push_event (stream->pad,
6282             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6283       }
6284     }
6285   }
6286 }
6287
6288 static void
6289 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6290     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6291 {
6292   GstClockTime ts, dur;
6293   GstEvent *gap;
6294
6295   ts = pos;
6296   dur =
6297       stream->segments[segment_index].duration - (pos -
6298       stream->segments[segment_index].time);
6299   gap = gst_event_new_gap (ts, dur);
6300   stream->time_position += dur;
6301
6302   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6303       "segment: %" GST_PTR_FORMAT, gap);
6304   gst_pad_push_event (stream->pad, gap);
6305 }
6306
6307 static void
6308 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6309     QtDemuxStream * stream)
6310 {
6311   gint i;
6312
6313   /* Push any initial gap segments before proceeding to the
6314    * 'real' data */
6315   for (i = 0; i < stream->n_segments; i++) {
6316     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6317
6318     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6319       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6320           stream->time_position);
6321     } else {
6322       /* Only support empty segment at the beginning followed by
6323        * one non-empty segment, this was checked when parsing the
6324        * edts atom, arriving here is unexpected */
6325       g_assert (i + 1 == stream->n_segments);
6326       break;
6327     }
6328   }
6329 }
6330
6331 static GstFlowReturn
6332 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6333 {
6334   GstQTDemux *demux;
6335
6336   demux = GST_QTDEMUX (parent);
6337
6338   GST_DEBUG_OBJECT (demux,
6339       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6340       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6341       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6342       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6343       gst_buffer_get_size (inbuf), demux->offset);
6344
6345   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6346     gboolean is_gap_input = FALSE;
6347     gint i;
6348
6349     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6350
6351     for (i = 0; i < demux->n_streams; i++) {
6352       demux->streams[i]->discont = TRUE;
6353     }
6354
6355     /* Check if we can land back on our feet in the case where upstream is
6356      * handling the seeking/pushing of samples with gaps in between (like
6357      * in the case of trick-mode DASH for example) */
6358     if (demux->upstream_format_is_time
6359         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6360       gint i;
6361       for (i = 0; i < demux->n_streams; i++) {
6362         guint32 res;
6363         GST_LOG_OBJECT (demux,
6364             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6365             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6366         res =
6367             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6368             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6369         if (res != -1) {
6370           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6371           GST_LOG_OBJECT (demux,
6372               "Checking if sample %d from stream %d is valid (offset:%"
6373               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6374               sample->offset, sample->size);
6375           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6376             GST_LOG_OBJECT (demux,
6377                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6378                 res);
6379             is_gap_input = TRUE;
6380             /* We can go back to standard playback mode */
6381             demux->state = QTDEMUX_STATE_MOVIE;
6382             /* Remember which sample this stream is at */
6383             demux->streams[i]->sample_index = res;
6384             /* Finally update all push-based values to the expected values */
6385             demux->neededbytes = demux->streams[i]->samples[res].size;
6386             demux->offset = GST_BUFFER_OFFSET (inbuf);
6387             demux->mdatleft =
6388                 demux->mdatsize - demux->offset + demux->mdatoffset;
6389             demux->todrop = 0;
6390           }
6391         }
6392       }
6393       if (!is_gap_input) {
6394         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6395         /* Reset state if it's a real discont */
6396         demux->neededbytes = 16;
6397         demux->state = QTDEMUX_STATE_INITIAL;
6398         demux->offset = GST_BUFFER_OFFSET (inbuf);
6399         gst_adapter_clear (demux->adapter);
6400       }
6401     }
6402     /* Reverse fragmented playback, need to flush all we have before
6403      * consuming a new fragment.
6404      * The samples array have the timestamps calculated by accumulating the
6405      * durations but this won't work for reverse playback of fragments as
6406      * the timestamps of a subsequent fragment should be smaller than the
6407      * previously received one. */
6408     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6409       gst_qtdemux_process_adapter (demux, TRUE);
6410       for (i = 0; i < demux->n_streams; i++)
6411         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6412     }
6413   }
6414
6415   gst_adapter_push (demux->adapter, inbuf);
6416
6417   GST_DEBUG_OBJECT (demux,
6418       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6419       demux->neededbytes, gst_adapter_available (demux->adapter));
6420
6421   return gst_qtdemux_process_adapter (demux, FALSE);
6422 }
6423
6424 static GstFlowReturn
6425 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6426 {
6427   GstFlowReturn ret = GST_FLOW_OK;
6428
6429   /* we never really mean to buffer that much */
6430   if (demux->neededbytes == -1) {
6431     goto eos;
6432   }
6433
6434   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6435       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6436
6437 #ifndef GST_DISABLE_GST_DEBUG
6438     {
6439       guint64 discont_offset, distance_from_discont;
6440
6441       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6442       distance_from_discont =
6443           gst_adapter_distance_from_discont (demux->adapter);
6444
6445       GST_DEBUG_OBJECT (demux,
6446           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6447           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6448           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6449           demux->offset, discont_offset, distance_from_discont);
6450     }
6451 #endif
6452
6453     switch (demux->state) {
6454       case QTDEMUX_STATE_INITIAL:{
6455         const guint8 *data;
6456         guint32 fourcc;
6457         guint64 size;
6458
6459         gst_qtdemux_check_seekability (demux);
6460
6461         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6462
6463         /* get fourcc/length, set neededbytes */
6464         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6465             &size, &fourcc);
6466         gst_adapter_unmap (demux->adapter);
6467         data = NULL;
6468         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6469             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6470         if (size == 0) {
6471           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6472               (_("This file is invalid and cannot be played.")),
6473               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6474                   GST_FOURCC_ARGS (fourcc)));
6475           ret = GST_FLOW_ERROR;
6476           break;
6477         }
6478         if (fourcc == FOURCC_mdat) {
6479           gint next_entry = next_entry_size (demux);
6480           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6481             /* we have the headers, start playback */
6482             demux->state = QTDEMUX_STATE_MOVIE;
6483             demux->neededbytes = next_entry;
6484             demux->mdatleft = size;
6485             demux->mdatsize = demux->mdatleft;
6486           } else {
6487             /* no headers yet, try to get them */
6488             guint bs;
6489             gboolean res;
6490             guint64 old, target;
6491
6492           buffer_data:
6493             old = demux->offset;
6494             target = old + size;
6495
6496             /* try to jump over the atom with a seek */
6497             /* only bother if it seems worth doing so,
6498              * and avoids possible upstream/server problems */
6499             if (demux->upstream_seekable &&
6500                 demux->upstream_size > 4 * (1 << 20)) {
6501               res = qtdemux_seek_offset (demux, target);
6502             } else {
6503               GST_DEBUG_OBJECT (demux, "skipping seek");
6504               res = FALSE;
6505             }
6506
6507             if (res) {
6508               GST_DEBUG_OBJECT (demux, "seek success");
6509               /* remember the offset fo the first mdat so we can seek back to it
6510                * after we have the headers */
6511               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6512                 demux->first_mdat = old;
6513                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6514                     demux->first_mdat);
6515               }
6516               /* seek worked, continue reading */
6517               demux->offset = target;
6518               demux->neededbytes = 16;
6519               demux->state = QTDEMUX_STATE_INITIAL;
6520             } else {
6521               /* seek failed, need to buffer */
6522               demux->offset = old;
6523               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6524               /* there may be multiple mdat (or alike) buffers */
6525               /* sanity check */
6526               if (demux->mdatbuffer)
6527                 bs = gst_buffer_get_size (demux->mdatbuffer);
6528               else
6529                 bs = 0;
6530               if (size + bs > 10 * (1 << 20))
6531                 goto no_moov;
6532               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6533               demux->neededbytes = size;
6534               if (!demux->mdatbuffer)
6535                 demux->mdatoffset = demux->offset;
6536             }
6537           }
6538         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6539           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6540               (_("This file is invalid and cannot be played.")),
6541               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6542                   GST_FOURCC_ARGS (fourcc), size));
6543           ret = GST_FLOW_ERROR;
6544           break;
6545         } else {
6546           /* this means we already started buffering and still no moov header,
6547            * let's continue buffering everything till we get moov */
6548           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6549                   || fourcc == FOURCC_moof))
6550             goto buffer_data;
6551           demux->neededbytes = size;
6552           demux->state = QTDEMUX_STATE_HEADER;
6553         }
6554         break;
6555       }
6556       case QTDEMUX_STATE_HEADER:{
6557         const guint8 *data;
6558         guint32 fourcc;
6559
6560         GST_DEBUG_OBJECT (demux, "In header");
6561
6562         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6563
6564         /* parse the header */
6565         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6566             &fourcc);
6567         if (fourcc == FOURCC_moov) {
6568           gint n;
6569
6570           /* in usual fragmented setup we could try to scan for more
6571            * and end up at the the moov (after mdat) again */
6572           if (demux->got_moov && demux->n_streams > 0 &&
6573               (!demux->fragmented
6574                   || demux->last_moov_offset == demux->offset)) {
6575             GST_DEBUG_OBJECT (demux,
6576                 "Skipping moov atom as we have (this) one already");
6577           } else {
6578             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6579
6580             if (demux->got_moov && demux->fragmented) {
6581               GST_DEBUG_OBJECT (demux,
6582                   "Got a second moov, clean up data from old one");
6583               if (demux->moov_node_compressed) {
6584                 g_node_destroy (demux->moov_node_compressed);
6585                 if (demux->moov_node)
6586                   g_free (demux->moov_node->data);
6587               }
6588               demux->moov_node_compressed = NULL;
6589               if (demux->moov_node)
6590                 g_node_destroy (demux->moov_node);
6591               demux->moov_node = NULL;
6592             } else {
6593               /* prepare newsegment to send when streaming actually starts */
6594               if (!demux->pending_newsegment) {
6595                 demux->pending_newsegment =
6596                     gst_event_new_segment (&demux->segment);
6597                 if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6598                   gst_event_set_seqnum (demux->pending_newsegment,
6599                       demux->segment_seqnum);
6600               }
6601             }
6602
6603             demux->last_moov_offset = demux->offset;
6604
6605             qtdemux_parse_moov (demux, data, demux->neededbytes);
6606             qtdemux_node_dump (demux, demux->moov_node);
6607             qtdemux_parse_tree (demux);
6608             qtdemux_prepare_streams (demux);
6609             if (!demux->got_moov)
6610               qtdemux_expose_streams (demux);
6611             else {
6612
6613               for (n = 0; n < demux->n_streams; n++) {
6614                 QtDemuxStream *stream = demux->streams[n];
6615
6616                 gst_qtdemux_configure_stream (demux, stream);
6617               }
6618             }
6619
6620             demux->got_moov = TRUE;
6621             gst_qtdemux_check_send_pending_segment (demux);
6622
6623             /* fragmented streams headers shouldn't contain edts atoms */
6624             if (!demux->fragmented) {
6625               for (n = 0; n < demux->n_streams; n++) {
6626                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6627                     demux->streams[n]);
6628               }
6629             }
6630
6631             if (demux->moov_node_compressed) {
6632               g_node_destroy (demux->moov_node_compressed);
6633               g_free (demux->moov_node->data);
6634             }
6635             demux->moov_node_compressed = NULL;
6636             g_node_destroy (demux->moov_node);
6637             demux->moov_node = NULL;
6638             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6639           }
6640         } else if (fourcc == FOURCC_moof) {
6641           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6642             guint64 dist = 0;
6643             GstClockTime prev_pts;
6644             guint64 prev_offset;
6645             guint64 adapter_discont_offset, adapter_discont_dist;
6646
6647             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6648
6649             /*
6650              * The timestamp of the moof buffer is relevant as some scenarios
6651              * won't have the initial timestamp in the atoms. Whenever a new
6652              * buffer has started, we get that buffer's PTS and use it as a base
6653              * timestamp for the trun entries.
6654              *
6655              * To keep track of the current buffer timestamp and starting point
6656              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6657              * from the beggining of the buffer, with the distance and demux->offset
6658              * we know if it is still the same buffer or not.
6659              */
6660             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6661             prev_offset = demux->offset - dist;
6662             if (demux->fragment_start_offset == -1
6663                 || prev_offset > demux->fragment_start_offset) {
6664               demux->fragment_start_offset = prev_offset;
6665               demux->fragment_start = prev_pts;
6666               GST_DEBUG_OBJECT (demux,
6667                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6668                   GST_TIME_FORMAT, demux->fragment_start_offset,
6669                   GST_TIME_ARGS (demux->fragment_start));
6670             }
6671
6672             /* We can't use prev_offset() here because this would require
6673              * upstream to set consistent and correct offsets on all buffers
6674              * since the discont. Nothing ever did that in the past and we
6675              * would break backwards compatibility here then.
6676              * Instead take the offset we had at the last discont and count
6677              * the bytes from there. This works with old code as there would
6678              * be no discont between moov and moof, and also works with
6679              * adaptivedemux which correctly sets offset and will set the
6680              * DISCONT flag accordingly when needed.
6681              *
6682              * We also only do this for upstream TIME segments as otherwise
6683              * there are potential backwards compatibility problems with
6684              * seeking in PUSH mode and upstream providing inconsistent
6685              * timestamps. */
6686             adapter_discont_offset =
6687                 gst_adapter_offset_at_discont (demux->adapter);
6688             adapter_discont_dist =
6689                 gst_adapter_distance_from_discont (demux->adapter);
6690
6691             GST_DEBUG_OBJECT (demux,
6692                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6693                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6694                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6695
6696             if (demux->upstream_format_is_time) {
6697               demux->moof_offset = adapter_discont_offset;
6698               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6699                 demux->moof_offset += adapter_discont_dist;
6700               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6701                 demux->moof_offset = demux->offset;
6702             } else {
6703               demux->moof_offset = demux->offset;
6704             }
6705
6706             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6707                     demux->moof_offset, NULL)) {
6708               gst_adapter_unmap (demux->adapter);
6709               ret = GST_FLOW_ERROR;
6710               goto done;
6711             }
6712             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6713             if (demux->mss_mode && !demux->exposed) {
6714               if (!demux->pending_newsegment) {
6715                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6716                 demux->pending_newsegment =
6717                     gst_event_new_segment (&demux->segment);
6718                 if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6719                   gst_event_set_seqnum (demux->pending_newsegment,
6720                       demux->segment_seqnum);
6721               }
6722               qtdemux_expose_streams (demux);
6723             }
6724           } else {
6725             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6726           }
6727         } else if (fourcc == FOURCC_ftyp) {
6728           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6729           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6730         } else if (fourcc == FOURCC_uuid) {
6731           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6732           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6733         } else if (fourcc == FOURCC_sidx) {
6734           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6735           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6736         } else {
6737           switch (fourcc) {
6738             case FOURCC_styp:
6739               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6740                * FALLTHROUGH */
6741             case FOURCC_skip:
6742             case FOURCC_free:
6743               /* [free] and [skip] are padding atoms */
6744               GST_DEBUG_OBJECT (demux,
6745                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6746                   GST_FOURCC_ARGS (fourcc));
6747               break;
6748             default:
6749               GST_WARNING_OBJECT (demux,
6750                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6751                   GST_FOURCC_ARGS (fourcc));
6752               /* Let's jump that one and go back to initial state */
6753               break;
6754           }
6755         }
6756         gst_adapter_unmap (demux->adapter);
6757         data = NULL;
6758
6759         if (demux->mdatbuffer && demux->n_streams) {
6760           gsize remaining_data_size = 0;
6761
6762           /* the mdat was before the header */
6763           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6764               demux->n_streams, demux->mdatbuffer);
6765           /* restore our adapter/offset view of things with upstream;
6766            * put preceding buffered data ahead of current moov data.
6767            * This should also handle evil mdat, moov, mdat cases and alike */
6768           gst_adapter_flush (demux->adapter, demux->neededbytes);
6769
6770           /* Store any remaining data after the mdat for later usage */
6771           remaining_data_size = gst_adapter_available (demux->adapter);
6772           if (remaining_data_size > 0) {
6773             g_assert (demux->restoredata_buffer == NULL);
6774             demux->restoredata_buffer =
6775                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6776             demux->restoredata_offset = demux->offset + demux->neededbytes;
6777             GST_DEBUG_OBJECT (demux,
6778                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6779                 G_GUINT64_FORMAT, remaining_data_size,
6780                 demux->restoredata_offset);
6781           }
6782
6783           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6784           demux->mdatbuffer = NULL;
6785           demux->offset = demux->mdatoffset;
6786           demux->neededbytes = next_entry_size (demux);
6787           demux->state = QTDEMUX_STATE_MOVIE;
6788           demux->mdatleft = gst_adapter_available (demux->adapter);
6789           demux->mdatsize = demux->mdatleft;
6790         } else {
6791           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6792           gst_adapter_flush (demux->adapter, demux->neededbytes);
6793
6794           /* only go back to the mdat if there are samples to play */
6795           if (demux->got_moov && demux->first_mdat != -1
6796               && has_next_entry (demux)) {
6797             gboolean res;
6798
6799             /* we need to seek back */
6800             res = qtdemux_seek_offset (demux, demux->first_mdat);
6801             if (res) {
6802               demux->offset = demux->first_mdat;
6803             } else {
6804               GST_DEBUG_OBJECT (demux, "Seek back failed");
6805             }
6806           } else {
6807             demux->offset += demux->neededbytes;
6808           }
6809           demux->neededbytes = 16;
6810           demux->state = QTDEMUX_STATE_INITIAL;
6811         }
6812
6813         break;
6814       }
6815       case QTDEMUX_STATE_BUFFER_MDAT:{
6816         GstBuffer *buf;
6817         guint8 fourcc[4];
6818
6819         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6820             demux->offset);
6821         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6822         gst_buffer_extract (buf, 0, fourcc, 4);
6823         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6824             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6825         if (demux->mdatbuffer)
6826           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6827         else
6828           demux->mdatbuffer = buf;
6829         demux->offset += demux->neededbytes;
6830         demux->neededbytes = 16;
6831         demux->state = QTDEMUX_STATE_INITIAL;
6832         gst_qtdemux_post_progress (demux, 1, 1);
6833
6834         break;
6835       }
6836       case QTDEMUX_STATE_MOVIE:{
6837         QtDemuxStream *stream = NULL;
6838         QtDemuxSample *sample;
6839         int i = -1;
6840         GstClockTime dts, pts, duration;
6841         gboolean keyframe;
6842
6843         GST_DEBUG_OBJECT (demux,
6844             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6845
6846         if (demux->fragmented) {
6847           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6848               demux->mdatleft);
6849           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6850             /* if needed data starts within this atom,
6851              * then it should not exceed this atom */
6852             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6853               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6854                   (_("This file is invalid and cannot be played.")),
6855                   ("sample data crosses atom boundary"));
6856               ret = GST_FLOW_ERROR;
6857               break;
6858             }
6859             demux->mdatleft -= demux->neededbytes;
6860           } else {
6861             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6862             /* so we are dropping more than left in this atom */
6863             gst_qtdemux_drop_data (demux, demux->mdatleft);
6864             demux->mdatleft = 0;
6865
6866             /* need to resume atom parsing so we do not miss any other pieces */
6867             demux->state = QTDEMUX_STATE_INITIAL;
6868             demux->neededbytes = 16;
6869
6870             /* check if there was any stored post mdat data from previous buffers */
6871             if (demux->restoredata_buffer) {
6872               g_assert (gst_adapter_available (demux->adapter) == 0);
6873
6874               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6875               demux->restoredata_buffer = NULL;
6876               demux->offset = demux->restoredata_offset;
6877             }
6878
6879             break;
6880           }
6881         }
6882
6883         if (demux->todrop) {
6884           if (demux->cenc_aux_info_offset > 0) {
6885             GstByteReader br;
6886             const guint8 *data;
6887
6888             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6889             data = gst_adapter_map (demux->adapter, demux->todrop);
6890             gst_byte_reader_init (&br, data + 8, demux->todrop);
6891             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6892                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6893               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6894               ret = GST_FLOW_ERROR;
6895               gst_adapter_unmap (demux->adapter);
6896               g_free (demux->cenc_aux_info_sizes);
6897               demux->cenc_aux_info_sizes = NULL;
6898               goto done;
6899             }
6900             demux->cenc_aux_info_offset = 0;
6901             g_free (demux->cenc_aux_info_sizes);
6902             demux->cenc_aux_info_sizes = NULL;
6903             gst_adapter_unmap (demux->adapter);
6904           }
6905           gst_qtdemux_drop_data (demux, demux->todrop);
6906         }
6907
6908         /* first buffer? */
6909         /* initial newsegment sent here after having added pads,
6910          * possible others in sink_event */
6911         gst_qtdemux_check_send_pending_segment (demux);
6912
6913         /* Figure out which stream this packet belongs to */
6914         for (i = 0; i < demux->n_streams; i++) {
6915           stream = demux->streams[i];
6916           if (stream->sample_index >= stream->n_samples)
6917             continue;
6918           GST_LOG_OBJECT (demux,
6919               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6920               " / size:%d)", i, stream->sample_index,
6921               stream->samples[stream->sample_index].offset,
6922               stream->samples[stream->sample_index].size);
6923
6924           if (stream->samples[stream->sample_index].offset == demux->offset)
6925             break;
6926         }
6927
6928         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6929           goto unknown_stream;
6930
6931         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6932
6933         if (stream->new_caps) {
6934           gst_qtdemux_configure_stream (demux, stream);
6935         }
6936
6937         /* Put data in a buffer, set timestamps, caps, ... */
6938         sample = &stream->samples[stream->sample_index];
6939
6940         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6941           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6942               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6943
6944           dts = QTSAMPLE_DTS (stream, sample);
6945           pts = QTSAMPLE_PTS (stream, sample);
6946           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6947           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6948
6949           /* check for segment end */
6950           if (G_UNLIKELY (demux->segment.stop != -1
6951                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6952             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6953             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6954
6955             /* skip this data, stream is EOS */
6956             gst_adapter_flush (demux->adapter, demux->neededbytes);
6957             demux->offset += demux->neededbytes;
6958
6959             /* check if all streams are eos */
6960             ret = GST_FLOW_EOS;
6961             for (i = 0; i < demux->n_streams; i++) {
6962               if (!STREAM_IS_EOS (demux->streams[i])) {
6963                 ret = GST_FLOW_OK;
6964                 break;
6965               }
6966             }
6967           } else {
6968             GstBuffer *outbuf;
6969
6970             outbuf =
6971                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6972
6973             /* FIXME: should either be an assert or a plain check */
6974             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6975
6976             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6977                 dts, pts, duration, keyframe, dts, demux->offset);
6978           }
6979
6980           /* combine flows */
6981           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6982         } else {
6983           /* skip this data, stream is EOS */
6984           gst_adapter_flush (demux->adapter, demux->neededbytes);
6985         }
6986
6987         stream->sample_index++;
6988         stream->offset_in_sample = 0;
6989
6990         /* update current offset and figure out size of next buffer */
6991         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6992             demux->offset, demux->neededbytes);
6993         demux->offset += demux->neededbytes;
6994         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6995             demux->offset);
6996
6997
6998         if (ret == GST_FLOW_EOS) {
6999           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7000           demux->neededbytes = -1;
7001           goto eos;
7002         }
7003
7004         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7005           if (demux->fragmented) {
7006             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7007             /* there may be more to follow, only finish this atom */
7008             demux->todrop = demux->mdatleft;
7009             demux->neededbytes = demux->todrop;
7010             break;
7011           }
7012           goto eos;
7013         }
7014         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7015           goto non_ok_unlinked_flow;
7016         }
7017         break;
7018       }
7019       default:
7020         goto invalid_state;
7021     }
7022   }
7023
7024   /* when buffering movie data, at least show user something is happening */
7025   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7026       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7027     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7028         demux->neededbytes);
7029   }
7030 done:
7031
7032   return ret;
7033
7034   /* ERRORS */
7035 non_ok_unlinked_flow:
7036   {
7037     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7038         gst_flow_get_name (ret));
7039     return ret;
7040   }
7041 unknown_stream:
7042   {
7043     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7044     ret = GST_FLOW_ERROR;
7045     goto done;
7046   }
7047 eos:
7048   {
7049     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7050     ret = GST_FLOW_EOS;
7051     goto done;
7052   }
7053 invalid_state:
7054   {
7055     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7056         (NULL), ("qtdemuxer invalid state %d", demux->state));
7057     ret = GST_FLOW_ERROR;
7058     goto done;
7059   }
7060 no_moov:
7061   {
7062     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7063         (NULL), ("no 'moov' atom within the first 10 MB"));
7064     ret = GST_FLOW_ERROR;
7065     goto done;
7066   }
7067 }
7068
7069 static gboolean
7070 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7071 {
7072   GstQuery *query;
7073   gboolean pull_mode;
7074
7075   query = gst_query_new_scheduling ();
7076
7077   if (!gst_pad_peer_query (sinkpad, query)) {
7078     gst_query_unref (query);
7079     goto activate_push;
7080   }
7081
7082   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7083       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7084   gst_query_unref (query);
7085
7086   if (!pull_mode)
7087     goto activate_push;
7088
7089   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7090   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7091
7092 activate_push:
7093   {
7094     GST_DEBUG_OBJECT (sinkpad, "activating push");
7095     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7096   }
7097 }
7098
7099 static gboolean
7100 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7101     GstPadMode mode, gboolean active)
7102 {
7103   gboolean res;
7104   GstQTDemux *demux = GST_QTDEMUX (parent);
7105
7106   switch (mode) {
7107     case GST_PAD_MODE_PUSH:
7108       demux->pullbased = FALSE;
7109       res = TRUE;
7110       break;
7111     case GST_PAD_MODE_PULL:
7112       if (active) {
7113         demux->pullbased = TRUE;
7114         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7115             sinkpad, NULL);
7116       } else {
7117         res = gst_pad_stop_task (sinkpad);
7118       }
7119       break;
7120     default:
7121       res = FALSE;
7122       break;
7123   }
7124   return res;
7125 }
7126
7127 #ifdef HAVE_ZLIB
7128 static void *
7129 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7130 {
7131   guint8 *buffer;
7132   z_stream z;
7133   int ret;
7134
7135   memset (&z, 0, sizeof (z));
7136   z.zalloc = NULL;
7137   z.zfree = NULL;
7138   z.opaque = NULL;
7139
7140   if ((ret = inflateInit (&z)) != Z_OK) {
7141     GST_ERROR ("inflateInit() returned %d", ret);
7142     return NULL;
7143   }
7144
7145   z.next_in = z_buffer;
7146   z.avail_in = z_length;
7147
7148   buffer = (guint8 *) g_malloc (*length);
7149   z.avail_out = *length;
7150   z.next_out = (Bytef *) buffer;
7151   do {
7152     ret = inflate (&z, Z_NO_FLUSH);
7153     if (ret == Z_STREAM_END) {
7154       break;
7155     } else if (ret != Z_OK) {
7156       GST_WARNING ("inflate() returned %d", ret);
7157       break;
7158     }
7159
7160     *length += 4096;
7161     buffer = (guint8 *) g_realloc (buffer, *length);
7162     z.next_out = (Bytef *) (buffer + z.total_out);
7163     z.avail_out += 4096;
7164   } while (z.avail_in > 0);
7165
7166   if (ret != Z_STREAM_END) {
7167     g_free (buffer);
7168     buffer = NULL;
7169     *length = 0;
7170   } else {
7171     *length = z.total_out;
7172   }
7173
7174   inflateEnd (&z);
7175
7176   return buffer;
7177 }
7178 #endif /* HAVE_ZLIB */
7179
7180 static gboolean
7181 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7182 {
7183   GNode *cmov;
7184
7185   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7186
7187   /* counts as header data */
7188   qtdemux->header_size += length;
7189
7190   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7191   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7192
7193   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7194   if (cmov) {
7195     guint32 method;
7196     GNode *dcom;
7197     GNode *cmvd;
7198     guint32 dcom_len;
7199
7200     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7201     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7202     if (dcom == NULL || cmvd == NULL)
7203       goto invalid_compression;
7204
7205     dcom_len = QT_UINT32 (dcom->data);
7206     if (dcom_len < 12)
7207       goto invalid_compression;
7208
7209     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7210     switch (method) {
7211 #ifdef HAVE_ZLIB
7212       case FOURCC_zlib:{
7213         guint uncompressed_length;
7214         guint compressed_length;
7215         guint8 *buf;
7216         guint32 cmvd_len;
7217
7218         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7219         if (cmvd_len < 12)
7220           goto invalid_compression;
7221
7222         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7223         compressed_length = cmvd_len - 12;
7224         GST_LOG ("length = %u", uncompressed_length);
7225
7226         buf =
7227             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7228             compressed_length, &uncompressed_length);
7229
7230         if (buf) {
7231           qtdemux->moov_node_compressed = qtdemux->moov_node;
7232           qtdemux->moov_node = g_node_new (buf);
7233
7234           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7235               uncompressed_length);
7236         }
7237         break;
7238       }
7239 #endif /* HAVE_ZLIB */
7240       default:
7241         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7242             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7243         break;
7244     }
7245   }
7246   return TRUE;
7247
7248   /* ERRORS */
7249 invalid_compression:
7250   {
7251     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7252     return FALSE;
7253   }
7254 }
7255
7256 static gboolean
7257 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7258     const guint8 * end)
7259 {
7260   while (G_UNLIKELY (buf < end)) {
7261     GNode *child;
7262     guint32 len;
7263
7264     if (G_UNLIKELY (buf + 4 > end)) {
7265       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7266       break;
7267     }
7268     len = QT_UINT32 (buf);
7269     if (G_UNLIKELY (len == 0)) {
7270       GST_LOG_OBJECT (qtdemux, "empty container");
7271       break;
7272     }
7273     if (G_UNLIKELY (len < 8)) {
7274       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7275       break;
7276     }
7277     if (G_UNLIKELY (len > (end - buf))) {
7278       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7279           (gint) (end - buf));
7280       break;
7281     }
7282
7283     child = g_node_new ((guint8 *) buf);
7284     g_node_append (node, child);
7285     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7286     qtdemux_parse_node (qtdemux, child, buf, len);
7287
7288     buf += len;
7289   }
7290   return TRUE;
7291 }
7292
7293 static gboolean
7294 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7295     GNode * xdxt)
7296 {
7297   int len = QT_UINT32 (xdxt->data);
7298   guint8 *buf = xdxt->data;
7299   guint8 *end = buf + len;
7300   GstBuffer *buffer;
7301
7302   /* skip size and type */
7303   buf += 8;
7304   end -= 8;
7305
7306   while (buf < end) {
7307     gint size;
7308     guint32 type;
7309
7310     size = QT_UINT32 (buf);
7311     type = QT_FOURCC (buf + 4);
7312
7313     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7314
7315     if (buf + size > end || size <= 0)
7316       break;
7317
7318     buf += 8;
7319     size -= 8;
7320
7321     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7322         GST_FOURCC_ARGS (type));
7323
7324     switch (type) {
7325       case FOURCC_tCtH:
7326         buffer = gst_buffer_new_and_alloc (size);
7327         gst_buffer_fill (buffer, 0, buf, size);
7328         stream->buffers = g_slist_append (stream->buffers, buffer);
7329         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7330         break;
7331       case FOURCC_tCt_:
7332         buffer = gst_buffer_new_and_alloc (size);
7333         gst_buffer_fill (buffer, 0, buf, size);
7334         stream->buffers = g_slist_append (stream->buffers, buffer);
7335         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7336         break;
7337       case FOURCC_tCtC:
7338         buffer = gst_buffer_new_and_alloc (size);
7339         gst_buffer_fill (buffer, 0, buf, size);
7340         stream->buffers = g_slist_append (stream->buffers, buffer);
7341         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7342         break;
7343       default:
7344         GST_WARNING_OBJECT (qtdemux,
7345             "unknown theora cookie %" GST_FOURCC_FORMAT,
7346             GST_FOURCC_ARGS (type));
7347         break;
7348     }
7349     buf += size;
7350   }
7351   return TRUE;
7352 }
7353
7354 static gboolean
7355 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7356     guint length)
7357 {
7358   guint32 fourcc = 0;
7359   guint32 node_length = 0;
7360   const QtNodeType *type;
7361   const guint8 *end;
7362
7363   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7364
7365   if (G_UNLIKELY (length < 8))
7366     goto not_enough_data;
7367
7368   node_length = QT_UINT32 (buffer);
7369   fourcc = QT_FOURCC (buffer + 4);
7370
7371   /* ignore empty nodes */
7372   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7373     return TRUE;
7374
7375   type = qtdemux_type_get (fourcc);
7376
7377   end = buffer + length;
7378
7379   GST_LOG_OBJECT (qtdemux,
7380       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7381       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7382
7383   if (node_length > length)
7384     goto broken_atom_size;
7385
7386   if (type->flags & QT_FLAG_CONTAINER) {
7387     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7388   } else {
7389     switch (fourcc) {
7390       case FOURCC_stsd:
7391       {
7392         if (node_length < 20) {
7393           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7394           break;
7395         }
7396         GST_DEBUG_OBJECT (qtdemux,
7397             "parsing stsd (sample table, sample description) atom");
7398         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7399         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7400         break;
7401       }
7402       case FOURCC_mp4a:
7403       case FOURCC_alac:
7404       case FOURCC_fLaC:
7405       {
7406         guint32 version;
7407         guint32 offset;
7408         guint min_size;
7409
7410         /* also read alac (or whatever) in stead of mp4a in the following,
7411          * since a similar layout is used in other cases as well */
7412         if (fourcc == FOURCC_mp4a)
7413           min_size = 20;
7414         else if (fourcc == FOURCC_fLaC)
7415           min_size = 86;
7416         else
7417           min_size = 40;
7418
7419         /* There are two things we might encounter here: a true mp4a atom, and
7420            an mp4a entry in an stsd atom. The latter is what we're interested
7421            in, and it looks like an atom, but isn't really one. The true mp4a
7422            atom is short, so we detect it based on length here. */
7423         if (length < min_size) {
7424           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7425               GST_FOURCC_ARGS (fourcc));
7426           break;
7427         }
7428
7429         /* 'version' here is the sound sample description version. Types 0 and
7430            1 are documented in the QTFF reference, but type 2 is not: it's
7431            described in Apple header files instead (struct SoundDescriptionV2
7432            in Movies.h) */
7433         version = QT_UINT16 (buffer + 16);
7434
7435         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7436             GST_FOURCC_ARGS (fourcc), version);
7437
7438         /* parse any esds descriptors */
7439         switch (version) {
7440           case 0:
7441             offset = 0x24;
7442             break;
7443           case 1:
7444             offset = 0x34;
7445             break;
7446           case 2:
7447             offset = 0x48;
7448             break;
7449           default:
7450             GST_WARNING_OBJECT (qtdemux,
7451                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7452                 GST_FOURCC_ARGS (fourcc), version);
7453             offset = 0;
7454             break;
7455         }
7456         if (offset)
7457           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7458         break;
7459       }
7460       case FOURCC_mp4v:
7461       case FOURCC_MP4V:
7462       case FOURCC_fmp4:
7463       case FOURCC_FMP4:
7464       case FOURCC_apcs:
7465       case FOURCC_apch:
7466       case FOURCC_apcn:
7467       case FOURCC_apco:
7468       case FOURCC_ap4h:
7469       case FOURCC_xvid:
7470       case FOURCC_XVID:
7471       case FOURCC_H264:
7472       case FOURCC_avc1:
7473       case FOURCC_avc3:
7474       case FOURCC_H265:
7475       case FOURCC_hvc1:
7476       case FOURCC_hev1:
7477       case FOURCC_mjp2:
7478       case FOURCC_encv:
7479       {
7480         guint32 version;
7481         guint32 str_len;
7482
7483         /* codec_data is contained inside these atoms, which all have
7484          * the same format. */
7485         /* video sample description size is 86 bytes without extension.
7486          * node_length have to be bigger than 86 bytes because video sample
7487          * description can include extenstions such as esds, fiel, glbl, etc. */
7488         if (node_length < 86) {
7489           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7490               " sample description length too short (%u < 86)",
7491               GST_FOURCC_ARGS (fourcc), node_length);
7492           break;
7493         }
7494
7495         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7496             GST_FOURCC_ARGS (fourcc));
7497
7498         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7499          *              its data format.
7500          * revision level (2 bytes) : must be set to 0. */
7501         version = QT_UINT32 (buffer + 16);
7502         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7503
7504         /* compressor name : PASCAL string and informative purposes
7505          * first byte : the number of bytes to be displayed.
7506          *              it has to be less than 32 because it is reserved
7507          *              space of 32 bytes total including itself. */
7508         str_len = QT_UINT8 (buffer + 50);
7509         if (str_len < 32)
7510           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7511               (char *) buffer + 51);
7512         else
7513           GST_WARNING_OBJECT (qtdemux,
7514               "compressorname length too big (%u > 31)", str_len);
7515
7516         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7517             end - buffer);
7518         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7519         break;
7520       }
7521       case FOURCC_meta:
7522       {
7523         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7524
7525         /* You are reading this correctly. QTFF specifies that the
7526          * metadata atom is a short atom, whereas ISO BMFF specifies
7527          * it's a full atom. But since so many people are doing things
7528          * differently, we actually peek into the atom to see which
7529          * variant it is */
7530         if (length < 16) {
7531           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7532               GST_FOURCC_ARGS (fourcc));
7533           break;
7534         }
7535         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7536           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7537            * starts with a 'hdlr' atom */
7538           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7539         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7540           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7541            * with version/flags both set to zero */
7542           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7543         } else
7544           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7545         break;
7546       }
7547       case FOURCC_mp4s:
7548       {
7549         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7550         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7551         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7552         break;
7553       }
7554       case FOURCC_XiTh:
7555       {
7556         guint32 version;
7557         guint32 offset;
7558
7559         if (length < 16) {
7560           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7561               GST_FOURCC_ARGS (fourcc));
7562           break;
7563         }
7564
7565         version = QT_UINT32 (buffer + 12);
7566         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7567
7568         switch (version) {
7569           case 0x00000001:
7570             offset = 0x62;
7571             break;
7572           default:
7573             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7574             offset = 0;
7575             break;
7576         }
7577         if (offset) {
7578           if (length < offset) {
7579             GST_WARNING_OBJECT (qtdemux,
7580                 "skipping too small %" GST_FOURCC_FORMAT " box",
7581                 GST_FOURCC_ARGS (fourcc));
7582             break;
7583           }
7584           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7585         }
7586         break;
7587       }
7588       case FOURCC_in24:
7589       {
7590         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7591         break;
7592       }
7593       case FOURCC_uuid:
7594       {
7595         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7596         break;
7597       }
7598       case FOURCC_enca:
7599       {
7600         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7601         break;
7602       }
7603       default:
7604         if (!strcmp (type->name, "unknown"))
7605           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7606         break;
7607     }
7608   }
7609   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7610       GST_FOURCC_ARGS (fourcc));
7611   return TRUE;
7612
7613 /* ERRORS */
7614 not_enough_data:
7615   {
7616     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7617         (_("This file is corrupt and cannot be played.")),
7618         ("Not enough data for an atom header, got only %u bytes", length));
7619     return FALSE;
7620   }
7621 broken_atom_size:
7622   {
7623     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7624         (_("This file is corrupt and cannot be played.")),
7625         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7626             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7627             length));
7628     return FALSE;
7629   }
7630 }
7631
7632 static GNode *
7633 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7634 {
7635   GNode *child;
7636   guint8 *buffer;
7637   guint32 child_fourcc;
7638
7639   for (child = g_node_first_child (node); child;
7640       child = g_node_next_sibling (child)) {
7641     buffer = (guint8 *) child->data;
7642
7643     child_fourcc = QT_FOURCC (buffer + 4);
7644
7645     if (G_UNLIKELY (child_fourcc == fourcc)) {
7646       return child;
7647     }
7648   }
7649   return NULL;
7650 }
7651
7652 static GNode *
7653 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7654     GstByteReader * parser)
7655 {
7656   GNode *child;
7657   guint8 *buffer;
7658   guint32 child_fourcc, child_len;
7659
7660   for (child = g_node_first_child (node); child;
7661       child = g_node_next_sibling (child)) {
7662     buffer = (guint8 *) child->data;
7663
7664     child_len = QT_UINT32 (buffer);
7665     child_fourcc = QT_FOURCC (buffer + 4);
7666
7667     if (G_UNLIKELY (child_fourcc == fourcc)) {
7668       if (G_UNLIKELY (child_len < (4 + 4)))
7669         return NULL;
7670       /* FIXME: must verify if atom length < parent atom length */
7671       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7672       return child;
7673     }
7674   }
7675   return NULL;
7676 }
7677
7678 static GNode *
7679 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7680 {
7681   return g_node_nth_child (node, index);
7682 }
7683
7684 static GNode *
7685 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7686     GstByteReader * parser)
7687 {
7688   GNode *child;
7689   guint8 *buffer;
7690   guint32 child_fourcc, child_len;
7691
7692   for (child = g_node_next_sibling (node); child;
7693       child = g_node_next_sibling (child)) {
7694     buffer = (guint8 *) child->data;
7695
7696     child_fourcc = QT_FOURCC (buffer + 4);
7697
7698     if (child_fourcc == fourcc) {
7699       if (parser) {
7700         child_len = QT_UINT32 (buffer);
7701         if (G_UNLIKELY (child_len < (4 + 4)))
7702           return NULL;
7703         /* FIXME: must verify if atom length < parent atom length */
7704         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7705       }
7706       return child;
7707     }
7708   }
7709   return NULL;
7710 }
7711
7712 static GNode *
7713 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7714 {
7715   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7716 }
7717
7718 static void
7719 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7720 {
7721 /* FIXME: This can only reliably work if demuxers have a
7722  * separate streaming thread per srcpad. This should be
7723  * done in a demuxer base class, which integrates parts
7724  * of multiqueue
7725  *
7726  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7727  */
7728 #if 0
7729   GstQuery *query;
7730
7731   query = gst_query_new_allocation (stream->caps, FALSE);
7732
7733   if (!gst_pad_peer_query (stream->pad, query)) {
7734     /* not a problem, just debug a little */
7735     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7736   }
7737
7738   if (stream->allocator)
7739     gst_object_unref (stream->allocator);
7740
7741   if (gst_query_get_n_allocation_params (query) > 0) {
7742     /* try the allocator */
7743     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7744         &stream->params);
7745     stream->use_allocator = TRUE;
7746   } else {
7747     stream->allocator = NULL;
7748     gst_allocation_params_init (&stream->params);
7749     stream->use_allocator = FALSE;
7750   }
7751   gst_query_unref (query);
7752 #endif
7753 }
7754
7755 static gboolean
7756 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7757     QtDemuxStream * stream)
7758 {
7759   GstStructure *s;
7760   const gchar *selected_system;
7761
7762   g_return_val_if_fail (qtdemux != NULL, FALSE);
7763   g_return_val_if_fail (stream != NULL, FALSE);
7764   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7765       FALSE);
7766
7767   if (stream->protection_scheme_type != FOURCC_cenc) {
7768     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7769     return FALSE;
7770   }
7771   if (qtdemux->protection_system_ids == NULL) {
7772     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7773         "cenc protection system information has been found");
7774     return FALSE;
7775   }
7776   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7777   selected_system = gst_protection_select_system ((const gchar **)
7778       qtdemux->protection_system_ids->pdata);
7779   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7780       qtdemux->protection_system_ids->len - 1);
7781   if (!selected_system) {
7782     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7783         "suitable decryptor element has been found");
7784     return FALSE;
7785   }
7786
7787   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7788   if (!gst_structure_has_name (s, "application/x-cenc")) {
7789     gst_structure_set (s,
7790         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7791         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7792         NULL);
7793     gst_structure_set_name (s, "application/x-cenc");
7794   }
7795   return TRUE;
7796 }
7797
7798 static gboolean
7799 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7800 {
7801   if (stream->subtype == FOURCC_vide) {
7802     /* fps is calculated base on the duration of the average framerate since
7803      * qt does not have a fixed framerate. */
7804     gboolean fps_available = TRUE;
7805
7806     if ((stream->n_samples == 1 && stream->first_duration == 0)
7807         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
7808       /* still frame */
7809       CUR_STREAM (stream)->fps_n = 0;
7810       CUR_STREAM (stream)->fps_d = 1;
7811     } else {
7812       if (stream->duration == 0 || stream->n_samples < 2) {
7813         CUR_STREAM (stream)->fps_n = stream->timescale;
7814         CUR_STREAM (stream)->fps_d = 1;
7815         fps_available = FALSE;
7816       } else {
7817         GstClockTime avg_duration;
7818         guint64 duration;
7819         guint32 n_samples;
7820
7821         /* duration and n_samples can be updated for fragmented format
7822          * so, framerate of fragmented format is calculated using data in a moof */
7823         if (qtdemux->fragmented && stream->n_samples_moof > 0
7824             && stream->duration_moof > 0) {
7825           n_samples = stream->n_samples_moof;
7826           duration = stream->duration_moof;
7827         } else {
7828           n_samples = stream->n_samples;
7829           duration = stream->duration;
7830         }
7831
7832         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7833         /* stream->duration is guint64, timescale, n_samples are guint32 */
7834         avg_duration =
7835             gst_util_uint64_scale_round (duration -
7836             stream->first_duration, GST_SECOND,
7837             (guint64) (stream->timescale) * (n_samples - 1));
7838
7839         GST_LOG_OBJECT (qtdemux,
7840             "Calculating avg sample duration based on stream (or moof) duration %"
7841             G_GUINT64_FORMAT
7842             " minus first sample %u, leaving %d samples gives %"
7843             GST_TIME_FORMAT, duration, stream->first_duration,
7844             n_samples - 1, GST_TIME_ARGS (avg_duration));
7845
7846         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7847             &CUR_STREAM (stream)->fps_d);
7848
7849         GST_DEBUG_OBJECT (qtdemux,
7850             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7851             stream->timescale, CUR_STREAM (stream)->fps_n,
7852             CUR_STREAM (stream)->fps_d);
7853       }
7854     }
7855
7856     if (CUR_STREAM (stream)->caps) {
7857       CUR_STREAM (stream)->caps =
7858           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7859
7860       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7861           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7862           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7863
7864       /* set framerate if calculated framerate is reliable */
7865       if (fps_available) {
7866         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7867             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7868             CUR_STREAM (stream)->fps_d, NULL);
7869       }
7870
7871       /* calculate pixel-aspect-ratio using display width and height */
7872       GST_DEBUG_OBJECT (qtdemux,
7873           "video size %dx%d, target display size %dx%d",
7874           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7875           stream->display_width, stream->display_height);
7876       /* qt file might have pasp atom */
7877       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7878         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7879             CUR_STREAM (stream)->par_h);
7880         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7881             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7882             CUR_STREAM (stream)->par_h, NULL);
7883       } else if (stream->display_width > 0 && stream->display_height > 0
7884           && CUR_STREAM (stream)->width > 0
7885           && CUR_STREAM (stream)->height > 0) {
7886         gint n, d;
7887
7888         /* calculate the pixel aspect ratio using the display and pixel w/h */
7889         n = stream->display_width * CUR_STREAM (stream)->height;
7890         d = stream->display_height * CUR_STREAM (stream)->width;
7891         if (n == d)
7892           n = d = 1;
7893         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7894         CUR_STREAM (stream)->par_w = n;
7895         CUR_STREAM (stream)->par_h = d;
7896         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7897             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7898             CUR_STREAM (stream)->par_h, NULL);
7899       }
7900
7901       if (CUR_STREAM (stream)->interlace_mode > 0) {
7902         if (CUR_STREAM (stream)->interlace_mode == 1) {
7903           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7904               G_TYPE_STRING, "progressive", NULL);
7905         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7906           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7907               G_TYPE_STRING, "interleaved", NULL);
7908           if (CUR_STREAM (stream)->field_order == 9) {
7909             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7910                 G_TYPE_STRING, "top-field-first", NULL);
7911           } else if (CUR_STREAM (stream)->field_order == 14) {
7912             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7913                 G_TYPE_STRING, "bottom-field-first", NULL);
7914           }
7915         }
7916       }
7917
7918       /* Create incomplete colorimetry here if needed */
7919       if (CUR_STREAM (stream)->colorimetry.range ||
7920           CUR_STREAM (stream)->colorimetry.matrix ||
7921           CUR_STREAM (stream)->colorimetry.transfer
7922           || CUR_STREAM (stream)->colorimetry.primaries) {
7923         gchar *colorimetry =
7924             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7925         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7926             G_TYPE_STRING, colorimetry, NULL);
7927         g_free (colorimetry);
7928       }
7929
7930       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7931         guint par_w = 1, par_h = 1;
7932
7933         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7934           par_w = CUR_STREAM (stream)->par_w;
7935           par_h = CUR_STREAM (stream)->par_h;
7936         }
7937
7938         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7939                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7940                 par_h)) {
7941           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7942         }
7943
7944         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7945             "multiview-mode", G_TYPE_STRING,
7946             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7947             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7948             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7949       }
7950     }
7951   }
7952
7953   else if (stream->subtype == FOURCC_soun) {
7954     if (CUR_STREAM (stream)->caps) {
7955       CUR_STREAM (stream)->caps =
7956           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7957       if (CUR_STREAM (stream)->rate > 0)
7958         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7959             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
7960       if (CUR_STREAM (stream)->n_channels > 0)
7961         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7962             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
7963       if (CUR_STREAM (stream)->n_channels > 2) {
7964         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7965          * correctly; this is just the minimum we can do - assume
7966          * we don't actually have any channel positions. */
7967         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7968             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7969       }
7970     }
7971   }
7972
7973   if (stream->pad) {
7974     GstCaps *prev_caps = NULL;
7975
7976     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7977     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7978     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7979     gst_pad_set_active (stream->pad, TRUE);
7980
7981     gst_pad_use_fixed_caps (stream->pad);
7982
7983     if (stream->protected) {
7984       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7985         GST_ERROR_OBJECT (qtdemux,
7986             "Failed to configure protected stream caps.");
7987         return FALSE;
7988       }
7989     }
7990
7991     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7992         CUR_STREAM (stream)->caps);
7993     if (stream->new_stream) {
7994       gchar *stream_id;
7995       GstEvent *event;
7996       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7997
7998       event =
7999           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8000           0);
8001       if (event) {
8002         gst_event_parse_stream_flags (event, &stream_flags);
8003         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8004           qtdemux->have_group_id = TRUE;
8005         else
8006           qtdemux->have_group_id = FALSE;
8007         gst_event_unref (event);
8008       } else if (!qtdemux->have_group_id) {
8009         qtdemux->have_group_id = TRUE;
8010         qtdemux->group_id = gst_util_group_id_next ();
8011       }
8012
8013       stream->new_stream = FALSE;
8014       stream_id =
8015           gst_pad_create_stream_id_printf (stream->pad,
8016           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
8017       event = gst_event_new_stream_start (stream_id);
8018       if (qtdemux->have_group_id)
8019         gst_event_set_group_id (event, qtdemux->group_id);
8020       if (stream->disabled)
8021         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8022       if (CUR_STREAM (stream)->sparse) {
8023         stream_flags |= GST_STREAM_FLAG_SPARSE;
8024       } else {
8025         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8026       }
8027       gst_event_set_stream_flags (event, stream_flags);
8028       gst_pad_push_event (stream->pad, event);
8029       g_free (stream_id);
8030     }
8031
8032     prev_caps = gst_pad_get_current_caps (stream->pad);
8033
8034     if (CUR_STREAM (stream)->caps) {
8035       if (!prev_caps
8036           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8037         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8038             CUR_STREAM (stream)->caps);
8039         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8040       } else {
8041         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8042       }
8043     } else {
8044       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8045     }
8046
8047     if (prev_caps)
8048       gst_caps_unref (prev_caps);
8049     stream->new_caps = FALSE;
8050   }
8051   return TRUE;
8052 }
8053
8054 static void
8055 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8056     QtDemuxStream * stream)
8057 {
8058   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8059     return;
8060
8061   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8062       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8063   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8064           stream->stsd_entries_length)) {
8065     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8066         (_("This file is invalid and cannot be played.")),
8067         ("New sample description id is out of bounds (%d >= %d)",
8068             stream->stsd_sample_description_id, stream->stsd_entries_length));
8069   } else {
8070     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8071     stream->new_caps = TRUE;
8072   }
8073 }
8074
8075 static gboolean
8076 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8077     QtDemuxStream * stream, GstTagList * list)
8078 {
8079   gboolean ret = TRUE;
8080   /* consistent default for push based mode */
8081   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8082
8083   if (stream->subtype == FOURCC_vide) {
8084     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8085
8086     stream->pad =
8087         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8088     g_free (name);
8089
8090     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8091       gst_object_unref (stream->pad);
8092       stream->pad = NULL;
8093       ret = FALSE;
8094       goto done;
8095     }
8096
8097     qtdemux->n_video_streams++;
8098   } else if (stream->subtype == FOURCC_soun) {
8099     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8100
8101     stream->pad =
8102         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8103     g_free (name);
8104     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8105       gst_object_unref (stream->pad);
8106       stream->pad = NULL;
8107       ret = FALSE;
8108       goto done;
8109     }
8110     qtdemux->n_audio_streams++;
8111   } else if (stream->subtype == FOURCC_strm) {
8112     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8113   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8114       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8115     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8116
8117     stream->pad =
8118         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8119     g_free (name);
8120     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8121       gst_object_unref (stream->pad);
8122       stream->pad = NULL;
8123       ret = FALSE;
8124       goto done;
8125     }
8126     qtdemux->n_sub_streams++;
8127   } else if (CUR_STREAM (stream)->caps) {
8128     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8129
8130     stream->pad =
8131         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8132     g_free (name);
8133     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8134       gst_object_unref (stream->pad);
8135       stream->pad = NULL;
8136       ret = FALSE;
8137       goto done;
8138     }
8139     qtdemux->n_video_streams++;
8140   } else {
8141     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8142     goto done;
8143   }
8144
8145   if (stream->pad) {
8146     GList *l;
8147
8148     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8149         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8150     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8151     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8152
8153     if (stream->stream_tags)
8154       gst_tag_list_unref (stream->stream_tags);
8155     stream->stream_tags = list;
8156     list = NULL;
8157     /* global tags go on each pad anyway */
8158     stream->send_global_tags = TRUE;
8159     /* send upstream GST_EVENT_PROTECTION events that were received before
8160        this source pad was created */
8161     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8162       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8163   }
8164 done:
8165   if (list)
8166     gst_tag_list_unref (list);
8167   return ret;
8168 }
8169
8170 /* find next atom with @fourcc starting at @offset */
8171 static GstFlowReturn
8172 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8173     guint64 * length, guint32 fourcc)
8174 {
8175   GstFlowReturn ret;
8176   guint32 lfourcc;
8177   GstBuffer *buf;
8178
8179   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8180       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8181
8182   while (TRUE) {
8183     GstMapInfo map;
8184
8185     buf = NULL;
8186     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8187     if (G_UNLIKELY (ret != GST_FLOW_OK))
8188       goto locate_failed;
8189     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8190       /* likely EOF */
8191       ret = GST_FLOW_EOS;
8192       gst_buffer_unref (buf);
8193       goto locate_failed;
8194     }
8195     gst_buffer_map (buf, &map, GST_MAP_READ);
8196     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8197     gst_buffer_unmap (buf, &map);
8198     gst_buffer_unref (buf);
8199
8200     if (G_UNLIKELY (*length == 0)) {
8201       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8202       ret = GST_FLOW_ERROR;
8203       goto locate_failed;
8204     }
8205
8206     if (lfourcc == fourcc) {
8207       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8208           *offset);
8209       break;
8210     } else {
8211       GST_LOG_OBJECT (qtdemux,
8212           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8213           GST_FOURCC_ARGS (fourcc), *offset);
8214       *offset += *length;
8215     }
8216   }
8217
8218   return GST_FLOW_OK;
8219
8220 locate_failed:
8221   {
8222     /* might simply have had last one */
8223     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8224     return ret;
8225   }
8226 }
8227
8228 /* should only do something in pull mode */
8229 /* call with OBJECT lock */
8230 static GstFlowReturn
8231 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8232 {
8233   guint64 length, offset;
8234   GstBuffer *buf = NULL;
8235   GstFlowReturn ret = GST_FLOW_OK;
8236   GstFlowReturn res = GST_FLOW_OK;
8237   GstMapInfo map;
8238
8239   offset = qtdemux->moof_offset;
8240   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8241
8242   if (!offset) {
8243     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8244     return GST_FLOW_EOS;
8245   }
8246
8247   /* best not do pull etc with lock held */
8248   GST_OBJECT_UNLOCK (qtdemux);
8249
8250   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8251   if (ret != GST_FLOW_OK)
8252     goto flow_failed;
8253
8254   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8255   if (G_UNLIKELY (ret != GST_FLOW_OK))
8256     goto flow_failed;
8257   gst_buffer_map (buf, &map, GST_MAP_READ);
8258   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8259     gst_buffer_unmap (buf, &map);
8260     gst_buffer_unref (buf);
8261     buf = NULL;
8262     goto parse_failed;
8263   }
8264
8265   gst_buffer_unmap (buf, &map);
8266   gst_buffer_unref (buf);
8267   buf = NULL;
8268
8269   offset += length;
8270   /* look for next moof */
8271   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8272   if (G_UNLIKELY (ret != GST_FLOW_OK))
8273     goto flow_failed;
8274
8275 exit:
8276   GST_OBJECT_LOCK (qtdemux);
8277
8278   qtdemux->moof_offset = offset;
8279
8280   return res;
8281
8282 parse_failed:
8283   {
8284     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8285     offset = 0;
8286     res = GST_FLOW_ERROR;
8287     goto exit;
8288   }
8289 flow_failed:
8290   {
8291     /* maybe upstream temporarily flushing */
8292     if (ret != GST_FLOW_FLUSHING) {
8293       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8294       offset = 0;
8295     } else {
8296       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8297       /* resume at current position next time */
8298     }
8299     res = ret;
8300     goto exit;
8301   }
8302 }
8303
8304 /* initialise bytereaders for stbl sub-atoms */
8305 static gboolean
8306 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8307 {
8308   stream->stbl_index = -1;      /* no samples have yet been parsed */
8309   stream->sample_index = -1;
8310
8311   /* time-to-sample atom */
8312   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8313     goto corrupt_file;
8314
8315   /* copy atom data into a new buffer for later use */
8316   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8317
8318   /* skip version + flags */
8319   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8320       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8321     goto corrupt_file;
8322   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8323
8324   /* make sure there's enough data */
8325   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8326     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8327     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8328         stream->n_sample_times);
8329     if (!stream->n_sample_times)
8330       goto corrupt_file;
8331   }
8332
8333   /* sync sample atom */
8334   stream->stps_present = FALSE;
8335   if ((stream->stss_present =
8336           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8337               &stream->stss) ? TRUE : FALSE) == TRUE) {
8338     /* copy atom data into a new buffer for later use */
8339     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8340
8341     /* skip version + flags */
8342     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8343         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8344       goto corrupt_file;
8345
8346     if (stream->n_sample_syncs) {
8347       /* make sure there's enough data */
8348       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8349         goto corrupt_file;
8350     }
8351
8352     /* partial sync sample atom */
8353     if ((stream->stps_present =
8354             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8355                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8356       /* copy atom data into a new buffer for later use */
8357       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8358
8359       /* skip version + flags */
8360       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8361           !gst_byte_reader_get_uint32_be (&stream->stps,
8362               &stream->n_sample_partial_syncs))
8363         goto corrupt_file;
8364
8365       /* if there are no entries, the stss table contains the real
8366        * sync samples */
8367       if (stream->n_sample_partial_syncs) {
8368         /* make sure there's enough data */
8369         if (!qt_atom_parser_has_chunks (&stream->stps,
8370                 stream->n_sample_partial_syncs, 4))
8371           goto corrupt_file;
8372       }
8373     }
8374   }
8375
8376   /* sample size */
8377   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8378     goto no_samples;
8379
8380   /* copy atom data into a new buffer for later use */
8381   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8382
8383   /* skip version + flags */
8384   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8385       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8386     goto corrupt_file;
8387
8388   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8389     goto corrupt_file;
8390
8391   if (!stream->n_samples)
8392     goto no_samples;
8393
8394   /* sample-to-chunk atom */
8395   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8396     goto corrupt_file;
8397
8398   /* copy atom data into a new buffer for later use */
8399   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8400
8401   /* skip version + flags */
8402   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8403       !gst_byte_reader_get_uint32_be (&stream->stsc,
8404           &stream->n_samples_per_chunk))
8405     goto corrupt_file;
8406
8407   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8408       stream->n_samples_per_chunk);
8409
8410   /* make sure there's enough data */
8411   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8412           12))
8413     goto corrupt_file;
8414
8415
8416   /* chunk offset */
8417   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8418     stream->co_size = sizeof (guint32);
8419   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8420           &stream->stco))
8421     stream->co_size = sizeof (guint64);
8422   else
8423     goto corrupt_file;
8424
8425   /* copy atom data into a new buffer for later use */
8426   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8427
8428   /* skip version + flags */
8429   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8430     goto corrupt_file;
8431
8432   /* chunks_are_samples == TRUE means treat chunks as samples */
8433   stream->chunks_are_samples = stream->sample_size
8434       && !CUR_STREAM (stream)->sampled;
8435   if (stream->chunks_are_samples) {
8436     /* treat chunks as samples */
8437     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8438       goto corrupt_file;
8439   } else {
8440     /* skip number of entries */
8441     if (!gst_byte_reader_skip (&stream->stco, 4))
8442       goto corrupt_file;
8443
8444     /* make sure there are enough data in the stsz atom */
8445     if (!stream->sample_size) {
8446       /* different sizes for each sample */
8447       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8448         goto corrupt_file;
8449     }
8450   }
8451
8452   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8453       stream->n_samples, (guint) sizeof (QtDemuxSample),
8454       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8455
8456   if (stream->n_samples >=
8457       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8458     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8459         "be larger than %uMB (broken file?)", stream->n_samples,
8460         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8461     return FALSE;
8462   }
8463
8464   g_assert (stream->samples == NULL);
8465   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8466   if (!stream->samples) {
8467     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8468         stream->n_samples);
8469     return FALSE;
8470   }
8471
8472   /* composition time-to-sample */
8473   if ((stream->ctts_present =
8474           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8475               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8476     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8477
8478     /* copy atom data into a new buffer for later use */
8479     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8480
8481     /* skip version + flags */
8482     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8483         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8484             &stream->n_composition_times))
8485       goto corrupt_file;
8486
8487     /* make sure there's enough data */
8488     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8489             4 + 4))
8490       goto corrupt_file;
8491
8492     /* This is optional, if missing we iterate the ctts */
8493     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8494       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8495           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8496         g_free ((gpointer) cslg.data);
8497         goto corrupt_file;
8498       }
8499     } else {
8500       gint32 cslg_least = 0;
8501       guint num_entries, pos;
8502       gint i;
8503
8504       pos = gst_byte_reader_get_pos (&stream->ctts);
8505       num_entries = stream->n_composition_times;
8506
8507       stream->cslg_shift = 0;
8508
8509       for (i = 0; i < num_entries; i++) {
8510         gint32 offset;
8511
8512         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8513         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8514
8515         if (offset < cslg_least)
8516           cslg_least = offset;
8517       }
8518
8519       if (cslg_least < 0)
8520         stream->cslg_shift = ABS (cslg_least);
8521       else
8522         stream->cslg_shift = 0;
8523
8524       /* reset the reader so we can generate sample table */
8525       gst_byte_reader_set_pos (&stream->ctts, pos);
8526     }
8527   } else {
8528     /* Ensure the cslg_shift value is consistent so we can use it
8529      * unconditionnally to produce TS and Segment */
8530     stream->cslg_shift = 0;
8531   }
8532
8533   return TRUE;
8534
8535 corrupt_file:
8536   {
8537     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8538         (_("This file is corrupt and cannot be played.")), (NULL));
8539     return FALSE;
8540   }
8541 no_samples:
8542   {
8543     gst_qtdemux_stbl_free (stream);
8544     if (!qtdemux->fragmented) {
8545       /* not quite good */
8546       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8547       return FALSE;
8548     } else {
8549       /* may pick up samples elsewhere */
8550       return TRUE;
8551     }
8552   }
8553 }
8554
8555 /* collect samples from the next sample to be parsed up to sample @n for @stream
8556  * by reading the info from @stbl
8557  *
8558  * This code can be executed from both the streaming thread and the seeking
8559  * thread so it takes the object lock to protect itself
8560  */
8561 static gboolean
8562 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8563 {
8564   gint i, j, k;
8565   QtDemuxSample *samples, *first, *cur, *last;
8566   guint32 n_samples_per_chunk;
8567   guint32 n_samples;
8568
8569   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8570       GST_FOURCC_FORMAT ", pad %s",
8571       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8572       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8573
8574   n_samples = stream->n_samples;
8575
8576   if (n >= n_samples)
8577     goto out_of_samples;
8578
8579   GST_OBJECT_LOCK (qtdemux);
8580   if (n <= stream->stbl_index)
8581     goto already_parsed;
8582
8583   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8584
8585   if (!stream->stsz.data) {
8586     /* so we already parsed and passed all the moov samples;
8587      * onto fragmented ones */
8588     g_assert (qtdemux->fragmented);
8589     goto done;
8590   }
8591
8592   /* pointer to the sample table */
8593   samples = stream->samples;
8594
8595   /* starts from -1, moves to the next sample index to parse */
8596   stream->stbl_index++;
8597
8598   /* keep track of the first and last sample to fill */
8599   first = &samples[stream->stbl_index];
8600   last = &samples[n];
8601
8602   if (!stream->chunks_are_samples) {
8603     /* set the sample sizes */
8604     if (stream->sample_size == 0) {
8605       /* different sizes for each sample */
8606       for (cur = first; cur <= last; cur++) {
8607         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8608         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8609             (guint) (cur - samples), cur->size);
8610       }
8611     } else {
8612       /* samples have the same size */
8613       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8614       for (cur = first; cur <= last; cur++)
8615         cur->size = stream->sample_size;
8616     }
8617   }
8618
8619   n_samples_per_chunk = stream->n_samples_per_chunk;
8620   cur = first;
8621
8622   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8623     guint32 last_chunk;
8624
8625     if (stream->stsc_chunk_index >= stream->last_chunk
8626         || stream->stsc_chunk_index < stream->first_chunk) {
8627       stream->first_chunk =
8628           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8629       stream->samples_per_chunk =
8630           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8631       /* starts from 1 */
8632       stream->stsd_sample_description_id =
8633           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8634
8635       /* chunk numbers are counted from 1 it seems */
8636       if (G_UNLIKELY (stream->first_chunk == 0))
8637         goto corrupt_file;
8638
8639       --stream->first_chunk;
8640
8641       /* the last chunk of each entry is calculated by taking the first chunk
8642        * of the next entry; except if there is no next, where we fake it with
8643        * INT_MAX */
8644       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8645         stream->last_chunk = G_MAXUINT32;
8646       } else {
8647         stream->last_chunk =
8648             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8649         if (G_UNLIKELY (stream->last_chunk == 0))
8650           goto corrupt_file;
8651
8652         --stream->last_chunk;
8653       }
8654
8655       GST_LOG_OBJECT (qtdemux,
8656           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8657           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8658           stream->samples_per_chunk, stream->stsd_sample_description_id);
8659
8660       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8661         goto corrupt_file;
8662
8663       if (stream->last_chunk != G_MAXUINT32) {
8664         if (!qt_atom_parser_peek_sub (&stream->stco,
8665                 stream->first_chunk * stream->co_size,
8666                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8667                 &stream->co_chunk))
8668           goto corrupt_file;
8669
8670       } else {
8671         stream->co_chunk = stream->stco;
8672         if (!gst_byte_reader_skip (&stream->co_chunk,
8673                 stream->first_chunk * stream->co_size))
8674           goto corrupt_file;
8675       }
8676
8677       stream->stsc_chunk_index = stream->first_chunk;
8678     }
8679
8680     last_chunk = stream->last_chunk;
8681
8682     if (stream->chunks_are_samples) {
8683       cur = &samples[stream->stsc_chunk_index];
8684
8685       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8686         if (j > n) {
8687           /* save state */
8688           stream->stsc_chunk_index = j;
8689           goto done;
8690         }
8691
8692         cur->offset =
8693             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8694             stream->co_size);
8695
8696         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8697             "%" G_GUINT64_FORMAT, j, cur->offset);
8698
8699         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8700             CUR_STREAM (stream)->bytes_per_frame > 0) {
8701           cur->size =
8702               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8703               CUR_STREAM (stream)->samples_per_frame *
8704               CUR_STREAM (stream)->bytes_per_frame;
8705         } else {
8706           cur->size = stream->samples_per_chunk;
8707         }
8708
8709         GST_DEBUG_OBJECT (qtdemux,
8710             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8711             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8712                     stream->stco_sample_index)), cur->size);
8713
8714         cur->timestamp = stream->stco_sample_index;
8715         cur->duration = stream->samples_per_chunk;
8716         cur->keyframe = TRUE;
8717         cur++;
8718
8719         stream->stco_sample_index += stream->samples_per_chunk;
8720       }
8721       stream->stsc_chunk_index = j;
8722     } else {
8723       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8724         guint32 samples_per_chunk;
8725         guint64 chunk_offset;
8726
8727         if (!stream->stsc_sample_index
8728             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8729                 &stream->chunk_offset))
8730           goto corrupt_file;
8731
8732         samples_per_chunk = stream->samples_per_chunk;
8733         chunk_offset = stream->chunk_offset;
8734
8735         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8736           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8737               G_GUINT64_FORMAT " and size %d",
8738               (guint) (cur - samples), chunk_offset, cur->size);
8739
8740           cur->offset = chunk_offset;
8741           chunk_offset += cur->size;
8742           cur++;
8743
8744           if (G_UNLIKELY (cur > last)) {
8745             /* save state */
8746             stream->stsc_sample_index = k + 1;
8747             stream->chunk_offset = chunk_offset;
8748             stream->stsc_chunk_index = j;
8749             goto done2;
8750           }
8751         }
8752         stream->stsc_sample_index = 0;
8753       }
8754       stream->stsc_chunk_index = j;
8755     }
8756     stream->stsc_index++;
8757   }
8758
8759   if (stream->chunks_are_samples)
8760     goto ctts;
8761 done2:
8762   {
8763     guint32 n_sample_times;
8764
8765     n_sample_times = stream->n_sample_times;
8766     cur = first;
8767
8768     for (i = stream->stts_index; i < n_sample_times; i++) {
8769       guint32 stts_samples;
8770       gint32 stts_duration;
8771       gint64 stts_time;
8772
8773       if (stream->stts_sample_index >= stream->stts_samples
8774           || !stream->stts_sample_index) {
8775
8776         stream->stts_samples =
8777             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8778         stream->stts_duration =
8779             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8780
8781         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8782             i, stream->stts_samples, stream->stts_duration);
8783
8784         stream->stts_sample_index = 0;
8785       }
8786
8787       stts_samples = stream->stts_samples;
8788       stts_duration = stream->stts_duration;
8789       stts_time = stream->stts_time;
8790
8791       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8792         GST_DEBUG_OBJECT (qtdemux,
8793             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8794             (guint) (cur - samples), j,
8795             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8796
8797         cur->timestamp = stts_time;
8798         cur->duration = stts_duration;
8799
8800         /* avoid 32-bit wrap-around,
8801          * but still mind possible 'negative' duration */
8802         stts_time += (gint64) stts_duration;
8803         cur++;
8804
8805         if (G_UNLIKELY (cur > last)) {
8806           /* save values */
8807           stream->stts_time = stts_time;
8808           stream->stts_sample_index = j + 1;
8809           if (stream->stts_sample_index >= stream->stts_samples)
8810             stream->stts_index++;
8811           goto done3;
8812         }
8813       }
8814       stream->stts_sample_index = 0;
8815       stream->stts_time = stts_time;
8816       stream->stts_index++;
8817     }
8818     /* fill up empty timestamps with the last timestamp, this can happen when
8819      * the last samples do not decode and so we don't have timestamps for them.
8820      * We however look at the last timestamp to estimate the track length so we
8821      * need something in here. */
8822     for (; cur < last; cur++) {
8823       GST_DEBUG_OBJECT (qtdemux,
8824           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8825           (guint) (cur - samples),
8826           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8827       cur->timestamp = stream->stts_time;
8828       cur->duration = -1;
8829     }
8830   }
8831 done3:
8832   {
8833     /* sample sync, can be NULL */
8834     if (stream->stss_present == TRUE) {
8835       guint32 n_sample_syncs;
8836
8837       n_sample_syncs = stream->n_sample_syncs;
8838
8839       if (!n_sample_syncs) {
8840         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8841         stream->all_keyframe = TRUE;
8842       } else {
8843         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8844           /* note that the first sample is index 1, not 0 */
8845           guint32 index;
8846
8847           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8848
8849           if (G_LIKELY (index > 0 && index <= n_samples)) {
8850             index -= 1;
8851             samples[index].keyframe = TRUE;
8852             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8853             /* and exit if we have enough samples */
8854             if (G_UNLIKELY (index >= n)) {
8855               i++;
8856               break;
8857             }
8858           }
8859         }
8860         /* save state */
8861         stream->stss_index = i;
8862       }
8863
8864       /* stps marks partial sync frames like open GOP I-Frames */
8865       if (stream->stps_present == TRUE) {
8866         guint32 n_sample_partial_syncs;
8867
8868         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8869
8870         /* if there are no entries, the stss table contains the real
8871          * sync samples */
8872         if (n_sample_partial_syncs) {
8873           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8874             /* note that the first sample is index 1, not 0 */
8875             guint32 index;
8876
8877             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8878
8879             if (G_LIKELY (index > 0 && index <= n_samples)) {
8880               index -= 1;
8881               samples[index].keyframe = TRUE;
8882               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8883               /* and exit if we have enough samples */
8884               if (G_UNLIKELY (index >= n)) {
8885                 i++;
8886                 break;
8887               }
8888             }
8889           }
8890           /* save state */
8891           stream->stps_index = i;
8892         }
8893       }
8894     } else {
8895       /* no stss, all samples are keyframes */
8896       stream->all_keyframe = TRUE;
8897       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8898     }
8899   }
8900
8901 ctts:
8902   /* composition time to sample */
8903   if (stream->ctts_present == TRUE) {
8904     guint32 n_composition_times;
8905     guint32 ctts_count;
8906     gint32 ctts_soffset;
8907
8908     /* Fill in the pts_offsets */
8909     cur = first;
8910     n_composition_times = stream->n_composition_times;
8911
8912     for (i = stream->ctts_index; i < n_composition_times; i++) {
8913       if (stream->ctts_sample_index >= stream->ctts_count
8914           || !stream->ctts_sample_index) {
8915         stream->ctts_count =
8916             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8917         stream->ctts_soffset =
8918             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8919         stream->ctts_sample_index = 0;
8920       }
8921
8922       ctts_count = stream->ctts_count;
8923       ctts_soffset = stream->ctts_soffset;
8924
8925       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8926         cur->pts_offset = ctts_soffset;
8927         cur++;
8928
8929         if (G_UNLIKELY (cur > last)) {
8930           /* save state */
8931           stream->ctts_sample_index = j + 1;
8932           goto done;
8933         }
8934       }
8935       stream->ctts_sample_index = 0;
8936       stream->ctts_index++;
8937     }
8938   }
8939 done:
8940   stream->stbl_index = n;
8941   /* if index has been completely parsed, free data that is no-longer needed */
8942   if (n + 1 == stream->n_samples) {
8943     gst_qtdemux_stbl_free (stream);
8944     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8945     if (qtdemux->pullbased) {
8946       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8947       while (n + 1 == stream->n_samples)
8948         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8949           break;
8950     }
8951   }
8952   GST_OBJECT_UNLOCK (qtdemux);
8953
8954   return TRUE;
8955
8956   /* SUCCESS */
8957 already_parsed:
8958   {
8959     GST_LOG_OBJECT (qtdemux,
8960         "Tried to parse up to sample %u but this sample has already been parsed",
8961         n);
8962     /* if fragmented, there may be more */
8963     if (qtdemux->fragmented && n == stream->stbl_index)
8964       goto done;
8965     GST_OBJECT_UNLOCK (qtdemux);
8966     return TRUE;
8967   }
8968   /* ERRORS */
8969 out_of_samples:
8970   {
8971     GST_LOG_OBJECT (qtdemux,
8972         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8973         stream->n_samples);
8974     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8975         (_("This file is corrupt and cannot be played.")), (NULL));
8976     return FALSE;
8977   }
8978 corrupt_file:
8979   {
8980     GST_OBJECT_UNLOCK (qtdemux);
8981     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8982         (_("This file is corrupt and cannot be played.")), (NULL));
8983     return FALSE;
8984   }
8985 }
8986
8987 /* collect all segment info for @stream.
8988  */
8989 static gboolean
8990 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8991     GNode * trak)
8992 {
8993   GNode *edts;
8994   /* accept edts if they contain gaps at start and there is only
8995    * one media segment */
8996   gboolean allow_pushbased_edts = TRUE;
8997   gint media_segments_count = 0;
8998
8999   /* parse and prepare segment info from the edit list */
9000   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9001   stream->n_segments = 0;
9002   stream->segments = NULL;
9003   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9004     GNode *elst;
9005     gint n_segments;
9006     gint i, count, entry_size;
9007     guint64 time;
9008     GstClockTime stime;
9009     const guint8 *buffer;
9010     guint8 version;
9011     guint32 size;
9012
9013     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9014     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9015       goto done;
9016
9017     buffer = elst->data;
9018
9019     size = QT_UINT32 (buffer);
9020     /* version, flags, n_segments */
9021     if (size < 16) {
9022       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9023       goto done;
9024     }
9025     version = QT_UINT8 (buffer + 8);
9026     entry_size = (version == 1) ? 20 : 12;
9027
9028     n_segments = QT_UINT32 (buffer + 12);
9029
9030     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9031       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9032       goto done;
9033     }
9034
9035     /* we might allocate a bit too much, at least allocate 1 segment */
9036     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9037
9038     /* segments always start from 0 */
9039     time = 0;
9040     stime = 0;
9041     count = 0;
9042     buffer += 16;
9043     for (i = 0; i < n_segments; i++) {
9044       guint64 duration;
9045       guint64 media_time;
9046       gboolean time_valid = TRUE;
9047       QtDemuxSegment *segment;
9048       guint32 rate_int;
9049       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9050
9051       if (version == 1) {
9052         media_time = QT_UINT64 (buffer + 8);
9053         duration = QT_UINT64 (buffer);
9054         if (media_time == G_MAXUINT64)
9055           time_valid = FALSE;
9056       } else {
9057         media_time = QT_UINT32 (buffer + 4);
9058         duration = QT_UINT32 (buffer);
9059         if (media_time == G_MAXUINT32)
9060           time_valid = FALSE;
9061       }
9062
9063       if (time_valid)
9064         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9065
9066       segment = &stream->segments[count++];
9067
9068       /* time and duration expressed in global timescale */
9069       segment->time = stime;
9070       /* add non scaled values so we don't cause roundoff errors */
9071       if (duration || media_start == GST_CLOCK_TIME_NONE) {
9072         time += duration;
9073         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9074         segment->duration = stime - segment->time;
9075       } else {
9076         /* zero duration does not imply media_start == media_stop
9077          * but, only specify media_start.*/
9078         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9079         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9080             && stime >= media_start) {
9081           segment->duration = stime - media_start;
9082         } else {
9083           segment->duration = GST_CLOCK_TIME_NONE;
9084         }
9085       }
9086       segment->stop_time = stime;
9087
9088       segment->trak_media_start = media_time;
9089       /* media_time expressed in stream timescale */
9090       if (time_valid) {
9091         segment->media_start = media_start;
9092         segment->media_stop = segment->media_start + segment->duration;
9093         media_segments_count++;
9094       } else {
9095         segment->media_start = GST_CLOCK_TIME_NONE;
9096         segment->media_stop = GST_CLOCK_TIME_NONE;
9097       }
9098       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9099
9100       if (rate_int <= 1) {
9101         /* 0 is not allowed, some programs write 1 instead of the floating point
9102          * value */
9103         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9104             rate_int);
9105         segment->rate = 1;
9106       } else {
9107         segment->rate = rate_int / 65536.0;
9108       }
9109
9110       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9111           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9112           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9113           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9114           i, GST_TIME_ARGS (segment->time),
9115           GST_TIME_ARGS (segment->duration),
9116           GST_TIME_ARGS (segment->media_start), media_time,
9117           GST_TIME_ARGS (segment->media_stop),
9118           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9119           stream->timescale);
9120       if (segment->stop_time > qtdemux->segment.stop) {
9121         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9122             " extends to %" GST_TIME_FORMAT
9123             " past the end of the file duration %" GST_TIME_FORMAT
9124             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9125             GST_TIME_ARGS (qtdemux->segment.stop));
9126         qtdemux->segment.stop = segment->stop_time;
9127       }
9128
9129       buffer += entry_size;
9130     }
9131     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9132     stream->n_segments = count;
9133     if (media_segments_count != 1)
9134       allow_pushbased_edts = FALSE;
9135   }
9136 done:
9137
9138   /* push based does not handle segments, so act accordingly here,
9139    * and warn if applicable */
9140   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9141     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9142     /* remove and use default one below, we stream like it anyway */
9143     g_free (stream->segments);
9144     stream->segments = NULL;
9145     stream->n_segments = 0;
9146   }
9147
9148   /* no segments, create one to play the complete trak */
9149   if (stream->n_segments == 0) {
9150     GstClockTime stream_duration =
9151         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9152
9153     if (stream->segments == NULL)
9154       stream->segments = g_new (QtDemuxSegment, 1);
9155
9156     /* represent unknown our way */
9157     if (stream_duration == 0)
9158       stream_duration = GST_CLOCK_TIME_NONE;
9159
9160     stream->segments[0].time = 0;
9161     stream->segments[0].stop_time = stream_duration;
9162     stream->segments[0].duration = stream_duration;
9163     stream->segments[0].media_start = 0;
9164     stream->segments[0].media_stop = stream_duration;
9165     stream->segments[0].rate = 1.0;
9166     stream->segments[0].trak_media_start = 0;
9167
9168     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9169         GST_TIME_ARGS (stream_duration));
9170     stream->n_segments = 1;
9171     stream->dummy_segment = TRUE;
9172   }
9173   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9174
9175   return TRUE;
9176 }
9177
9178 /*
9179  * Parses the stsd atom of a svq3 trak looking for
9180  * the SMI and gama atoms.
9181  */
9182 static void
9183 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9184     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9185 {
9186   const guint8 *_gamma = NULL;
9187   GstBuffer *_seqh = NULL;
9188   const guint8 *stsd_data = stsd_entry_data;
9189   guint32 length = QT_UINT32 (stsd_data);
9190   guint16 version;
9191
9192   if (length < 32) {
9193     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9194     goto end;
9195   }
9196
9197   stsd_data += 16;
9198   length -= 16;
9199   version = QT_UINT16 (stsd_data);
9200   if (version == 3) {
9201     if (length >= 70) {
9202       length -= 70;
9203       stsd_data += 70;
9204       while (length > 8) {
9205         guint32 fourcc, size;
9206         const guint8 *data;
9207         size = QT_UINT32 (stsd_data);
9208         fourcc = QT_FOURCC (stsd_data + 4);
9209         data = stsd_data + 8;
9210
9211         if (size == 0) {
9212           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9213               "svq3 atom parsing");
9214           goto end;
9215         }
9216
9217         switch (fourcc) {
9218           case FOURCC_gama:{
9219             if (size == 12) {
9220               _gamma = data;
9221             } else {
9222               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9223                   " for gama atom, expected 12", size);
9224             }
9225             break;
9226           }
9227           case FOURCC_SMI_:{
9228             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9229               guint32 seqh_size;
9230               if (_seqh != NULL) {
9231                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9232                     " found, ignoring");
9233               } else {
9234                 seqh_size = QT_UINT32 (data + 4);
9235                 if (seqh_size > 0) {
9236                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9237                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9238                 }
9239               }
9240             }
9241             break;
9242           }
9243           default:{
9244             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9245                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9246           }
9247         }
9248
9249         if (size <= length) {
9250           length -= size;
9251           stsd_data += size;
9252         }
9253       }
9254     } else {
9255       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9256     }
9257   } else {
9258     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9259         G_GUINT16_FORMAT, version);
9260     goto end;
9261   }
9262
9263 end:
9264   if (gamma) {
9265     *gamma = _gamma;
9266   }
9267   if (seqh) {
9268     *seqh = _seqh;
9269   } else if (_seqh) {
9270     gst_buffer_unref (_seqh);
9271   }
9272 }
9273
9274 static gchar *
9275 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9276 {
9277   GNode *dinf;
9278   GstByteReader dref;
9279   gchar *uri = NULL;
9280
9281   /*
9282    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9283    * atom that might contain a 'data' atom with the rtsp uri.
9284    * This case was reported in bug #597497, some info about
9285    * the hndl atom can be found in TN1195
9286    */
9287   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9288   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9289
9290   if (dinf) {
9291     guint32 dref_num_entries = 0;
9292     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9293         gst_byte_reader_skip (&dref, 4) &&
9294         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9295       gint i;
9296
9297       /* search dref entries for hndl atom */
9298       for (i = 0; i < dref_num_entries; i++) {
9299         guint32 size = 0, type;
9300         guint8 string_len = 0;
9301         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9302             qt_atom_parser_get_fourcc (&dref, &type)) {
9303           if (type == FOURCC_hndl) {
9304             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9305
9306             /* skip data reference handle bytes and the
9307              * following pascal string and some extra 4
9308              * bytes I have no idea what are */
9309             if (!gst_byte_reader_skip (&dref, 4) ||
9310                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9311                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9312               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9313               break;
9314             }
9315
9316             /* iterate over the atoms to find the data atom */
9317             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9318               guint32 atom_size;
9319               guint32 atom_type;
9320
9321               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9322                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9323                 if (atom_type == FOURCC_data) {
9324                   const guint8 *uri_aux = NULL;
9325
9326                   /* found the data atom that might contain the rtsp uri */
9327                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9328                       "hndl atom, interpreting it as an URI");
9329                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9330                           &uri_aux)) {
9331                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9332                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9333                     else
9334                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9335                           "didn't contain a rtsp address");
9336                   } else {
9337                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9338                         "atom contents");
9339                   }
9340                   break;
9341                 }
9342                 /* skipping to the next entry */
9343                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9344                   break;
9345               } else {
9346                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9347                     "atom header");
9348                 break;
9349               }
9350             }
9351             break;
9352           }
9353           /* skip to the next entry */
9354           if (!gst_byte_reader_skip (&dref, size - 8))
9355             break;
9356         } else {
9357           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9358         }
9359       }
9360       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9361     }
9362   }
9363   return uri;
9364 }
9365
9366 #define AMR_NB_ALL_MODES        0x81ff
9367 #define AMR_WB_ALL_MODES        0x83ff
9368 static guint
9369 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9370 {
9371   /* The 'damr' atom is of the form:
9372    *
9373    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9374    *    32 b       8 b          16 b           8 b                 8 b
9375    *
9376    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9377    * represents the highest mode used in the stream (and thus the maximum
9378    * bitrate), with a couple of special cases as seen below.
9379    */
9380
9381   /* Map of frame type ID -> bitrate */
9382   static const guint nb_bitrates[] = {
9383     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9384   };
9385   static const guint wb_bitrates[] = {
9386     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9387   };
9388   GstMapInfo map;
9389   gsize max_mode;
9390   guint16 mode_set;
9391
9392   gst_buffer_map (buf, &map, GST_MAP_READ);
9393
9394   if (map.size != 0x11) {
9395     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9396     goto bad_data;
9397   }
9398
9399   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9400     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9401         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9402     goto bad_data;
9403   }
9404
9405   mode_set = QT_UINT16 (map.data + 13);
9406
9407   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9408     max_mode = 7 + (wb ? 1 : 0);
9409   else
9410     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9411     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9412
9413   if (max_mode == -1) {
9414     GST_DEBUG ("No mode indication was found (mode set) = %x",
9415         (guint) mode_set);
9416     goto bad_data;
9417   }
9418
9419   gst_buffer_unmap (buf, &map);
9420   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9421
9422 bad_data:
9423   gst_buffer_unmap (buf, &map);
9424   return 0;
9425 }
9426
9427 static gboolean
9428 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9429     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9430 {
9431   /*
9432    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9433    * [0 1 2]
9434    * [3 4 5]
9435    * [6 7 8]
9436    */
9437
9438   if (gst_byte_reader_get_remaining (reader) < 36)
9439     return FALSE;
9440
9441   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9442   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9443   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9444   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9445   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9446   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9447   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9448   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9449   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9450
9451   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9452   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9453       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9454       matrix[2] & 0xFF);
9455   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9456       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9457       matrix[5] & 0xFF);
9458   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9459       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9460       matrix[8] & 0xFF);
9461
9462   return TRUE;
9463 }
9464
9465 static void
9466 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9467     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9468 {
9469
9470 /* [a b c]
9471  * [d e f]
9472  * [g h i]
9473  *
9474  * This macro will only compare value abdegh, it expects cfi to have already
9475  * been checked
9476  */
9477 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9478                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9479
9480   /* only handle the cases where the last column has standard values */
9481   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9482     const gchar *rotation_tag = NULL;
9483
9484     /* no rotation needed */
9485     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9486       /* NOP */
9487     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9488       rotation_tag = "rotate-90";
9489     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9490       rotation_tag = "rotate-180";
9491     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9492       rotation_tag = "rotate-270";
9493     } else {
9494       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9495     }
9496
9497     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9498         rotation_tag);
9499     if (rotation_tag != NULL) {
9500       if (*taglist == NULL)
9501         *taglist = gst_tag_list_new_empty ();
9502       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9503           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9504     }
9505   } else {
9506     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9507   }
9508 }
9509
9510 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9511  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9512  * Common Encryption (cenc), the function will also parse the tenc box (defined
9513  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9514  * (typically an enc[v|a|t|s] sample entry); the function will set
9515  * @original_fmt to the fourcc of the original unencrypted stream format.
9516  * Returns TRUE if successful; FALSE otherwise. */
9517 static gboolean
9518 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9519     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9520 {
9521   GNode *sinf;
9522   GNode *frma;
9523   GNode *schm;
9524   GNode *schi;
9525
9526   g_return_val_if_fail (qtdemux != NULL, FALSE);
9527   g_return_val_if_fail (stream != NULL, FALSE);
9528   g_return_val_if_fail (container != NULL, FALSE);
9529   g_return_val_if_fail (original_fmt != NULL, FALSE);
9530
9531   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9532   if (G_UNLIKELY (!sinf)) {
9533     if (stream->protection_scheme_type == FOURCC_cenc) {
9534       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9535           "mandatory for Common Encryption");
9536       return FALSE;
9537     }
9538     return TRUE;
9539   }
9540
9541   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9542   if (G_UNLIKELY (!frma)) {
9543     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9544     return FALSE;
9545   }
9546
9547   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9548   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9549       GST_FOURCC_ARGS (*original_fmt));
9550
9551   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9552   if (!schm) {
9553     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9554     return FALSE;
9555   }
9556   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9557   stream->protection_scheme_version =
9558       QT_UINT32 ((const guint8 *) schm->data + 16);
9559
9560   GST_DEBUG_OBJECT (qtdemux,
9561       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9562       "protection_scheme_version: %#010x",
9563       GST_FOURCC_ARGS (stream->protection_scheme_type),
9564       stream->protection_scheme_version);
9565
9566   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9567   if (!schi) {
9568     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9569     return FALSE;
9570   }
9571   if (stream->protection_scheme_type == FOURCC_cenc) {
9572     QtDemuxCencSampleSetInfo *info;
9573     GNode *tenc;
9574     const guint8 *tenc_data;
9575     guint32 isEncrypted;
9576     guint8 iv_size;
9577     const guint8 *default_kid;
9578     GstBuffer *kid_buf;
9579
9580     if (G_UNLIKELY (!stream->protection_scheme_info))
9581       stream->protection_scheme_info =
9582           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9583
9584     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9585
9586     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9587     if (!tenc) {
9588       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9589           "which is mandatory for Common Encryption");
9590       return FALSE;
9591     }
9592     tenc_data = (const guint8 *) tenc->data + 12;
9593     isEncrypted = QT_UINT24 (tenc_data);
9594     iv_size = QT_UINT8 (tenc_data + 3);
9595     default_kid = (tenc_data + 4);
9596     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9597     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9598     if (info->default_properties)
9599       gst_structure_free (info->default_properties);
9600     info->default_properties =
9601         gst_structure_new ("application/x-cenc",
9602         "iv_size", G_TYPE_UINT, iv_size,
9603         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9604         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9605     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9606         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9607     gst_buffer_unref (kid_buf);
9608   }
9609   return TRUE;
9610 }
9611
9612 /* parse the traks.
9613  * With each track we associate a new QtDemuxStream that contains all the info
9614  * about the trak.
9615  * traks that do not decode to something (like strm traks) will not have a pad.
9616  */
9617 static gboolean
9618 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9619 {
9620   GstByteReader tkhd;
9621   int offset;
9622   GNode *mdia;
9623   GNode *mdhd;
9624   GNode *hdlr;
9625   GNode *minf;
9626   GNode *stbl;
9627   GNode *stsd;
9628   GNode *mp4a;
9629   GNode *mp4v;
9630   GNode *esds;
9631   GNode *tref;
9632   GNode *udta;
9633   GNode *svmi;
9634
9635   QtDemuxStream *stream = NULL;
9636   gboolean new_stream = FALSE;
9637   const guint8 *stsd_data;
9638   const guint8 *stsd_entry_data;
9639   guint remaining_stsd_len;
9640   guint stsd_entry_count;
9641   guint stsd_index;
9642   guint16 lang_code;            /* quicktime lang code or packed iso code */
9643   guint32 version;
9644   guint32 tkhd_flags = 0;
9645   guint8 tkhd_version = 0;
9646   guint32 w = 0, h = 0;
9647   guint value_size, stsd_len, len;
9648   guint32 track_id;
9649   guint32 dummy;
9650
9651   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9652
9653   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9654       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9655       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9656     goto corrupt_file;
9657
9658   /* pick between 64 or 32 bits */
9659   value_size = tkhd_version == 1 ? 8 : 4;
9660   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9661       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9662     goto corrupt_file;
9663
9664   if (!qtdemux->got_moov) {
9665     if (qtdemux_find_stream (qtdemux, track_id))
9666       goto existing_stream;
9667     stream = _create_stream ();
9668     stream->track_id = track_id;
9669     new_stream = TRUE;
9670   } else {
9671     stream = qtdemux_find_stream (qtdemux, track_id);
9672     if (!stream) {
9673       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9674       goto skip_track;
9675     }
9676
9677     /* reset reused stream */
9678     gst_qtdemux_stream_reset (qtdemux, stream);
9679   }
9680   /* need defaults for fragments */
9681   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9682
9683   if ((tkhd_flags & 1) == 0)
9684     stream->disabled = TRUE;
9685
9686   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9687       tkhd_version, tkhd_flags, stream->track_id);
9688
9689   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9690     goto corrupt_file;
9691
9692   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9693     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9694     if (qtdemux->major_brand != FOURCC_mjp2 ||
9695         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9696       goto corrupt_file;
9697   }
9698
9699   len = QT_UINT32 ((guint8 *) mdhd->data);
9700   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9701   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9702   if (version == 0x01000000) {
9703     if (len < 38)
9704       goto corrupt_file;
9705     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9706     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9707     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9708   } else {
9709     if (len < 30)
9710       goto corrupt_file;
9711     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9712     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9713     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9714   }
9715
9716   if (lang_code < 0x400) {
9717     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9718   } else if (lang_code == 0x7fff) {
9719     stream->lang_id[0] = 0;     /* unspecified */
9720   } else {
9721     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9722     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9723     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9724     stream->lang_id[3] = 0;
9725   }
9726
9727   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9728       stream->timescale);
9729   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9730       stream->duration);
9731   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9732       lang_code, stream->lang_id);
9733
9734   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9735     goto corrupt_file;
9736
9737   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9738     /* chapters track reference */
9739     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9740     if (chap) {
9741       gsize length = GST_READ_UINT32_BE (chap->data);
9742       if (qtdemux->chapters_track_id)
9743         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9744
9745       if (length >= 12) {
9746         qtdemux->chapters_track_id =
9747             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9748       }
9749     }
9750   }
9751
9752   /* fragmented files may have bogus duration in moov */
9753   if (!qtdemux->fragmented &&
9754       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9755     guint64 tdur1, tdur2;
9756
9757     /* don't overflow */
9758     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9759     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9760
9761     /* HACK:
9762      * some of those trailers, nowadays, have prologue images that are
9763      * themselves video tracks as well. I haven't really found a way to
9764      * identify those yet, except for just looking at their duration. */
9765     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9766       GST_WARNING_OBJECT (qtdemux,
9767           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9768           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9769           "found, assuming preview image or something; skipping track",
9770           stream->duration, stream->timescale, qtdemux->duration,
9771           qtdemux->timescale);
9772       if (new_stream)
9773         gst_qtdemux_stream_free (qtdemux, stream);
9774       return TRUE;
9775     }
9776   }
9777
9778   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9779     goto corrupt_file;
9780
9781   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9782       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9783
9784   len = QT_UINT32 ((guint8 *) hdlr->data);
9785   if (len >= 20)
9786     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9787   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9788       GST_FOURCC_ARGS (stream->subtype));
9789
9790   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9791     goto corrupt_file;
9792
9793   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9794     goto corrupt_file;
9795
9796   /*parse svmi header if existing */
9797   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9798   if (svmi) {
9799     len = QT_UINT32 ((guint8 *) svmi->data);
9800     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9801     if (!version) {
9802       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9803       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9804       guint8 frame_type, frame_layout;
9805
9806       /* MPEG-A stereo video */
9807       if (qtdemux->major_brand == FOURCC_ss02)
9808         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9809
9810       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9811       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9812       switch (frame_type) {
9813         case 0:
9814           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9815           break;
9816         case 1:
9817           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9818           break;
9819         case 2:
9820           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9821           break;
9822         case 3:
9823           /* mode 3 is primary/secondary view sequence, ie
9824            * left/right views in separate tracks. See section 7.2
9825            * of ISO/IEC 23000-11:2009 */
9826           GST_FIXME_OBJECT (qtdemux,
9827               "Implement stereo video in separate streams");
9828       }
9829
9830       if ((frame_layout & 0x1) == 0)
9831         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9832
9833       GST_LOG_OBJECT (qtdemux,
9834           "StereoVideo: composition type: %u, is_left_first: %u",
9835           frame_type, frame_layout);
9836       stream->multiview_mode = mode;
9837       stream->multiview_flags = flags;
9838     }
9839   }
9840
9841   /* parse rest of tkhd */
9842   if (stream->subtype == FOURCC_vide) {
9843     guint32 matrix[9];
9844
9845     /* version 1 uses some 64-bit ints */
9846     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9847       goto corrupt_file;
9848
9849     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9850       goto corrupt_file;
9851
9852     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9853         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9854       goto corrupt_file;
9855
9856     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9857         &stream->stream_tags);
9858   }
9859
9860   /* parse stsd */
9861   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9862     goto corrupt_file;
9863   stsd_data = (const guint8 *) stsd->data;
9864
9865   /* stsd should at least have one entry */
9866   stsd_len = QT_UINT32 (stsd_data);
9867   if (stsd_len < 24) {
9868     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9869     if (stream->subtype == FOURCC_vivo) {
9870       if (new_stream)
9871         gst_qtdemux_stream_free (qtdemux, stream);
9872       return TRUE;
9873     } else {
9874       goto corrupt_file;
9875     }
9876   }
9877
9878   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9879   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9880   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9881   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9882
9883   stsd_entry_data = stsd_data + 16;
9884   remaining_stsd_len = stsd_len - 16;
9885   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9886     guint32 fourcc;
9887     gchar *codec = NULL;
9888     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9889
9890     /* and that entry should fit within stsd */
9891     len = QT_UINT32 (stsd_entry_data);
9892     if (len > remaining_stsd_len)
9893       goto corrupt_file;
9894
9895     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9896     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9897         GST_FOURCC_ARGS (entry->fourcc));
9898     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9899
9900     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9901       goto error_encrypted;
9902
9903     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9904       /* FIXME this looks wrong, there might be multiple children
9905        * with the same type */
9906       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9907       stream->protected = TRUE;
9908       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9909         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9910     }
9911
9912     if (stream->subtype == FOURCC_vide) {
9913       GNode *colr;
9914       GNode *fiel;
9915       GNode *pasp;
9916       gboolean gray;
9917       gint depth, palette_size, palette_count;
9918       guint32 *palette_data = NULL;
9919
9920       entry->sampled = TRUE;
9921
9922       stream->display_width = w >> 16;
9923       stream->display_height = h >> 16;
9924
9925       offset = 16;
9926       if (len < 86)             /* TODO verify */
9927         goto corrupt_file;
9928
9929       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
9930       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
9931       entry->fps_n = 0;         /* this is filled in later */
9932       entry->fps_d = 0;         /* this is filled in later */
9933       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
9934       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
9935
9936       /* if color_table_id is 0, ctab atom must follow; however some files
9937        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9938        * if color table is not present we'll correct the value */
9939       if (entry->color_table_id == 0 &&
9940           (len < 90
9941               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
9942         entry->color_table_id = -1;
9943       }
9944
9945       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9946           entry->width, entry->height, entry->bits_per_sample,
9947           entry->color_table_id);
9948
9949       depth = entry->bits_per_sample;
9950
9951       /* more than 32 bits means grayscale */
9952       gray = (depth > 32);
9953       /* low 32 bits specify the depth  */
9954       depth &= 0x1F;
9955
9956       /* different number of palette entries is determined by depth. */
9957       palette_count = 0;
9958       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9959         palette_count = (1 << depth);
9960       palette_size = palette_count * 4;
9961
9962       if (entry->color_table_id) {
9963         switch (palette_count) {
9964           case 0:
9965             break;
9966           case 2:
9967             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9968             break;
9969           case 4:
9970             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9971             break;
9972           case 16:
9973             if (gray)
9974               palette_data =
9975                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
9976             else
9977               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9978             break;
9979           case 256:
9980             if (gray)
9981               palette_data =
9982                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
9983             else
9984               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9985             break;
9986           default:
9987             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9988                 (_("The video in this file might not play correctly.")),
9989                 ("unsupported palette depth %d", depth));
9990             break;
9991         }
9992       } else {
9993         gint i, j, start, end;
9994
9995         if (len < 94)
9996           goto corrupt_file;
9997
9998         /* read table */
9999         start = QT_UINT32 (stsd_entry_data + offset + 70);
10000         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10001         end = QT_UINT16 (stsd_entry_data + offset + 76);
10002
10003         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10004             start, end, palette_count);
10005
10006         if (end > 255)
10007           end = 255;
10008         if (start > end)
10009           start = end;
10010
10011         if (len < 94 + (end - start) * 8)
10012           goto corrupt_file;
10013
10014         /* palette is always the same size */
10015         palette_data = g_malloc0 (256 * 4);
10016         palette_size = 256 * 4;
10017
10018         for (j = 0, i = start; i <= end; j++, i++) {
10019           guint32 a, r, g, b;
10020
10021           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10022           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10023           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10024           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10025
10026           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10027               (g & 0xff00) | (b >> 8);
10028         }
10029       }
10030
10031       if (entry->caps)
10032         gst_caps_unref (entry->caps);
10033
10034       entry->caps =
10035           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10036           &codec);
10037       if (G_UNLIKELY (!entry->caps)) {
10038         g_free (palette_data);
10039         goto unknown_stream;
10040       }
10041
10042       if (codec) {
10043         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10044             GST_TAG_VIDEO_CODEC, codec, NULL);
10045         g_free (codec);
10046         codec = NULL;
10047       }
10048
10049       if (palette_data) {
10050         GstStructure *s;
10051
10052         if (entry->rgb8_palette)
10053           gst_memory_unref (entry->rgb8_palette);
10054         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10055             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10056
10057         s = gst_caps_get_structure (entry->caps, 0);
10058
10059         /* non-raw video has a palette_data property. raw video has the palette as
10060          * an extra plane that we append to the output buffers before we push
10061          * them*/
10062         if (!gst_structure_has_name (s, "video/x-raw")) {
10063           GstBuffer *palette;
10064
10065           palette = gst_buffer_new ();
10066           gst_buffer_append_memory (palette, entry->rgb8_palette);
10067           entry->rgb8_palette = NULL;
10068
10069           gst_caps_set_simple (entry->caps, "palette_data",
10070               GST_TYPE_BUFFER, palette, NULL);
10071           gst_buffer_unref (palette);
10072         }
10073       } else if (palette_count != 0) {
10074         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10075             (NULL), ("Unsupported palette depth %d", depth));
10076       }
10077
10078       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10079           QT_UINT16 (stsd_entry_data + offset + 32));
10080
10081       esds = NULL;
10082       pasp = NULL;
10083       colr = NULL;
10084       fiel = NULL;
10085       /* pick 'the' stsd child */
10086       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10087       if (!stream->protected) {
10088         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10089           mp4v = NULL;
10090         }
10091       } else {
10092         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10093           mp4v = NULL;
10094         }
10095       }
10096
10097       if (mp4v) {
10098         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10099         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10100         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10101         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10102       }
10103
10104       if (pasp) {
10105         const guint8 *pasp_data = (const guint8 *) pasp->data;
10106         gint len = QT_UINT32 (pasp_data);
10107
10108         if (len == 16) {
10109           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10110           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10111         } else {
10112           CUR_STREAM (stream)->par_w = 0;
10113           CUR_STREAM (stream)->par_h = 0;
10114         }
10115       } else {
10116         CUR_STREAM (stream)->par_w = 0;
10117         CUR_STREAM (stream)->par_h = 0;
10118       }
10119
10120       if (fiel) {
10121         const guint8 *fiel_data = (const guint8 *) fiel->data;
10122         gint len = QT_UINT32 (fiel_data);
10123
10124         if (len == 10) {
10125           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10126           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10127         }
10128       }
10129
10130       if (colr) {
10131         const guint8 *colr_data = (const guint8 *) colr->data;
10132         gint len = QT_UINT32 (colr_data);
10133
10134         if (len == 19 || len == 18) {
10135           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10136
10137           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10138             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10139             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10140             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10141             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10142
10143             switch (primaries) {
10144               case 1:
10145                 CUR_STREAM (stream)->colorimetry.primaries =
10146                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10147                 break;
10148               case 5:
10149                 CUR_STREAM (stream)->colorimetry.primaries =
10150                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10151                 break;
10152               case 6:
10153                 CUR_STREAM (stream)->colorimetry.primaries =
10154                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10155                 break;
10156               case 9:
10157                 CUR_STREAM (stream)->colorimetry.primaries =
10158                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10159                 break;
10160               default:
10161                 break;
10162             }
10163
10164             switch (transfer_function) {
10165               case 1:
10166                 CUR_STREAM (stream)->colorimetry.transfer =
10167                     GST_VIDEO_TRANSFER_BT709;
10168                 break;
10169               case 7:
10170                 CUR_STREAM (stream)->colorimetry.transfer =
10171                     GST_VIDEO_TRANSFER_SMPTE240M;
10172                 break;
10173               default:
10174                 break;
10175             }
10176
10177             switch (matrix) {
10178               case 1:
10179                 CUR_STREAM (stream)->colorimetry.matrix =
10180                     GST_VIDEO_COLOR_MATRIX_BT709;
10181                 break;
10182               case 6:
10183                 CUR_STREAM (stream)->colorimetry.matrix =
10184                     GST_VIDEO_COLOR_MATRIX_BT601;
10185                 break;
10186               case 7:
10187                 CUR_STREAM (stream)->colorimetry.matrix =
10188                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10189                 break;
10190               case 9:
10191                 CUR_STREAM (stream)->colorimetry.matrix =
10192                     GST_VIDEO_COLOR_MATRIX_BT2020;
10193                 break;
10194               default:
10195                 break;
10196             }
10197
10198             CUR_STREAM (stream)->colorimetry.range =
10199                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10200                 GST_VIDEO_COLOR_RANGE_16_235;
10201           } else {
10202             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10203           }
10204         } else {
10205           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10206         }
10207       }
10208
10209       if (esds) {
10210         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10211             stream->stream_tags);
10212       } else {
10213         switch (fourcc) {
10214           case FOURCC_H264:
10215           case FOURCC_avc1:
10216           case FOURCC_avc3:
10217           {
10218             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10219             const guint8 *avc_data = stsd_entry_data + 0x56;
10220
10221             /* find avcC */
10222             while (len >= 0x8) {
10223               gint size;
10224
10225               if (QT_UINT32 (avc_data) <= len)
10226                 size = QT_UINT32 (avc_data) - 0x8;
10227               else
10228                 size = len - 0x8;
10229
10230               if (size < 1)
10231                 /* No real data, so break out */
10232                 break;
10233
10234               switch (QT_FOURCC (avc_data + 0x4)) {
10235                 case FOURCC_avcC:
10236                 {
10237                   /* parse, if found */
10238                   GstBuffer *buf;
10239
10240                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10241
10242                   /* First 4 bytes are the length of the atom, the next 4 bytes
10243                    * are the fourcc, the next 1 byte is the version, and the
10244                    * subsequent bytes are profile_tier_level structure like data. */
10245                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10246                       avc_data + 8 + 1, size - 1);
10247                   buf = gst_buffer_new_and_alloc (size);
10248                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10249                   gst_caps_set_simple (entry->caps,
10250                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10251                   gst_buffer_unref (buf);
10252
10253                   break;
10254                 }
10255                 case FOURCC_strf:
10256                 {
10257                   GstBuffer *buf;
10258
10259                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10260
10261                   /* First 4 bytes are the length of the atom, the next 4 bytes
10262                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10263                    * next 1 byte is the version, and the
10264                    * subsequent bytes are sequence parameter set like data. */
10265
10266                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10267                   if (size > 1) {
10268                     gst_codec_utils_h264_caps_set_level_and_profile
10269                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10270
10271                     buf = gst_buffer_new_and_alloc (size);
10272                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10273                     gst_caps_set_simple (entry->caps,
10274                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10275                     gst_buffer_unref (buf);
10276                   }
10277                   break;
10278                 }
10279                 case FOURCC_btrt:
10280                 {
10281                   guint avg_bitrate, max_bitrate;
10282
10283                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10284                   if (size < 12)
10285                     break;
10286
10287                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10288                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10289
10290                   if (!max_bitrate && !avg_bitrate)
10291                     break;
10292
10293                   /* Some muxers seem to swap the average and maximum bitrates
10294                    * (I'm looking at you, YouTube), so we swap for sanity. */
10295                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10296                     guint temp = avg_bitrate;
10297
10298                     avg_bitrate = max_bitrate;
10299                     max_bitrate = temp;
10300                   }
10301
10302                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10303                     gst_tag_list_add (stream->stream_tags,
10304                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10305                         max_bitrate, NULL);
10306                   }
10307                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10308                     gst_tag_list_add (stream->stream_tags,
10309                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10310                         NULL);
10311                   }
10312
10313                   break;
10314                 }
10315
10316                 default:
10317                   break;
10318               }
10319
10320               len -= size + 8;
10321               avc_data += size + 8;
10322             }
10323
10324             break;
10325           }
10326           case FOURCC_H265:
10327           case FOURCC_hvc1:
10328           case FOURCC_hev1:
10329           {
10330             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10331             const guint8 *hevc_data = stsd_entry_data + 0x56;
10332
10333             /* find hevc */
10334             while (len >= 0x8) {
10335               gint size;
10336
10337               if (QT_UINT32 (hevc_data) <= len)
10338                 size = QT_UINT32 (hevc_data) - 0x8;
10339               else
10340                 size = len - 0x8;
10341
10342               if (size < 1)
10343                 /* No real data, so break out */
10344                 break;
10345
10346               switch (QT_FOURCC (hevc_data + 0x4)) {
10347                 case FOURCC_hvcC:
10348                 {
10349                   /* parse, if found */
10350                   GstBuffer *buf;
10351
10352                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10353
10354                   /* First 4 bytes are the length of the atom, the next 4 bytes
10355                    * are the fourcc, the next 1 byte is the version, and the
10356                    * subsequent bytes are sequence parameter set like data. */
10357                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10358                       (entry->caps, hevc_data + 8 + 1, size - 1);
10359
10360                   buf = gst_buffer_new_and_alloc (size);
10361                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10362                   gst_caps_set_simple (entry->caps,
10363                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10364                   gst_buffer_unref (buf);
10365                   break;
10366                 }
10367                 default:
10368                   break;
10369               }
10370               len -= size + 8;
10371               hevc_data += size + 8;
10372             }
10373             break;
10374           }
10375           case FOURCC_mp4v:
10376           case FOURCC_MP4V:
10377           case FOURCC_fmp4:
10378           case FOURCC_FMP4:
10379           case FOURCC_xvid:
10380           case FOURCC_XVID:
10381           {
10382             GNode *glbl;
10383
10384             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10385                 GST_FOURCC_ARGS (fourcc));
10386
10387             /* codec data might be in glbl extension atom */
10388             glbl = mp4v ?
10389                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10390             if (glbl) {
10391               guint8 *data;
10392               GstBuffer *buf;
10393               gint len;
10394
10395               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10396               data = glbl->data;
10397               len = QT_UINT32 (data);
10398               if (len > 0x8) {
10399                 len -= 0x8;
10400                 buf = gst_buffer_new_and_alloc (len);
10401                 gst_buffer_fill (buf, 0, data + 8, len);
10402                 gst_caps_set_simple (entry->caps,
10403                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10404                 gst_buffer_unref (buf);
10405               }
10406             }
10407             break;
10408           }
10409           case FOURCC_mjp2:
10410           {
10411             /* see annex I of the jpeg2000 spec */
10412             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10413             const guint8 *data;
10414             const gchar *colorspace = NULL;
10415             gint ncomp = 0;
10416             guint32 ncomp_map = 0;
10417             gint32 *comp_map = NULL;
10418             guint32 nchan_def = 0;
10419             gint32 *chan_def = NULL;
10420
10421             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10422             /* some required atoms */
10423             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10424             if (!mjp2)
10425               break;
10426             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10427             if (!jp2h)
10428               break;
10429
10430             /* number of components; redundant with info in codestream, but useful
10431                to a muxer */
10432             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10433             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10434               break;
10435             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10436
10437             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10438             if (!colr)
10439               break;
10440             GST_DEBUG_OBJECT (qtdemux, "found colr");
10441             /* extract colour space info */
10442             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10443               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10444                 case 16:
10445                   colorspace = "sRGB";
10446                   break;
10447                 case 17:
10448                   colorspace = "GRAY";
10449                   break;
10450                 case 18:
10451                   colorspace = "sYUV";
10452                   break;
10453                 default:
10454                   colorspace = NULL;
10455                   break;
10456               }
10457             }
10458             if (!colorspace)
10459               /* colr is required, and only values 16, 17, and 18 are specified,
10460                  so error if we have no colorspace */
10461               break;
10462
10463             /* extract component mapping */
10464             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10465             if (cmap) {
10466               guint32 cmap_len = 0;
10467               int i;
10468               cmap_len = QT_UINT32 (cmap->data);
10469               if (cmap_len >= 8) {
10470                 /* normal box, subtract off header */
10471                 cmap_len -= 8;
10472                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10473                 if (cmap_len % 4 == 0) {
10474                   ncomp_map = (cmap_len / 4);
10475                   comp_map = g_new0 (gint32, ncomp_map);
10476                   for (i = 0; i < ncomp_map; i++) {
10477                     guint16 cmp;
10478                     guint8 mtyp, pcol;
10479                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10480                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10481                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10482                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10483                   }
10484                 }
10485               }
10486             }
10487             /* extract channel definitions */
10488             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10489             if (cdef) {
10490               guint32 cdef_len = 0;
10491               int i;
10492               cdef_len = QT_UINT32 (cdef->data);
10493               if (cdef_len >= 10) {
10494                 /* normal box, subtract off header and len */
10495                 cdef_len -= 10;
10496                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10497                 if (cdef_len % 6 == 0) {
10498                   nchan_def = (cdef_len / 6);
10499                   chan_def = g_new0 (gint32, nchan_def);
10500                   for (i = 0; i < nchan_def; i++)
10501                     chan_def[i] = -1;
10502                   for (i = 0; i < nchan_def; i++) {
10503                     guint16 cn, typ, asoc;
10504                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10505                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10506                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10507                     if (cn < nchan_def) {
10508                       switch (typ) {
10509                         case 0:
10510                           chan_def[cn] = asoc;
10511                           break;
10512                         case 1:
10513                           chan_def[cn] = 0;     /* alpha */
10514                           break;
10515                         default:
10516                           chan_def[cn] = -typ;
10517                       }
10518                     }
10519                   }
10520                 }
10521               }
10522             }
10523
10524             gst_caps_set_simple (entry->caps,
10525                 "num-components", G_TYPE_INT, ncomp, NULL);
10526             gst_caps_set_simple (entry->caps,
10527                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10528
10529             if (comp_map) {
10530               GValue arr = { 0, };
10531               GValue elt = { 0, };
10532               int i;
10533               g_value_init (&arr, GST_TYPE_ARRAY);
10534               g_value_init (&elt, G_TYPE_INT);
10535               for (i = 0; i < ncomp_map; i++) {
10536                 g_value_set_int (&elt, comp_map[i]);
10537                 gst_value_array_append_value (&arr, &elt);
10538               }
10539               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10540                   "component-map", &arr);
10541               g_value_unset (&elt);
10542               g_value_unset (&arr);
10543               g_free (comp_map);
10544             }
10545
10546             if (chan_def) {
10547               GValue arr = { 0, };
10548               GValue elt = { 0, };
10549               int i;
10550               g_value_init (&arr, GST_TYPE_ARRAY);
10551               g_value_init (&elt, G_TYPE_INT);
10552               for (i = 0; i < nchan_def; i++) {
10553                 g_value_set_int (&elt, chan_def[i]);
10554                 gst_value_array_append_value (&arr, &elt);
10555               }
10556               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10557                   "channel-definitions", &arr);
10558               g_value_unset (&elt);
10559               g_value_unset (&arr);
10560               g_free (chan_def);
10561             }
10562
10563             /* some optional atoms */
10564             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10565             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10566
10567             /* indicate possible fields in caps */
10568             if (field) {
10569               data = (guint8 *) field->data + 8;
10570               if (*data != 1)
10571                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10572                     (gint) * data, NULL);
10573             }
10574             /* add codec_data if provided */
10575             if (prefix) {
10576               GstBuffer *buf;
10577               gint len;
10578
10579               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10580               data = prefix->data;
10581               len = QT_UINT32 (data);
10582               if (len > 0x8) {
10583                 len -= 0x8;
10584                 buf = gst_buffer_new_and_alloc (len);
10585                 gst_buffer_fill (buf, 0, data + 8, len);
10586                 gst_caps_set_simple (entry->caps,
10587                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10588                 gst_buffer_unref (buf);
10589               }
10590             }
10591             break;
10592           }
10593           case FOURCC_SVQ3:
10594           case FOURCC_VP31:
10595           {
10596             GstBuffer *buf;
10597             GstBuffer *seqh = NULL;
10598             const guint8 *gamma_data = NULL;
10599             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10600
10601             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10602                 &seqh);
10603             if (gamma_data) {
10604               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10605                   QT_FP32 (gamma_data), NULL);
10606             }
10607             if (seqh) {
10608               /* sorry for the bad name, but we don't know what this is, other
10609                * than its own fourcc */
10610               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10611                   NULL);
10612               gst_buffer_unref (seqh);
10613             }
10614
10615             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10616             buf = gst_buffer_new_and_alloc (len);
10617             gst_buffer_fill (buf, 0, stsd_data, len);
10618             gst_caps_set_simple (entry->caps,
10619                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10620             gst_buffer_unref (buf);
10621             break;
10622           }
10623           case FOURCC_jpeg:
10624           {
10625             /* https://developer.apple.com/standards/qtff-2001.pdf,
10626              * page 92, "Video Sample Description", under table 3.1 */
10627             GstByteReader br;
10628
10629             const gint compressor_offset =
10630                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10631             const gint min_size = compressor_offset + 32 + 2 + 2;
10632             GNode *jpeg;
10633             guint32 len;
10634             guint16 color_table_id = 0;
10635             gboolean ok;
10636
10637             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10638
10639             /* recover information on interlaced/progressive */
10640             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10641             if (!jpeg)
10642               break;
10643
10644             len = QT_UINT32 (jpeg->data);
10645             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10646                 min_size);
10647             if (len >= min_size) {
10648               gst_byte_reader_init (&br, jpeg->data, len);
10649
10650               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10651               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10652               if (color_table_id != 0) {
10653                 /* the spec says there can be concatenated chunks in the data, and we want
10654                  * to find one called field. Walk through them. */
10655                 gint offset = min_size;
10656                 while (offset + 8 < len) {
10657                   guint32 size = 0, tag;
10658                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10659                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10660                   if (!ok || size < 8) {
10661                     GST_WARNING_OBJECT (qtdemux,
10662                         "Failed to walk optional chunk list");
10663                     break;
10664                   }
10665                   GST_DEBUG_OBJECT (qtdemux,
10666                       "Found optional %4.4s chunk, size %u",
10667                       (const char *) &tag, size);
10668                   if (tag == FOURCC_fiel) {
10669                     guint8 n_fields = 0, ordering = 0;
10670                     gst_byte_reader_get_uint8 (&br, &n_fields);
10671                     gst_byte_reader_get_uint8 (&br, &ordering);
10672                     if (n_fields == 1 || n_fields == 2) {
10673                       GST_DEBUG_OBJECT (qtdemux,
10674                           "Found fiel tag with %u fields, ordering %u",
10675                           n_fields, ordering);
10676                       if (n_fields == 2)
10677                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10678                             "interlace-mode", G_TYPE_STRING, "interleaved",
10679                             NULL);
10680                     } else {
10681                       GST_WARNING_OBJECT (qtdemux,
10682                           "Found fiel tag with invalid fields (%u)", n_fields);
10683                     }
10684                   }
10685                   offset += size;
10686                 }
10687               } else {
10688                 GST_DEBUG_OBJECT (qtdemux,
10689                     "Color table ID is 0, not trying to get interlacedness");
10690               }
10691             } else {
10692               GST_WARNING_OBJECT (qtdemux,
10693                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10694             }
10695
10696             break;
10697           }
10698           case FOURCC_rle_:
10699           case FOURCC_WRLE:
10700           {
10701             gst_caps_set_simple (entry->caps,
10702                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
10703                 NULL);
10704             break;
10705           }
10706           case FOURCC_XiTh:
10707           {
10708             GNode *xith, *xdxt;
10709
10710             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10711             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10712             if (!xith)
10713               break;
10714
10715             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10716             if (!xdxt)
10717               break;
10718
10719             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10720             /* collect the headers and store them in a stream list so that we can
10721              * send them out first */
10722             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10723             break;
10724           }
10725           case FOURCC_ovc1:
10726           {
10727             GNode *ovc1;
10728             guint8 *ovc1_data;
10729             guint ovc1_len;
10730             GstBuffer *buf;
10731
10732             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10733             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10734             if (!ovc1)
10735               break;
10736             ovc1_data = ovc1->data;
10737             ovc1_len = QT_UINT32 (ovc1_data);
10738             if (ovc1_len <= 198) {
10739               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10740               break;
10741             }
10742             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10743             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10744             gst_caps_set_simple (entry->caps,
10745                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10746             gst_buffer_unref (buf);
10747             break;
10748           }
10749           case FOURCC_vc_1:
10750           {
10751             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10752             const guint8 *vc1_data = stsd_entry_data + 0x56;
10753
10754             /* find dvc1 */
10755             while (len >= 8) {
10756               gint size;
10757
10758               if (QT_UINT32 (vc1_data) <= len)
10759                 size = QT_UINT32 (vc1_data) - 8;
10760               else
10761                 size = len - 8;
10762
10763               if (size < 1)
10764                 /* No real data, so break out */
10765                 break;
10766
10767               switch (QT_FOURCC (vc1_data + 0x4)) {
10768                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10769                 {
10770                   GstBuffer *buf;
10771
10772                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10773                   buf = gst_buffer_new_and_alloc (size);
10774                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10775                   gst_caps_set_simple (entry->caps,
10776                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10777                   gst_buffer_unref (buf);
10778                   break;
10779                 }
10780                 default:
10781                   break;
10782               }
10783               len -= size + 8;
10784               vc1_data += size + 8;
10785             }
10786             break;
10787           }
10788           default:
10789             break;
10790         }
10791       }
10792
10793       GST_INFO_OBJECT (qtdemux,
10794           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10795           GST_FOURCC_ARGS (fourcc), entry->caps);
10796
10797     } else if (stream->subtype == FOURCC_soun) {
10798       GNode *wave;
10799       int version, samplesize;
10800       guint16 compression_id;
10801       gboolean amrwb = FALSE;
10802
10803       offset = 16;
10804       /* sample description entry (16) + sound sample description v0 (20) */
10805       if (len < 36)
10806         goto corrupt_file;
10807
10808       version = QT_UINT32 (stsd_entry_data + offset);
10809       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10810       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10811       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10812       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10813
10814       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10815       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10816           QT_UINT32 (stsd_entry_data + offset + 4));
10817       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10818       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10819       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10820       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10821           QT_UINT16 (stsd_entry_data + offset + 14));
10822       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10823
10824       if (compression_id == 0xfffe)
10825         entry->sampled = TRUE;
10826
10827       /* first assume uncompressed audio */
10828       entry->bytes_per_sample = samplesize / 8;
10829       entry->samples_per_frame = entry->n_channels;
10830       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10831       entry->samples_per_packet = entry->samples_per_frame;
10832       entry->bytes_per_packet = entry->bytes_per_sample;
10833
10834       offset = 36;
10835       switch (fourcc) {
10836           /* Yes, these have to be hard-coded */
10837         case FOURCC_MAC6:
10838         {
10839           entry->samples_per_packet = 6;
10840           entry->bytes_per_packet = 1;
10841           entry->bytes_per_frame = 1 * entry->n_channels;
10842           entry->bytes_per_sample = 1;
10843           entry->samples_per_frame = 6 * entry->n_channels;
10844           break;
10845         }
10846         case FOURCC_MAC3:
10847         {
10848           entry->samples_per_packet = 3;
10849           entry->bytes_per_packet = 1;
10850           entry->bytes_per_frame = 1 * entry->n_channels;
10851           entry->bytes_per_sample = 1;
10852           entry->samples_per_frame = 3 * entry->n_channels;
10853           break;
10854         }
10855         case FOURCC_ima4:
10856         {
10857           entry->samples_per_packet = 64;
10858           entry->bytes_per_packet = 34;
10859           entry->bytes_per_frame = 34 * entry->n_channels;
10860           entry->bytes_per_sample = 2;
10861           entry->samples_per_frame = 64 * entry->n_channels;
10862           break;
10863         }
10864         case FOURCC_ulaw:
10865         case FOURCC_alaw:
10866         {
10867           entry->samples_per_packet = 1;
10868           entry->bytes_per_packet = 1;
10869           entry->bytes_per_frame = 1 * entry->n_channels;
10870           entry->bytes_per_sample = 1;
10871           entry->samples_per_frame = 1 * entry->n_channels;
10872           break;
10873         }
10874         case FOURCC_agsm:
10875         {
10876           entry->samples_per_packet = 160;
10877           entry->bytes_per_packet = 33;
10878           entry->bytes_per_frame = 33 * entry->n_channels;
10879           entry->bytes_per_sample = 2;
10880           entry->samples_per_frame = 160 * entry->n_channels;
10881           break;
10882         }
10883         default:
10884           break;
10885       }
10886
10887       if (version == 0x00010000) {
10888         /* sample description entry (16) + sound sample description v1 (20+16) */
10889         if (len < 52)
10890           goto corrupt_file;
10891
10892         switch (fourcc) {
10893           case FOURCC_twos:
10894           case FOURCC_sowt:
10895           case FOURCC_raw_:
10896           case FOURCC_lpcm:
10897             break;
10898           default:
10899           {
10900             /* only parse extra decoding config for non-pcm audio */
10901             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10902             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10903             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10904             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10905
10906             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10907                 entry->samples_per_packet);
10908             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10909                 entry->bytes_per_packet);
10910             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10911                 entry->bytes_per_frame);
10912             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10913                 entry->bytes_per_sample);
10914
10915             if (!entry->sampled && entry->bytes_per_packet) {
10916               entry->samples_per_frame = (entry->bytes_per_frame /
10917                   entry->bytes_per_packet) * entry->samples_per_packet;
10918               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10919                   entry->samples_per_frame);
10920             }
10921             break;
10922           }
10923         }
10924       } else if (version == 0x00020000) {
10925         union
10926         {
10927           gdouble fp;
10928           guint64 val;
10929         } qtfp;
10930
10931         /* sample description entry (16) + sound sample description v2 (56) */
10932         if (len < 72)
10933           goto corrupt_file;
10934
10935         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
10936         entry->rate = qtfp.fp;
10937         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
10938
10939         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10940         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
10941         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
10942         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10943             QT_UINT32 (stsd_entry_data + offset + 20));
10944         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10945             QT_UINT32 (stsd_entry_data + offset + 24));
10946         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10947             QT_UINT32 (stsd_entry_data + offset + 28));
10948         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10949             QT_UINT32 (stsd_entry_data + offset + 32));
10950       } else if (version != 0x00000) {
10951         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
10952             version);
10953       }
10954
10955       if (entry->caps)
10956         gst_caps_unref (entry->caps);
10957
10958       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
10959           stsd_entry_data + 32, len - 16, &codec);
10960
10961       switch (fourcc) {
10962         case FOURCC_in24:
10963         {
10964           GNode *enda;
10965           GNode *in24;
10966
10967           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10968
10969           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10970           if (!enda) {
10971             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10972             if (wave)
10973               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10974           }
10975           if (enda) {
10976             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10977             gst_caps_set_simple (entry->caps,
10978                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
10979                 NULL);
10980           }
10981           break;
10982         }
10983         case FOURCC_owma:
10984         {
10985           const guint8 *owma_data;
10986           const gchar *codec_name = NULL;
10987           guint owma_len;
10988           GstBuffer *buf;
10989           gint version = 1;
10990           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10991           /* FIXME this should also be gst_riff_strf_auds,
10992            * but the latter one is actually missing bits-per-sample :( */
10993           typedef struct
10994           {
10995             gint16 wFormatTag;
10996             gint16 nChannels;
10997             gint32 nSamplesPerSec;
10998             gint32 nAvgBytesPerSec;
10999             gint16 nBlockAlign;
11000             gint16 wBitsPerSample;
11001             gint16 cbSize;
11002           } WAVEFORMATEX;
11003           WAVEFORMATEX *wfex;
11004
11005           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11006           owma_data = stsd_entry_data;
11007           owma_len = QT_UINT32 (owma_data);
11008           if (owma_len <= 54) {
11009             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11010             break;
11011           }
11012           wfex = (WAVEFORMATEX *) (owma_data + 36);
11013           buf = gst_buffer_new_and_alloc (owma_len - 54);
11014           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11015           if (wfex->wFormatTag == 0x0161) {
11016             codec_name = "Windows Media Audio";
11017             version = 2;
11018           } else if (wfex->wFormatTag == 0x0162) {
11019             codec_name = "Windows Media Audio 9 Pro";
11020             version = 3;
11021           } else if (wfex->wFormatTag == 0x0163) {
11022             codec_name = "Windows Media Audio 9 Lossless";
11023             /* is that correct? gstffmpegcodecmap.c is missing it, but
11024              * fluendo codec seems to support it */
11025             version = 4;
11026           }
11027
11028           gst_caps_set_simple (entry->caps,
11029               "codec_data", GST_TYPE_BUFFER, buf,
11030               "wmaversion", G_TYPE_INT, version,
11031               "block_align", G_TYPE_INT,
11032               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11033               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11034               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11035               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11036           gst_buffer_unref (buf);
11037
11038           if (codec_name) {
11039             g_free (codec);
11040             codec = g_strdup (codec_name);
11041           }
11042           break;
11043         }
11044         case FOURCC_wma_:
11045         {
11046           gint len = QT_UINT32 (stsd_entry_data) - offset;
11047           const guint8 *wfex_data = stsd_entry_data + offset;
11048           const gchar *codec_name = NULL;
11049           gint version = 1;
11050           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11051           /* FIXME this should also be gst_riff_strf_auds,
11052            * but the latter one is actually missing bits-per-sample :( */
11053           typedef struct
11054           {
11055             gint16 wFormatTag;
11056             gint16 nChannels;
11057             gint32 nSamplesPerSec;
11058             gint32 nAvgBytesPerSec;
11059             gint16 nBlockAlign;
11060             gint16 wBitsPerSample;
11061             gint16 cbSize;
11062           } WAVEFORMATEX;
11063           WAVEFORMATEX wfex;
11064
11065           /* FIXME: unify with similar wavformatex parsing code above */
11066           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11067
11068           /* find wfex */
11069           while (len >= 8) {
11070             gint size;
11071
11072             if (QT_UINT32 (wfex_data) <= len)
11073               size = QT_UINT32 (wfex_data) - 8;
11074             else
11075               size = len - 8;
11076
11077             if (size < 1)
11078               /* No real data, so break out */
11079               break;
11080
11081             switch (QT_FOURCC (wfex_data + 4)) {
11082               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11083               {
11084                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11085
11086                 if (size < 8 + 18)
11087                   break;
11088
11089                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11090                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11091                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11092                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11093                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11094                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11095                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11096
11097                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11098                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11099                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11100                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11101                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11102                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11103
11104                 if (wfex.wFormatTag == 0x0161) {
11105                   codec_name = "Windows Media Audio";
11106                   version = 2;
11107                 } else if (wfex.wFormatTag == 0x0162) {
11108                   codec_name = "Windows Media Audio 9 Pro";
11109                   version = 3;
11110                 } else if (wfex.wFormatTag == 0x0163) {
11111                   codec_name = "Windows Media Audio 9 Lossless";
11112                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11113                    * fluendo codec seems to support it */
11114                   version = 4;
11115                 }
11116
11117                 gst_caps_set_simple (entry->caps,
11118                     "wmaversion", G_TYPE_INT, version,
11119                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11120                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11121                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11122                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11123
11124                 if (size > wfex.cbSize) {
11125                   GstBuffer *buf;
11126
11127                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11128                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11129                       size - wfex.cbSize);
11130                   gst_caps_set_simple (entry->caps,
11131                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11132                   gst_buffer_unref (buf);
11133                 } else {
11134                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11135                 }
11136
11137                 if (codec_name) {
11138                   g_free (codec);
11139                   codec = g_strdup (codec_name);
11140                 }
11141                 break;
11142               }
11143               default:
11144                 break;
11145             }
11146             len -= size + 8;
11147             wfex_data += size + 8;
11148           }
11149           break;
11150         }
11151         case FOURCC_opus:
11152         {
11153           const guint8 *opus_data;
11154           guint8 *channel_mapping = NULL;
11155           guint32 rate;
11156           guint8 channels;
11157           guint8 channel_mapping_family;
11158           guint8 stream_count;
11159           guint8 coupled_count;
11160           guint8 i;
11161
11162           opus_data = stsd_entry_data;
11163
11164           channels = GST_READ_UINT8 (opus_data + 45);
11165           rate = GST_READ_UINT32_LE (opus_data + 48);
11166           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11167           stream_count = GST_READ_UINT8 (opus_data + 55);
11168           coupled_count = GST_READ_UINT8 (opus_data + 56);
11169
11170           if (channels > 0) {
11171             channel_mapping = g_malloc (channels * sizeof (guint8));
11172             for (i = 0; i < channels; i++)
11173               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11174           }
11175
11176           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11177               channel_mapping_family, stream_count, coupled_count,
11178               channel_mapping);
11179           break;
11180         }
11181         default:
11182           break;
11183       }
11184
11185       if (codec) {
11186         GstStructure *s;
11187         gint bitrate = 0;
11188
11189         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11190             GST_TAG_AUDIO_CODEC, codec, NULL);
11191         g_free (codec);
11192         codec = NULL;
11193
11194         /* some bitrate info may have ended up in caps */
11195         s = gst_caps_get_structure (entry->caps, 0);
11196         gst_structure_get_int (s, "bitrate", &bitrate);
11197         if (bitrate > 0)
11198           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11199               GST_TAG_BITRATE, bitrate, NULL);
11200       }
11201
11202       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11203       if (!stream->protected) {
11204       } else {
11205         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11206           mp4v = NULL;
11207         }
11208       }
11209       if (stream->protected && fourcc == FOURCC_mp4a) {
11210         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11211           mp4a = NULL;
11212         }
11213       } else {
11214         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11215           mp4a = NULL;
11216         }
11217       }
11218
11219       wave = NULL;
11220       esds = NULL;
11221       if (mp4a) {
11222         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11223         if (wave)
11224           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11225         if (!esds)
11226           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11227       }
11228
11229
11230       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11231          16 bits is a byte-swapped wave-style codec identifier,
11232          and we can find a WAVE header internally to a 'wave' atom here.
11233          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11234          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11235          is big-endian).
11236        */
11237       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11238         if (len < offset + 20) {
11239           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11240         } else {
11241           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11242           const guint8 *data = stsd_entry_data + offset + 16;
11243           GNode *wavenode;
11244           GNode *waveheadernode;
11245
11246           wavenode = g_node_new ((guint8 *) data);
11247           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11248             const guint8 *waveheader;
11249             guint32 headerlen;
11250
11251             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11252             if (waveheadernode) {
11253               waveheader = (const guint8 *) waveheadernode->data;
11254               headerlen = QT_UINT32 (waveheader);
11255
11256               if (headerlen > 8) {
11257                 gst_riff_strf_auds *header = NULL;
11258                 GstBuffer *headerbuf;
11259                 GstBuffer *extra;
11260
11261                 waveheader += 8;
11262                 headerlen -= 8;
11263
11264                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11265                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11266
11267                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11268                         headerbuf, &header, &extra)) {
11269                   gst_caps_unref (entry->caps);
11270                   /* FIXME: Need to do something with the channel reorder map */
11271                   entry->caps =
11272                       gst_riff_create_audio_caps (header->format, NULL, header,
11273                       extra, NULL, NULL, NULL);
11274
11275                   if (extra)
11276                     gst_buffer_unref (extra);
11277                   g_free (header);
11278                 }
11279               }
11280             } else
11281               GST_DEBUG ("Didn't find waveheadernode for this codec");
11282           }
11283           g_node_destroy (wavenode);
11284         }
11285       } else if (esds) {
11286         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11287             stream->stream_tags);
11288       } else {
11289         switch (fourcc) {
11290 #if 0
11291             /* FIXME: what is in the chunk? */
11292           case FOURCC_QDMC:
11293           {
11294             gint len = QT_UINT32 (stsd_data);
11295
11296             /* seems to be always = 116 = 0x74 */
11297             break;
11298           }
11299 #endif
11300           case FOURCC_QDM2:
11301           {
11302             gint len = QT_UINT32 (stsd_entry_data);
11303
11304             if (len > 0x3C) {
11305               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11306
11307               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11308               gst_caps_set_simple (entry->caps,
11309                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11310               gst_buffer_unref (buf);
11311             }
11312             gst_caps_set_simple (entry->caps,
11313                 "samplesize", G_TYPE_INT, samplesize, NULL);
11314             break;
11315           }
11316           case FOURCC_alac:
11317           {
11318             GNode *alac, *wave = NULL;
11319
11320             /* apparently, m4a has this atom appended directly in the stsd entry,
11321              * while mov has it in a wave atom */
11322             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11323             if (alac) {
11324               /* alac now refers to stsd entry atom */
11325               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11326               if (wave)
11327                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11328               else
11329                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11330             }
11331             if (alac) {
11332               const guint8 *alac_data = alac->data;
11333               gint len = QT_UINT32 (alac->data);
11334               GstBuffer *buf;
11335
11336               if (len < 36) {
11337                 GST_DEBUG_OBJECT (qtdemux,
11338                     "discarding alac atom with unexpected len %d", len);
11339               } else {
11340                 /* codec-data contains alac atom size and prefix,
11341                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11342                 buf = gst_buffer_new_and_alloc (len);
11343                 gst_buffer_fill (buf, 0, alac->data, len);
11344                 gst_caps_set_simple (entry->caps,
11345                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11346                 gst_buffer_unref (buf);
11347
11348                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11349                 entry->n_channels = QT_UINT8 (alac_data + 21);
11350                 entry->rate = QT_UINT32 (alac_data + 32);
11351               }
11352             }
11353             gst_caps_set_simple (entry->caps,
11354                 "samplesize", G_TYPE_INT, samplesize, NULL);
11355             break;
11356           }
11357           case FOURCC_fLaC:
11358           {
11359             /* The codingname of the sample entry is 'fLaC' */
11360             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11361
11362             if (flac) {
11363               /* The 'dfLa' box is added to the sample entry to convey
11364                  initializing information for the decoder. */
11365               const GNode *dfla =
11366                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11367
11368               if (dfla) {
11369                 const guint32 len = QT_UINT32 (dfla->data);
11370
11371                 /* Must contain at least dfLa box header (12),
11372                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11373                 if (len < 50) {
11374                   GST_DEBUG_OBJECT (qtdemux,
11375                       "discarding dfla atom with unexpected len %d", len);
11376                 } else {
11377                   /* skip dfLa header to get the METADATA_BLOCKs */
11378                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11379                   const guint32 metadata_blocks_len = len - 12;
11380
11381                   gchar *stream_marker = g_strdup ("fLaC");
11382                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11383                       strlen (stream_marker));
11384
11385                   guint32 index = 0;
11386                   guint32 remainder = 0;
11387                   guint32 block_size = 0;
11388                   gboolean is_last = FALSE;
11389
11390                   GValue array = G_VALUE_INIT;
11391                   GValue value = G_VALUE_INIT;
11392
11393                   g_value_init (&array, GST_TYPE_ARRAY);
11394                   g_value_init (&value, GST_TYPE_BUFFER);
11395
11396                   gst_value_set_buffer (&value, block);
11397                   gst_value_array_append_value (&array, &value);
11398                   g_value_reset (&value);
11399
11400                   gst_buffer_unref (block);
11401
11402                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11403                    * of data, and we haven't already finished parsing */
11404                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11405                     remainder = metadata_blocks_len - index;
11406
11407                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11408                     block_size = 4 +
11409                         (metadata_blocks[index + 1] << 16) +
11410                         (metadata_blocks[index + 2] << 8) +
11411                         metadata_blocks[index + 3];
11412
11413                     /* be careful not to read off end of box */
11414                     if (block_size > remainder) {
11415                       break;
11416                     }
11417
11418                     is_last = metadata_blocks[index] >> 7;
11419
11420                     block = gst_buffer_new_and_alloc (block_size);
11421
11422                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11423                         block_size);
11424
11425                     gst_value_set_buffer (&value, block);
11426                     gst_value_array_append_value (&array, &value);
11427                     g_value_reset (&value);
11428
11429                     gst_buffer_unref (block);
11430
11431                     index += block_size;
11432                   }
11433
11434                   /* only append the metadata if we successfully read all of it */
11435                   if (is_last) {
11436                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11437                             (stream)->caps, 0), "streamheader", &array);
11438                   } else {
11439                     GST_WARNING_OBJECT (qtdemux,
11440                         "discarding all METADATA_BLOCKs due to invalid "
11441                         "block_size %d at idx %d, rem %d", block_size, index,
11442                         remainder);
11443                   }
11444
11445                   g_value_unset (&value);
11446                   g_value_unset (&array);
11447
11448                   /* The sample rate obtained from the stsd may not be accurate
11449                    * since it cannot represent rates greater than 65535Hz, so
11450                    * override that value with the sample rate from the
11451                    * METADATA_BLOCK_STREAMINFO block */
11452                   CUR_STREAM (stream)->rate =
11453                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11454                 }
11455               }
11456             }
11457             break;
11458           }
11459           case FOURCC_sawb:
11460             /* Fallthrough! */
11461             amrwb = TRUE;
11462           case FOURCC_samr:
11463           {
11464             gint len = QT_UINT32 (stsd_entry_data);
11465
11466             if (len > 0x24) {
11467               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11468               guint bitrate;
11469
11470               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11471
11472               /* If we have enough data, let's try to get the 'damr' atom. See
11473                * the 3GPP container spec (26.244) for more details. */
11474               if ((len - 0x34) > 8 &&
11475                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11476                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11477                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11478               }
11479
11480               gst_caps_set_simple (entry->caps,
11481                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11482               gst_buffer_unref (buf);
11483             }
11484             break;
11485           }
11486           case FOURCC_mp4a:
11487           {
11488             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11489             gint len = QT_UINT32 (stsd_entry_data);
11490
11491             if (len >= 34) {
11492               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11493
11494               if (sound_version == 1) {
11495                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11496                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11497                 guint8 codec_data[2];
11498                 GstBuffer *buf;
11499                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11500
11501                 gint sample_rate_index =
11502                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11503
11504                 /* build AAC codec data */
11505                 codec_data[0] = profile << 3;
11506                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11507                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11508                 codec_data[1] |= (channels & 0xF) << 3;
11509
11510                 buf = gst_buffer_new_and_alloc (2);
11511                 gst_buffer_fill (buf, 0, codec_data, 2);
11512                 gst_caps_set_simple (entry->caps,
11513                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11514                 gst_buffer_unref (buf);
11515               }
11516             }
11517             break;
11518           }
11519           case FOURCC_lpcm:
11520             /* Fully handled elsewhere */
11521             break;
11522           default:
11523             GST_INFO_OBJECT (qtdemux,
11524                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11525             break;
11526         }
11527       }
11528       GST_INFO_OBJECT (qtdemux,
11529           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11530           GST_FOURCC_ARGS (fourcc), entry->caps);
11531
11532     } else if (stream->subtype == FOURCC_strm) {
11533       if (fourcc == FOURCC_rtsp) {
11534         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11535       } else {
11536         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11537             GST_FOURCC_ARGS (fourcc));
11538         goto unknown_stream;
11539       }
11540       entry->sampled = TRUE;
11541     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11542         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11543
11544       entry->sampled = TRUE;
11545       entry->sparse = TRUE;
11546
11547       entry->caps =
11548           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11549           &codec);
11550       if (codec) {
11551         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11552             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11553         g_free (codec);
11554         codec = NULL;
11555       }
11556
11557       /* hunt for sort-of codec data */
11558       switch (fourcc) {
11559         case FOURCC_mp4s:
11560         {
11561           GNode *mp4s = NULL;
11562           GNode *esds = NULL;
11563
11564           /* look for palette in a stsd->mp4s->esds sub-atom */
11565           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11566           if (mp4s)
11567             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11568           if (esds == NULL) {
11569             /* Invalid STSD */
11570             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11571             break;
11572           }
11573
11574           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11575               stream->stream_tags);
11576           break;
11577         }
11578         default:
11579           GST_INFO_OBJECT (qtdemux,
11580               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11581           break;
11582       }
11583       GST_INFO_OBJECT (qtdemux,
11584           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11585           GST_FOURCC_ARGS (fourcc), entry->caps);
11586     } else {
11587       /* everything in 1 sample */
11588       entry->sampled = TRUE;
11589
11590       entry->caps =
11591           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11592           &codec);
11593
11594       if (entry->caps == NULL)
11595         goto unknown_stream;
11596
11597       if (codec) {
11598         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11599             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11600         g_free (codec);
11601         codec = NULL;
11602       }
11603     }
11604
11605     /* promote to sampled format */
11606     if (entry->fourcc == FOURCC_samr) {
11607       /* force mono 8000 Hz for AMR */
11608       entry->sampled = TRUE;
11609       entry->n_channels = 1;
11610       entry->rate = 8000;
11611     } else if (entry->fourcc == FOURCC_sawb) {
11612       /* force mono 16000 Hz for AMR-WB */
11613       entry->sampled = TRUE;
11614       entry->n_channels = 1;
11615       entry->rate = 16000;
11616     } else if (entry->fourcc == FOURCC_mp4a) {
11617       entry->sampled = TRUE;
11618     }
11619
11620
11621     stsd_entry_data += len;
11622     remaining_stsd_len -= len;
11623
11624   }
11625
11626   /* collect sample information */
11627   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11628     goto samples_failed;
11629
11630   if (qtdemux->fragmented) {
11631     guint64 offset;
11632
11633     /* need all moov samples as basis; probably not many if any at all */
11634     /* prevent moof parsing taking of at this time */
11635     offset = qtdemux->moof_offset;
11636     qtdemux->moof_offset = 0;
11637     if (stream->n_samples &&
11638         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11639       qtdemux->moof_offset = offset;
11640       goto samples_failed;
11641     }
11642     qtdemux->moof_offset = 0;
11643     /* movie duration more reliable in this case (e.g. mehd) */
11644     if (qtdemux->segment.duration &&
11645         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11646       stream->duration =
11647           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11648   }
11649
11650   /* configure segments */
11651   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11652     goto segments_failed;
11653
11654   /* add some language tag, if useful */
11655   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11656       strcmp (stream->lang_id, "und")) {
11657     const gchar *lang_code;
11658
11659     /* convert ISO 639-2 code to ISO 639-1 */
11660     lang_code = gst_tag_get_language_code (stream->lang_id);
11661     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11662         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11663   }
11664
11665   /* Check for UDTA tags */
11666   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11667     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11668   }
11669
11670   /* now we are ready to add the stream */
11671   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11672     goto too_many_streams;
11673
11674   if (!qtdemux->got_moov) {
11675     qtdemux->streams[qtdemux->n_streams] = stream;
11676     qtdemux->n_streams++;
11677     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11678   }
11679
11680   return TRUE;
11681
11682 /* ERRORS */
11683 skip_track:
11684   {
11685     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11686     if (new_stream)
11687       gst_qtdemux_stream_free (qtdemux, stream);
11688     return TRUE;
11689   }
11690 corrupt_file:
11691   {
11692     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11693         (_("This file is corrupt and cannot be played.")), (NULL));
11694     if (new_stream)
11695       gst_qtdemux_stream_free (qtdemux, stream);
11696     return FALSE;
11697   }
11698 error_encrypted:
11699   {
11700     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11701     if (new_stream)
11702       gst_qtdemux_stream_free (qtdemux, stream);
11703     return FALSE;
11704   }
11705 samples_failed:
11706 segments_failed:
11707   {
11708     /* we posted an error already */
11709     /* free stbl sub-atoms */
11710     gst_qtdemux_stbl_free (stream);
11711     if (new_stream)
11712       gst_qtdemux_stream_free (qtdemux, stream);
11713     return FALSE;
11714   }
11715 existing_stream:
11716   {
11717     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11718         track_id);
11719     if (new_stream)
11720       gst_qtdemux_stream_free (qtdemux, stream);
11721     return TRUE;
11722   }
11723 unknown_stream:
11724   {
11725     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11726         GST_FOURCC_ARGS (stream->subtype));
11727     if (new_stream)
11728       gst_qtdemux_stream_free (qtdemux, stream);
11729     return TRUE;
11730   }
11731 too_many_streams:
11732   {
11733     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11734         (_("This file contains too many streams. Only playing first %d"),
11735             GST_QTDEMUX_MAX_STREAMS), (NULL));
11736     return TRUE;
11737   }
11738 }
11739
11740 /* If we can estimate the overall bitrate, and don't have information about the
11741  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11742  * the overall bitrate minus the sum of the bitrates of all other streams. This
11743  * should be useful for the common case where we have one audio and one video
11744  * stream and can estimate the bitrate of one, but not the other. */
11745 static void
11746 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11747 {
11748   QtDemuxStream *stream = NULL;
11749   gint64 size, sys_bitrate, sum_bitrate = 0;
11750   GstClockTime duration;
11751   gint i;
11752   guint bitrate;
11753
11754   if (qtdemux->fragmented)
11755     return;
11756
11757   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11758
11759   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11760       || size <= 0) {
11761     GST_DEBUG_OBJECT (qtdemux,
11762         "Size in bytes of the stream not known - bailing");
11763     return;
11764   }
11765
11766   /* Subtract the header size */
11767   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11768       size, qtdemux->header_size);
11769
11770   if (size < qtdemux->header_size)
11771     return;
11772
11773   size = size - qtdemux->header_size;
11774
11775   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11776     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11777     return;
11778   }
11779
11780   for (i = 0; i < qtdemux->n_streams; i++) {
11781     switch (qtdemux->streams[i]->subtype) {
11782       case FOURCC_soun:
11783       case FOURCC_vide:
11784         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11785             CUR_STREAM (qtdemux->streams[i])->caps);
11786         /* retrieve bitrate, prefer avg then max */
11787         bitrate = 0;
11788         if (qtdemux->streams[i]->stream_tags) {
11789           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11790                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
11791             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11792           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11793                   GST_TAG_NOMINAL_BITRATE, &bitrate))
11794             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11795           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11796                   GST_TAG_BITRATE, &bitrate))
11797             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11798         }
11799         if (bitrate)
11800           sum_bitrate += bitrate;
11801         else {
11802           if (stream) {
11803             GST_DEBUG_OBJECT (qtdemux,
11804                 ">1 stream with unknown bitrate - bailing");
11805             return;
11806           } else
11807             stream = qtdemux->streams[i];
11808         }
11809
11810       default:
11811         /* For other subtypes, we assume no significant impact on bitrate */
11812         break;
11813     }
11814   }
11815
11816   if (!stream) {
11817     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11818     return;
11819   }
11820
11821   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11822
11823   if (sys_bitrate < sum_bitrate) {
11824     /* This can happen, since sum_bitrate might be derived from maximum
11825      * bitrates and not average bitrates */
11826     GST_DEBUG_OBJECT (qtdemux,
11827         "System bitrate less than sum bitrate - bailing");
11828     return;
11829   }
11830
11831   bitrate = sys_bitrate - sum_bitrate;
11832   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11833       ", Stream bitrate = %u", sys_bitrate, bitrate);
11834
11835   if (!stream->stream_tags)
11836     stream->stream_tags = gst_tag_list_new_empty ();
11837   else
11838     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11839
11840   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11841       GST_TAG_BITRATE, bitrate, NULL);
11842 }
11843
11844 static GstFlowReturn
11845 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11846 {
11847   gint i;
11848   GstFlowReturn ret = GST_FLOW_OK;
11849
11850   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11851
11852   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11853     QtDemuxStream *stream = qtdemux->streams[i];
11854     guint32 sample_num = 0;
11855
11856     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11857         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11858
11859     if (qtdemux->fragmented) {
11860       /* need all moov samples first */
11861       GST_OBJECT_LOCK (qtdemux);
11862       while (stream->n_samples == 0)
11863         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11864           break;
11865       GST_OBJECT_UNLOCK (qtdemux);
11866     } else {
11867       /* discard any stray moof */
11868       qtdemux->moof_offset = 0;
11869     }
11870
11871     /* prepare braking */
11872     if (ret != GST_FLOW_ERROR)
11873       ret = GST_FLOW_OK;
11874
11875     /* in pull mode, we should have parsed some sample info by now;
11876      * and quite some code will not handle no samples.
11877      * in push mode, we'll just have to deal with it */
11878     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11879       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11880       gst_qtdemux_remove_stream (qtdemux, i);
11881       i--;
11882       continue;
11883     }
11884
11885     /* parse the initial sample for use in setting the frame rate cap */
11886     while (sample_num == 0 && sample_num < stream->n_samples) {
11887       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11888         break;
11889       ++sample_num;
11890     }
11891     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11892       stream->first_duration = stream->samples[0].duration;
11893       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11894           stream->track_id, stream->first_duration);
11895     }
11896   }
11897
11898   return ret;
11899 }
11900
11901 static GstFlowReturn
11902 qtdemux_expose_streams (GstQTDemux * qtdemux)
11903 {
11904   gint i;
11905   GSList *oldpads = NULL;
11906   GSList *iter;
11907
11908   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11909
11910   for (i = 0; i < qtdemux->n_streams; i++) {
11911     QtDemuxStream *stream = qtdemux->streams[i];
11912     GstPad *oldpad = stream->pad;
11913     GstTagList *list;
11914
11915     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11916         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11917
11918     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11919         stream->track_id == qtdemux->chapters_track_id) {
11920       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11921          so that it doesn't look like a subtitle track */
11922       gst_qtdemux_remove_stream (qtdemux, i);
11923       i--;
11924       continue;
11925     }
11926
11927     /* now we have all info and can expose */
11928     list = stream->stream_tags;
11929     stream->stream_tags = NULL;
11930     if (oldpad)
11931       oldpads = g_slist_prepend (oldpads, oldpad);
11932     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11933       return GST_FLOW_ERROR;
11934   }
11935
11936   gst_qtdemux_guess_bitrate (qtdemux);
11937
11938   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11939
11940   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11941     GstPad *oldpad = iter->data;
11942     GstEvent *event;
11943
11944     event = gst_event_new_eos ();
11945     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
11946       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11947
11948     gst_pad_push_event (oldpad, event);
11949     gst_pad_set_active (oldpad, FALSE);
11950     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11951     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11952     gst_object_unref (oldpad);
11953   }
11954
11955   /* check if we should post a redirect in case there is a single trak
11956    * and it is a redirecting trak */
11957   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11958     GstMessage *m;
11959
11960     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11961         "an external content");
11962     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11963         gst_structure_new ("redirect",
11964             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11965             NULL));
11966     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11967     qtdemux->posted_redirect = TRUE;
11968   }
11969
11970   for (i = 0; i < qtdemux->n_streams; i++) {
11971     QtDemuxStream *stream = qtdemux->streams[i];
11972
11973     qtdemux_do_allocation (qtdemux, stream);
11974   }
11975
11976   qtdemux->exposed = TRUE;
11977   return GST_FLOW_OK;
11978 }
11979
11980 /* check if major or compatible brand is 3GP */
11981 static inline gboolean
11982 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11983 {
11984   if (major) {
11985     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11986         FOURCC_3g__);
11987   } else if (qtdemux->comp_brands != NULL) {
11988     GstMapInfo map;
11989     guint8 *data;
11990     gsize size;
11991     gboolean res = FALSE;
11992
11993     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11994     data = map.data;
11995     size = map.size;
11996     while (size >= 4) {
11997       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11998           FOURCC_3g__);
11999       data += 4;
12000       size -= 4;
12001     }
12002     gst_buffer_unmap (qtdemux->comp_brands, &map);
12003     return res;
12004   } else {
12005     return FALSE;
12006   }
12007 }
12008
12009 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12010 static inline gboolean
12011 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12012 {
12013   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12014       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12015       || fourcc == FOURCC_albm;
12016 }
12017
12018 static void
12019 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12020     const char *tag, const char *dummy, GNode * node)
12021 {
12022   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12023   int offset;
12024   char *name;
12025   gchar *data;
12026   gdouble longitude, latitude, altitude;
12027   gint len;
12028
12029   len = QT_UINT32 (node->data);
12030   if (len <= 14)
12031     goto short_read;
12032
12033   data = node->data;
12034   offset = 14;
12035
12036   /* TODO: language code skipped */
12037
12038   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12039
12040   if (!name) {
12041     /* do not alarm in trivial case, but bail out otherwise */
12042     if (*(data + offset) != 0) {
12043       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12044           "giving up", tag);
12045     }
12046   } else {
12047     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12048         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12049     offset += strlen (name);
12050     g_free (name);
12051   }
12052
12053   if (len < offset + 2 + 4 + 4 + 4)
12054     goto short_read;
12055
12056   /* +1 +1 = skip null-terminator and location role byte */
12057   offset += 1 + 1;
12058   /* table in spec says unsigned, semantics say negative has meaning ... */
12059   longitude = QT_SFP32 (data + offset);
12060
12061   offset += 4;
12062   latitude = QT_SFP32 (data + offset);
12063
12064   offset += 4;
12065   altitude = QT_SFP32 (data + offset);
12066
12067   /* one invalid means all are invalid */
12068   if (longitude >= -180.0 && longitude <= 180.0 &&
12069       latitude >= -90.0 && latitude <= 90.0) {
12070     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12071         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12072         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12073         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12074   }
12075
12076   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12077
12078   return;
12079
12080   /* ERRORS */
12081 short_read:
12082   {
12083     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12084     return;
12085   }
12086 }
12087
12088
12089 static void
12090 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12091     const char *tag, const char *dummy, GNode * node)
12092 {
12093   guint16 y;
12094   GDate *date;
12095   gint len;
12096
12097   len = QT_UINT32 (node->data);
12098   if (len < 14)
12099     return;
12100
12101   y = QT_UINT16 ((guint8 *) node->data + 12);
12102   if (y == 0) {
12103     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12104     return;
12105   }
12106   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12107
12108   date = g_date_new_dmy (1, 1, y);
12109   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12110   g_date_free (date);
12111 }
12112
12113 static void
12114 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12115     const char *tag, const char *dummy, GNode * node)
12116 {
12117   int offset;
12118   char *tag_str = NULL;
12119   guint8 *entity;
12120   guint16 table;
12121   gint len;
12122
12123   len = QT_UINT32 (node->data);
12124   if (len <= 20)
12125     goto short_read;
12126
12127   offset = 12;
12128   entity = (guint8 *) node->data + offset;
12129   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12130     GST_DEBUG_OBJECT (qtdemux,
12131         "classification info: %c%c%c%c invalid classification entity",
12132         entity[0], entity[1], entity[2], entity[3]);
12133     return;
12134   }
12135
12136   offset += 4;
12137   table = QT_UINT16 ((guint8 *) node->data + offset);
12138
12139   /* Language code skipped */
12140
12141   offset += 4;
12142
12143   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12144    * XXXX: classification entity, fixed length 4 chars.
12145    * Y[YYYY]: classification table, max 5 chars.
12146    */
12147   tag_str = g_strdup_printf ("----://%u/%s",
12148       table, (char *) node->data + offset);
12149
12150   /* memcpy To be sure we're preserving byte order */
12151   memcpy (tag_str, entity, 4);
12152   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12153
12154   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12155
12156   g_free (tag_str);
12157
12158   return;
12159
12160   /* ERRORS */
12161 short_read:
12162   {
12163     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12164     return;
12165   }
12166 }
12167
12168 static gboolean
12169 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12170     const char *tag, const char *dummy, GNode * node)
12171 {
12172   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12173   GNode *data;
12174   char *s;
12175   int len;
12176   guint32 type;
12177   int offset;
12178   gboolean ret = TRUE;
12179   const gchar *charset = NULL;
12180
12181   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12182   if (data) {
12183     len = QT_UINT32 (data->data);
12184     type = QT_UINT32 ((guint8 *) data->data + 8);
12185     if (type == 0x00000001 && len > 16) {
12186       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12187           env_vars);
12188       if (s) {
12189         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12190         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12191         g_free (s);
12192       } else {
12193         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12194       }
12195     }
12196   } else {
12197     len = QT_UINT32 (node->data);
12198     type = QT_UINT32 ((guint8 *) node->data + 4);
12199     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12200       gint str_len;
12201       gint lang_code;
12202
12203       /* Type starts with the (C) symbol, so the next data is a list
12204        * of (string size(16), language code(16), string) */
12205
12206       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12207       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12208
12209       /* the string + fourcc + size + 2 16bit fields,
12210        * means that there are more tags in this atom */
12211       if (len > str_len + 8 + 4) {
12212         /* TODO how to represent the same tag in different languages? */
12213         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12214             "text alternatives, reading only first one");
12215       }
12216
12217       offset = 12;
12218       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12219       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12220
12221       if (lang_code < 0x800) {  /* MAC encoded string */
12222         charset = "mac";
12223       }
12224     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12225             QT_FOURCC ((guint8 *) node->data + 4))) {
12226       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12227
12228       /* we go for 3GP style encoding if major brands claims so,
12229        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12230       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12231           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12232               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12233         offset = 14;
12234         /* 16-bit Language code is ignored here as well */
12235         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12236       } else {
12237         goto normal;
12238       }
12239     } else {
12240     normal:
12241       offset = 8;
12242       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12243       ret = FALSE;              /* may have to fallback */
12244     }
12245     if (charset) {
12246       GError *err = NULL;
12247
12248       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12249           charset, NULL, NULL, &err);
12250       if (err) {
12251         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12252             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12253             err->message);
12254         g_error_free (err);
12255       }
12256     } else {
12257       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12258           len - offset, env_vars);
12259     }
12260     if (s) {
12261       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12262       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12263       g_free (s);
12264       ret = TRUE;
12265     } else {
12266       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12267     }
12268   }
12269   return ret;
12270 }
12271
12272 static void
12273 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12274     const char *tag, const char *dummy, GNode * node)
12275 {
12276   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12277 }
12278
12279 static void
12280 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12281     const char *tag, const char *dummy, GNode * node)
12282 {
12283   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12284   guint8 *data;
12285   char *s, *t, *k = NULL;
12286   int len;
12287   int offset;
12288   int count;
12289
12290   /* first try normal string tag if major brand not 3GP */
12291   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12292     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12293       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12294        * let's try it 3gpp way after minor safety check */
12295       data = node->data;
12296       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12297         return;
12298     } else
12299       return;
12300   }
12301
12302   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12303
12304   data = node->data;
12305
12306   len = QT_UINT32 (data);
12307   if (len < 15)
12308     goto short_read;
12309
12310   count = QT_UINT8 (data + 14);
12311   offset = 15;
12312   for (; count; count--) {
12313     gint slen;
12314
12315     if (offset + 1 > len)
12316       goto short_read;
12317     slen = QT_UINT8 (data + offset);
12318     offset += 1;
12319     if (offset + slen > len)
12320       goto short_read;
12321     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12322         slen, env_vars);
12323     if (s) {
12324       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12325       if (k) {
12326         t = g_strjoin (",", k, s, NULL);
12327         g_free (s);
12328         g_free (k);
12329         k = t;
12330       } else {
12331         k = s;
12332       }
12333     } else {
12334       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12335     }
12336     offset += slen;
12337   }
12338
12339 done:
12340   if (k) {
12341     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12342     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12343   }
12344   g_free (k);
12345
12346   return;
12347
12348   /* ERRORS */
12349 short_read:
12350   {
12351     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12352     goto done;
12353   }
12354 }
12355
12356 static void
12357 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12358     const char *tag1, const char *tag2, GNode * node)
12359 {
12360   GNode *data;
12361   int len;
12362   int type;
12363   int n1, n2;
12364
12365   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12366   if (data) {
12367     len = QT_UINT32 (data->data);
12368     type = QT_UINT32 ((guint8 *) data->data + 8);
12369     if (type == 0x00000000 && len >= 22) {
12370       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12371       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12372       if (n1 > 0) {
12373         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12374         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12375       }
12376       if (n2 > 0) {
12377         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12378         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12379       }
12380     }
12381   }
12382 }
12383
12384 static void
12385 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12386     const char *tag1, const char *dummy, GNode * node)
12387 {
12388   GNode *data;
12389   int len;
12390   int type;
12391   int n1;
12392
12393   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12394   if (data) {
12395     len = QT_UINT32 (data->data);
12396     type = QT_UINT32 ((guint8 *) data->data + 8);
12397     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12398     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12399     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12400       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12401       if (n1) {
12402         /* do not add bpm=0 */
12403         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12404         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12405             NULL);
12406       }
12407     }
12408   }
12409 }
12410
12411 static void
12412 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12413     const char *tag1, const char *dummy, GNode * node)
12414 {
12415   GNode *data;
12416   int len;
12417   int type;
12418   guint32 num;
12419
12420   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12421   if (data) {
12422     len = QT_UINT32 (data->data);
12423     type = QT_UINT32 ((guint8 *) data->data + 8);
12424     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12425     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12426     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12427       num = QT_UINT32 ((guint8 *) data->data + 16);
12428       if (num) {
12429         /* do not add num=0 */
12430         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12431         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12432       }
12433     }
12434   }
12435 }
12436
12437 static void
12438 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12439     const char *tag1, const char *dummy, GNode * node)
12440 {
12441   GNode *data;
12442   int len;
12443   int type;
12444   GstSample *sample;
12445
12446   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12447   if (data) {
12448     len = QT_UINT32 (data->data);
12449     type = QT_UINT32 ((guint8 *) data->data + 8);
12450     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12451     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12452       GstTagImageType image_type;
12453
12454       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12455         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12456       else
12457         image_type = GST_TAG_IMAGE_TYPE_NONE;
12458
12459       if ((sample =
12460               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12461                   len - 16, image_type))) {
12462         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12463         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12464         gst_sample_unref (sample);
12465       }
12466     }
12467   }
12468 }
12469
12470 static void
12471 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12472     const char *tag, const char *dummy, GNode * node)
12473 {
12474   GNode *data;
12475   char *s;
12476   int len;
12477   int type;
12478
12479   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12480   if (data) {
12481     len = QT_UINT32 (data->data);
12482     type = QT_UINT32 ((guint8 *) data->data + 8);
12483     if (type == 0x00000001 && len > 16) {
12484       guint y, m = 1, d = 1;
12485       gint ret;
12486
12487       s = g_strndup ((char *) data->data + 16, len - 16);
12488       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12489       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12490       if (ret >= 1 && y > 1500 && y < 3000) {
12491         GDate *date;
12492
12493         date = g_date_new_dmy (d, m, y);
12494         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12495         g_date_free (date);
12496       } else {
12497         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12498       }
12499       g_free (s);
12500     }
12501   }
12502 }
12503
12504 static void
12505 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12506     const char *tag, const char *dummy, GNode * node)
12507 {
12508   GNode *data;
12509
12510   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12511
12512   /* re-route to normal string tag if major brand says so
12513    * or no data atom and compatible brand suggests so */
12514   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12515       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12516     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12517     return;
12518   }
12519
12520   if (data) {
12521     guint len, type, n;
12522
12523     len = QT_UINT32 (data->data);
12524     type = QT_UINT32 ((guint8 *) data->data + 8);
12525     if (type == 0x00000000 && len >= 18) {
12526       n = QT_UINT16 ((guint8 *) data->data + 16);
12527       if (n > 0) {
12528         const gchar *genre;
12529
12530         genre = gst_tag_id3_genre_get (n - 1);
12531         if (genre != NULL) {
12532           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12533           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12534         }
12535       }
12536     }
12537   }
12538 }
12539
12540 static void
12541 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12542     const gchar * tag, guint8 * data, guint32 datasize)
12543 {
12544   gdouble value;
12545   gchar *datacopy;
12546
12547   /* make a copy to have \0 at the end */
12548   datacopy = g_strndup ((gchar *) data, datasize);
12549
12550   /* convert the str to double */
12551   if (sscanf (datacopy, "%lf", &value) == 1) {
12552     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12553     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12554   } else {
12555     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12556         datacopy);
12557   }
12558   g_free (datacopy);
12559 }
12560
12561
12562 static void
12563 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12564     const char *tag, const char *tag_bis, GNode * node)
12565 {
12566   GNode *mean;
12567   GNode *name;
12568   GNode *data;
12569   guint32 meansize;
12570   guint32 namesize;
12571   guint32 datatype;
12572   guint32 datasize;
12573   const gchar *meanstr;
12574   const gchar *namestr;
12575
12576   /* checking the whole ---- atom size for consistency */
12577   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12578     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12579     return;
12580   }
12581
12582   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12583   if (!mean) {
12584     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12585     return;
12586   }
12587
12588   meansize = QT_UINT32 (mean->data);
12589   if (meansize <= 12) {
12590     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12591     return;
12592   }
12593   meanstr = ((gchar *) mean->data) + 12;
12594   meansize -= 12;
12595
12596   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12597   if (!name) {
12598     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12599     return;
12600   }
12601
12602   namesize = QT_UINT32 (name->data);
12603   if (namesize <= 12) {
12604     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12605     return;
12606   }
12607   namestr = ((gchar *) name->data) + 12;
12608   namesize -= 12;
12609
12610   /*
12611    * Data atom is:
12612    * uint32 - size
12613    * uint32 - name
12614    * uint8  - version
12615    * uint24 - data type
12616    * uint32 - all 0
12617    * rest   - the data
12618    */
12619   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12620   if (!data) {
12621     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12622     return;
12623   }
12624   datasize = QT_UINT32 (data->data);
12625   if (datasize <= 16) {
12626     GST_WARNING_OBJECT (demux, "Data atom too small");
12627     return;
12628   }
12629   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12630
12631   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12632       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12633     static const struct
12634     {
12635       const gchar name[28];
12636       const gchar tag[28];
12637     } tags[] = {
12638       {
12639       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12640       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12641       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12642       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12643       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12644       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12645       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12646       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12647     };
12648     int i;
12649
12650     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12651       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12652         switch (gst_tag_get_type (tags[i].tag)) {
12653           case G_TYPE_DOUBLE:
12654             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12655                 ((guint8 *) data->data) + 16, datasize - 16);
12656             break;
12657           case G_TYPE_STRING:
12658             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12659             break;
12660           default:
12661             /* not reached */
12662             break;
12663         }
12664         break;
12665       }
12666     }
12667     if (i == G_N_ELEMENTS (tags))
12668       goto unknown_tag;
12669   } else {
12670     goto unknown_tag;
12671   }
12672
12673   return;
12674
12675 /* errors */
12676 unknown_tag:
12677 #ifndef GST_DISABLE_GST_DEBUG
12678   {
12679     gchar *namestr_dbg;
12680     gchar *meanstr_dbg;
12681
12682     meanstr_dbg = g_strndup (meanstr, meansize);
12683     namestr_dbg = g_strndup (namestr, namesize);
12684
12685     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12686         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12687
12688     g_free (namestr_dbg);
12689     g_free (meanstr_dbg);
12690   }
12691 #endif
12692   return;
12693 }
12694
12695 static void
12696 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12697     const char *tag_bis, GNode * node)
12698 {
12699   guint8 *data;
12700   GstBuffer *buf;
12701   guint len;
12702   GstTagList *id32_taglist = NULL;
12703
12704   GST_LOG_OBJECT (demux, "parsing ID32");
12705
12706   data = node->data;
12707   len = GST_READ_UINT32_BE (data);
12708
12709   /* need at least full box and language tag */
12710   if (len < 12 + 2)
12711     return;
12712
12713   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12714   gst_buffer_fill (buf, 0, data + 14, len - 14);
12715
12716   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12717   if (id32_taglist) {
12718     GST_LOG_OBJECT (demux, "parsing ok");
12719     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12720     gst_tag_list_unref (id32_taglist);
12721   } else {
12722     GST_LOG_OBJECT (demux, "parsing failed");
12723   }
12724
12725   gst_buffer_unref (buf);
12726 }
12727
12728 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12729     const char *tag, const char *tag_bis, GNode * node);
12730
12731 /* unmapped tags
12732 FOURCC_pcst -> if media is a podcast -> bool
12733 FOURCC_cpil -> if media is part of a compilation -> bool
12734 FOURCC_pgap -> if media is part of a gapless context -> bool
12735 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12736 */
12737
12738 static const struct
12739 {
12740   guint32 fourcc;
12741   const gchar *gst_tag;
12742   const gchar *gst_tag_bis;
12743   const GstQTDemuxAddTagFunc func;
12744 } add_funcs[] = {
12745   {
12746   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12747   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12748   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12749   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12750   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12751   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12752   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12753   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12754   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12755   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12756   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12757   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12758   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12759   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12760   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12761   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12762   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12763   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12764   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12765   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12766   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12767   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12768   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12769         qtdemux_tag_add_num}, {
12770   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12771         qtdemux_tag_add_num}, {
12772   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12773   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12774   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12775   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12776   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12777   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12778   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12779   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12780   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12781   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12782   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12783   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12784   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12785   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12786   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12787   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12788   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12789   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12790         qtdemux_tag_add_classification}, {
12791   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12792   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12793   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12794
12795     /* This is a special case, some tags are stored in this
12796      * 'reverse dns naming', according to:
12797      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12798      * bug #614471
12799      */
12800   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12801     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12802   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12803 };
12804
12805 struct _GstQtDemuxTagList
12806 {
12807   GstQTDemux *demux;
12808   GstTagList *taglist;
12809 };
12810 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12811
12812 static void
12813 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12814 {
12815   gint len;
12816   guint8 *data;
12817   GstBuffer *buf;
12818   gchar *media_type;
12819   const gchar *style;
12820   GstSample *sample;
12821   GstStructure *s;
12822   guint i;
12823   guint8 ndata[4];
12824   GstQTDemux *demux = qtdemuxtaglist->demux;
12825   GstTagList *taglist = qtdemuxtaglist->taglist;
12826
12827   data = node->data;
12828   len = QT_UINT32 (data);
12829   buf = gst_buffer_new_and_alloc (len);
12830   gst_buffer_fill (buf, 0, data, len);
12831
12832   /* heuristic to determine style of tag */
12833   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12834       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12835     style = "itunes";
12836   else if (demux->major_brand == FOURCC_qt__)
12837     style = "quicktime";
12838   /* fall back to assuming iso/3gp tag style */
12839   else
12840     style = "iso";
12841
12842   /* santize the name for the caps. */
12843   for (i = 0; i < 4; i++) {
12844     guint8 d = data[4 + i];
12845     if (g_ascii_isalnum (d))
12846       ndata[i] = g_ascii_tolower (d);
12847     else
12848       ndata[i] = '_';
12849   }
12850
12851   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12852       ndata[0], ndata[1], ndata[2], ndata[3]);
12853   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12854
12855   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12856   sample = gst_sample_new (buf, NULL, NULL, s);
12857   gst_buffer_unref (buf);
12858   g_free (media_type);
12859
12860   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12861       len, s);
12862
12863   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12864       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12865
12866   gst_sample_unref (sample);
12867 }
12868
12869 static void
12870 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12871 {
12872   GNode *meta;
12873   GNode *ilst;
12874   GNode *xmp_;
12875   GNode *node;
12876   gint i;
12877   GstQtDemuxTagList demuxtaglist;
12878
12879   demuxtaglist.demux = qtdemux;
12880   demuxtaglist.taglist = taglist;
12881
12882   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12883   if (meta != NULL) {
12884     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12885     if (ilst == NULL) {
12886       GST_LOG_OBJECT (qtdemux, "no ilst");
12887       return;
12888     }
12889   } else {
12890     ilst = udta;
12891     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12892   }
12893
12894   i = 0;
12895   while (i < G_N_ELEMENTS (add_funcs)) {
12896     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12897     if (node) {
12898       gint len;
12899
12900       len = QT_UINT32 (node->data);
12901       if (len < 12) {
12902         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12903             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12904       } else {
12905         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12906             add_funcs[i].gst_tag_bis, node);
12907       }
12908       g_node_destroy (node);
12909     } else {
12910       i++;
12911     }
12912   }
12913
12914   /* parsed nodes have been removed, pass along remainder as blob */
12915   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12916       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12917
12918   /* parse up XMP_ node if existing */
12919   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12920   if (xmp_ != NULL) {
12921     GstBuffer *buf;
12922     GstTagList *xmptaglist;
12923
12924     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12925         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12926     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12927     gst_buffer_unref (buf);
12928
12929     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12930   } else {
12931     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12932   }
12933 }
12934
12935 typedef struct
12936 {
12937   GstStructure *structure;      /* helper for sort function */
12938   gchar *location;
12939   guint min_req_bitrate;
12940   guint min_req_qt_version;
12941 } GstQtReference;
12942
12943 static gint
12944 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12945 {
12946   GstQtReference *ref_a = (GstQtReference *) a;
12947   GstQtReference *ref_b = (GstQtReference *) b;
12948
12949   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12950     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12951
12952   /* known bitrates go before unknown; higher bitrates go first */
12953   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12954 }
12955
12956 /* sort the redirects and post a message for the application.
12957  */
12958 static void
12959 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12960 {
12961   GstQtReference *best;
12962   GstStructure *s;
12963   GstMessage *msg;
12964   GValue list_val = { 0, };
12965   GList *l;
12966
12967   g_assert (references != NULL);
12968
12969   references = g_list_sort (references, qtdemux_redirects_sort_func);
12970
12971   best = (GstQtReference *) references->data;
12972
12973   g_value_init (&list_val, GST_TYPE_LIST);
12974
12975   for (l = references; l != NULL; l = l->next) {
12976     GstQtReference *ref = (GstQtReference *) l->data;
12977     GValue struct_val = { 0, };
12978
12979     ref->structure = gst_structure_new ("redirect",
12980         "new-location", G_TYPE_STRING, ref->location, NULL);
12981
12982     if (ref->min_req_bitrate > 0) {
12983       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12984           ref->min_req_bitrate, NULL);
12985     }
12986
12987     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12988     g_value_set_boxed (&struct_val, ref->structure);
12989     gst_value_list_append_value (&list_val, &struct_val);
12990     g_value_unset (&struct_val);
12991     /* don't free anything here yet, since we need best->structure below */
12992   }
12993
12994   g_assert (best != NULL);
12995   s = gst_structure_copy (best->structure);
12996
12997   if (g_list_length (references) > 1) {
12998     gst_structure_set_value (s, "locations", &list_val);
12999   }
13000
13001   g_value_unset (&list_val);
13002
13003   for (l = references; l != NULL; l = l->next) {
13004     GstQtReference *ref = (GstQtReference *) l->data;
13005
13006     gst_structure_free (ref->structure);
13007     g_free (ref->location);
13008     g_free (ref);
13009   }
13010   g_list_free (references);
13011
13012   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13013   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13014   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13015   qtdemux->posted_redirect = TRUE;
13016 }
13017
13018 /* look for redirect nodes, collect all redirect information and
13019  * process it.
13020  */
13021 static gboolean
13022 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13023 {
13024   GNode *rmra, *rmda, *rdrf;
13025
13026   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13027   if (rmra) {
13028     GList *redirects = NULL;
13029
13030     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13031     while (rmda) {
13032       GstQtReference ref = { NULL, NULL, 0, 0 };
13033       GNode *rmdr, *rmvc;
13034
13035       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13036         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13037         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13038             ref.min_req_bitrate);
13039       }
13040
13041       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13042         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13043         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13044
13045 #ifndef GST_DISABLE_GST_DEBUG
13046         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13047 #endif
13048         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13049
13050         GST_LOG_OBJECT (qtdemux,
13051             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13052             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13053             bitmask, check_type);
13054         if (package == FOURCC_qtim && check_type == 0) {
13055           ref.min_req_qt_version = version;
13056         }
13057       }
13058
13059       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13060       if (rdrf) {
13061         guint32 ref_type;
13062         guint8 *ref_data;
13063         guint ref_len;
13064
13065         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13066         if (ref_len > 20) {
13067           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13068           ref_data = (guint8 *) rdrf->data + 20;
13069           if (ref_type == FOURCC_alis) {
13070             guint record_len, record_version, fn_len;
13071
13072             if (ref_len > 70) {
13073               /* MacOSX alias record, google for alias-layout.txt */
13074               record_len = QT_UINT16 (ref_data + 4);
13075               record_version = QT_UINT16 (ref_data + 4 + 2);
13076               fn_len = QT_UINT8 (ref_data + 50);
13077               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13078                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13079               }
13080             } else {
13081               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13082                   ref_len);
13083             }
13084           } else if (ref_type == FOURCC_url_) {
13085             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13086           } else {
13087             GST_DEBUG_OBJECT (qtdemux,
13088                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13089                 GST_FOURCC_ARGS (ref_type));
13090           }
13091           if (ref.location != NULL) {
13092             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13093             redirects =
13094                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13095           } else {
13096             GST_WARNING_OBJECT (qtdemux,
13097                 "Failed to extract redirect location from rdrf atom");
13098           }
13099         } else {
13100           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13101         }
13102       }
13103
13104       /* look for others */
13105       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13106     }
13107
13108     if (redirects != NULL) {
13109       qtdemux_process_redirects (qtdemux, redirects);
13110     }
13111   }
13112   return TRUE;
13113 }
13114
13115 static GstTagList *
13116 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13117 {
13118   const gchar *fmt;
13119
13120   if (tags == NULL) {
13121     tags = gst_tag_list_new_empty ();
13122     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13123   }
13124
13125   if (qtdemux->major_brand == FOURCC_mjp2)
13126     fmt = "Motion JPEG 2000";
13127   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13128     fmt = "3GP";
13129   else if (qtdemux->major_brand == FOURCC_qt__)
13130     fmt = "Quicktime";
13131   else if (qtdemux->fragmented)
13132     fmt = "ISO fMP4";
13133   else
13134     fmt = "ISO MP4/M4A";
13135
13136   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13137       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13138
13139   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13140       fmt, NULL);
13141
13142   return tags;
13143 }
13144
13145 /* we have read the complete moov node now.
13146  * This function parses all of the relevant info, creates the traks and
13147  * prepares all data structures for playback
13148  */
13149 static gboolean
13150 qtdemux_parse_tree (GstQTDemux * qtdemux)
13151 {
13152   GNode *mvhd;
13153   GNode *trak;
13154   GNode *udta;
13155   GNode *mvex;
13156   GstClockTime duration;
13157   GNode *pssh;
13158   guint64 creation_time;
13159   GstDateTime *datetime = NULL;
13160   gint version;
13161
13162   /* make sure we have a usable taglist */
13163   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13164
13165   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13166   if (mvhd == NULL) {
13167     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13168     return qtdemux_parse_redirects (qtdemux);
13169   }
13170
13171   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13172   if (version == 1) {
13173     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13174     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13175     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13176   } else if (version == 0) {
13177     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13178     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13179     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13180   } else {
13181     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13182     return FALSE;
13183   }
13184
13185   /* Moving qt creation time (secs since 1904) to unix time */
13186   if (creation_time != 0) {
13187     /* Try to use epoch first as it should be faster and more commonly found */
13188     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13189       GTimeVal now;
13190
13191       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13192       /* some data cleansing sanity */
13193       g_get_current_time (&now);
13194       if (now.tv_sec + 24 * 3600 < creation_time) {
13195         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13196       } else {
13197         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13198       }
13199     } else {
13200       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13201       GDateTime *dt, *dt_local;
13202
13203       dt = g_date_time_add_seconds (base_dt, creation_time);
13204       dt_local = g_date_time_to_local (dt);
13205       datetime = gst_date_time_new_from_g_date_time (dt_local);
13206
13207       g_date_time_unref (base_dt);
13208       g_date_time_unref (dt);
13209     }
13210   }
13211   if (datetime) {
13212     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13213     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13214         datetime, NULL);
13215     gst_date_time_unref (datetime);
13216   }
13217
13218   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13219   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13220
13221   /* check for fragmented file and get some (default) data */
13222   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13223   if (mvex) {
13224     GNode *mehd;
13225     GstByteReader mehd_data;
13226
13227     /* let track parsing or anyone know weird stuff might happen ... */
13228     qtdemux->fragmented = TRUE;
13229
13230     /* compensate for total duration */
13231     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13232     if (mehd)
13233       qtdemux_parse_mehd (qtdemux, &mehd_data);
13234   }
13235
13236   /* set duration in the segment info */
13237   gst_qtdemux_get_duration (qtdemux, &duration);
13238   if (duration) {
13239     qtdemux->segment.duration = duration;
13240     /* also do not exceed duration; stop is set that way post seek anyway,
13241      * and segment activation falls back to duration,
13242      * whereas loop only checks stop, so let's align this here as well */
13243     qtdemux->segment.stop = duration;
13244   }
13245
13246   /* parse all traks */
13247   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13248   while (trak) {
13249     qtdemux_parse_trak (qtdemux, trak);
13250     /* iterate all siblings */
13251     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13252   }
13253
13254   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13255
13256   /* find tags */
13257   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13258   if (udta) {
13259     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13260   } else {
13261     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13262   }
13263
13264   /* maybe also some tags in meta box */
13265   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13266   if (udta) {
13267     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13268     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13269   } else {
13270     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13271   }
13272
13273   /* parse any protection system info */
13274   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13275   while (pssh) {
13276     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13277     qtdemux_parse_pssh (qtdemux, pssh);
13278     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13279   }
13280
13281   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13282
13283   return TRUE;
13284 }
13285
13286 /* taken from ffmpeg */
13287 static int
13288 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13289 {
13290   int count = 4;
13291   int len = 0;
13292
13293   while (count--) {
13294     int c;
13295
13296     if (ptr >= end)
13297       return -1;
13298
13299     c = *ptr++;
13300     len = (len << 7) | (c & 0x7f);
13301     if (!(c & 0x80))
13302       break;
13303   }
13304   *end_out = ptr;
13305   return len;
13306 }
13307
13308 /* this can change the codec originally present in @list */
13309 static void
13310 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13311     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13312 {
13313   int len = QT_UINT32 (esds->data);
13314   guint8 *ptr = esds->data;
13315   guint8 *end = ptr + len;
13316   int tag;
13317   guint8 *data_ptr = NULL;
13318   int data_len = 0;
13319   guint8 object_type_id = 0;
13320   const char *codec_name = NULL;
13321   GstCaps *caps = NULL;
13322
13323   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13324   ptr += 8;
13325   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13326   ptr += 4;
13327   while (ptr + 1 < end) {
13328     tag = QT_UINT8 (ptr);
13329     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13330     ptr++;
13331     len = read_descr_size (ptr, end, &ptr);
13332     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13333
13334     /* Check the stated amount of data is available for reading */
13335     if (len < 0 || ptr + len > end)
13336       break;
13337
13338     switch (tag) {
13339       case ES_DESCRIPTOR_TAG:
13340         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13341         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13342         ptr += 3;
13343         break;
13344       case DECODER_CONFIG_DESC_TAG:{
13345         guint max_bitrate, avg_bitrate;
13346
13347         object_type_id = QT_UINT8 (ptr);
13348         max_bitrate = QT_UINT32 (ptr + 5);
13349         avg_bitrate = QT_UINT32 (ptr + 9);
13350         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13351         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13352         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13353         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13354         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13355         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13356           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13357               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13358         }
13359         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13360           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13361               avg_bitrate, NULL);
13362         }
13363         ptr += 13;
13364         break;
13365       }
13366       case DECODER_SPECIFIC_INFO_TAG:
13367         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13368         if (object_type_id == 0xe0 && len == 0x40) {
13369           guint8 *data;
13370           GstStructure *s;
13371           guint32 clut[16];
13372           gint i;
13373
13374           GST_DEBUG_OBJECT (qtdemux,
13375               "Have VOBSUB palette. Creating palette event");
13376           /* move to decConfigDescr data and read palette */
13377           data = ptr;
13378           for (i = 0; i < 16; i++) {
13379             clut[i] = QT_UINT32 (data);
13380             data += 4;
13381           }
13382
13383           s = gst_structure_new ("application/x-gst-dvd", "event",
13384               G_TYPE_STRING, "dvd-spu-clut-change",
13385               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13386               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13387               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13388               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13389               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13390               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13391               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13392               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13393               NULL);
13394
13395           /* store event and trigger custom processing */
13396           stream->pending_event =
13397               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13398         } else {
13399           /* Generic codec_data handler puts it on the caps */
13400           data_ptr = ptr;
13401           data_len = len;
13402         }
13403
13404         ptr += len;
13405         break;
13406       case SL_CONFIG_DESC_TAG:
13407         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13408         ptr += 1;
13409         break;
13410       default:
13411         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13412             tag);
13413         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13414         ptr += len;
13415         break;
13416     }
13417   }
13418
13419   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13420    * in use, and should also be used to override some other parameters for some
13421    * codecs. */
13422   switch (object_type_id) {
13423     case 0x20:                 /* MPEG-4 */
13424       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13425        * profile_and_level_indication */
13426       if (data_ptr != NULL && data_len >= 5 &&
13427           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13428         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13429             data_ptr + 4, data_len - 4);
13430       }
13431       break;                    /* Nothing special needed here */
13432     case 0x21:                 /* H.264 */
13433       codec_name = "H.264 / AVC";
13434       caps = gst_caps_new_simple ("video/x-h264",
13435           "stream-format", G_TYPE_STRING, "avc",
13436           "alignment", G_TYPE_STRING, "au", NULL);
13437       break;
13438     case 0x40:                 /* AAC (any) */
13439     case 0x66:                 /* AAC Main */
13440     case 0x67:                 /* AAC LC */
13441     case 0x68:                 /* AAC SSR */
13442       /* Override channels and rate based on the codec_data, as it's often
13443        * wrong. */
13444       /* Only do so for basic setup without HE-AAC extension */
13445       if (data_ptr && data_len == 2) {
13446         guint channels, rate;
13447
13448         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13449         if (channels > 0)
13450           entry->n_channels = channels;
13451
13452         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13453         if (rate > 0)
13454           entry->rate = rate;
13455       }
13456
13457       /* Set level and profile if possible */
13458       if (data_ptr != NULL && data_len >= 2) {
13459         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13460             data_ptr, data_len);
13461       } else {
13462         const gchar *profile_str = NULL;
13463         GstBuffer *buffer;
13464         GstMapInfo map;
13465         guint8 *codec_data;
13466         gint rate_idx, profile;
13467
13468         /* No codec_data, let's invent something.
13469          * FIXME: This is wrong for SBR! */
13470
13471         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13472
13473         buffer = gst_buffer_new_and_alloc (2);
13474         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13475         codec_data = map.data;
13476
13477         rate_idx =
13478             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13479             (stream)->rate);
13480
13481         switch (object_type_id) {
13482           case 0x66:
13483             profile_str = "main";
13484             profile = 0;
13485             break;
13486           case 0x67:
13487             profile_str = "lc";
13488             profile = 1;
13489             break;
13490           case 0x68:
13491             profile_str = "ssr";
13492             profile = 2;
13493             break;
13494           default:
13495             profile = 3;
13496             break;
13497         }
13498
13499         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13500         codec_data[1] =
13501             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13502
13503         gst_buffer_unmap (buffer, &map);
13504         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13505             GST_TYPE_BUFFER, buffer, NULL);
13506         gst_buffer_unref (buffer);
13507
13508         if (profile_str) {
13509           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13510               G_TYPE_STRING, profile_str, NULL);
13511         }
13512       }
13513       break;
13514     case 0x60:                 /* MPEG-2, various profiles */
13515     case 0x61:
13516     case 0x62:
13517     case 0x63:
13518     case 0x64:
13519     case 0x65:
13520       codec_name = "MPEG-2 video";
13521       caps = gst_caps_new_simple ("video/mpeg",
13522           "mpegversion", G_TYPE_INT, 2,
13523           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13524       break;
13525     case 0x69:                 /* MPEG-2 BC audio */
13526     case 0x6B:                 /* MPEG-1 audio */
13527       caps = gst_caps_new_simple ("audio/mpeg",
13528           "mpegversion", G_TYPE_INT, 1, NULL);
13529       codec_name = "MPEG-1 audio";
13530       break;
13531     case 0x6A:                 /* MPEG-1 */
13532       codec_name = "MPEG-1 video";
13533       caps = gst_caps_new_simple ("video/mpeg",
13534           "mpegversion", G_TYPE_INT, 1,
13535           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13536       break;
13537     case 0x6C:                 /* MJPEG */
13538       caps =
13539           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13540           NULL);
13541       codec_name = "Motion-JPEG";
13542       break;
13543     case 0x6D:                 /* PNG */
13544       caps =
13545           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13546           NULL);
13547       codec_name = "PNG still images";
13548       break;
13549     case 0x6E:                 /* JPEG2000 */
13550       codec_name = "JPEG-2000";
13551       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13552       break;
13553     case 0xA4:                 /* Dirac */
13554       codec_name = "Dirac";
13555       caps = gst_caps_new_empty_simple ("video/x-dirac");
13556       break;
13557     case 0xA5:                 /* AC3 */
13558       codec_name = "AC-3 audio";
13559       caps = gst_caps_new_simple ("audio/x-ac3",
13560           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13561       break;
13562     case 0xA9:                 /* AC3 */
13563       codec_name = "DTS audio";
13564       caps = gst_caps_new_simple ("audio/x-dts",
13565           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13566       break;
13567     case 0xE1:                 /* QCELP */
13568       /* QCELP, the codec_data is a riff tag (little endian) with
13569        * 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). */
13570       caps = gst_caps_new_empty_simple ("audio/qcelp");
13571       codec_name = "QCELP";
13572       break;
13573     default:
13574       break;
13575   }
13576
13577   /* If we have a replacement caps, then change our caps for this stream */
13578   if (caps) {
13579     gst_caps_unref (entry->caps);
13580     entry->caps = caps;
13581   }
13582
13583   if (codec_name && list)
13584     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13585         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13586
13587   /* Add the codec_data attribute to caps, if we have it */
13588   if (data_ptr) {
13589     GstBuffer *buffer;
13590
13591     buffer = gst_buffer_new_and_alloc (data_len);
13592     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13593
13594     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13595     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13596
13597     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13598         buffer, NULL);
13599     gst_buffer_unref (buffer);
13600   }
13601
13602 }
13603
13604 static inline GstCaps *
13605 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13606 {
13607   GstCaps *caps;
13608   guint i;
13609   char *s, fourstr[5];
13610
13611   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13612   for (i = 0; i < 4; i++) {
13613     if (!g_ascii_isalnum (fourstr[i]))
13614       fourstr[i] = '_';
13615   }
13616   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13617   caps = gst_caps_new_empty_simple (s);
13618   g_free (s);
13619   return caps;
13620 }
13621
13622 #define _codec(name) \
13623   do { \
13624     if (codec_name) { \
13625       *codec_name = g_strdup (name); \
13626     } \
13627   } while (0)
13628
13629 static GstCaps *
13630 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13631     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13632     const guint8 * stsd_entry_data, gchar ** codec_name)
13633 {
13634   GstCaps *caps = NULL;
13635   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13636
13637   switch (fourcc) {
13638     case FOURCC_png:
13639       _codec ("PNG still images");
13640       caps = gst_caps_new_empty_simple ("image/png");
13641       break;
13642     case FOURCC_jpeg:
13643       _codec ("JPEG still images");
13644       caps =
13645           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13646           NULL);
13647       break;
13648     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13649     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13650     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13651     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13652       _codec ("Motion-JPEG");
13653       caps =
13654           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13655           NULL);
13656       break;
13657     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13658       _codec ("Motion-JPEG format B");
13659       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13660       break;
13661     case FOURCC_mjp2:
13662       _codec ("JPEG-2000");
13663       /* override to what it should be according to spec, avoid palette_data */
13664       entry->bits_per_sample = 24;
13665       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13666       break;
13667     case FOURCC_SVQ3:
13668       _codec ("Sorensen video v.3");
13669       caps = gst_caps_new_simple ("video/x-svq",
13670           "svqversion", G_TYPE_INT, 3, NULL);
13671       break;
13672     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13673     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13674       _codec ("Sorensen video v.1");
13675       caps = gst_caps_new_simple ("video/x-svq",
13676           "svqversion", G_TYPE_INT, 1, NULL);
13677       break;
13678     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13679       caps = gst_caps_new_empty_simple ("video/x-raw");
13680       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13681       _codec ("Windows Raw RGB");
13682       stream->alignment = 32;
13683       break;
13684     case FOURCC_raw_:
13685     {
13686       guint16 bps;
13687
13688       bps = QT_UINT16 (stsd_entry_data + 82);
13689       switch (bps) {
13690         case 15:
13691           format = GST_VIDEO_FORMAT_RGB15;
13692           break;
13693         case 16:
13694           format = GST_VIDEO_FORMAT_RGB16;
13695           break;
13696         case 24:
13697           format = GST_VIDEO_FORMAT_RGB;
13698           break;
13699         case 32:
13700           format = GST_VIDEO_FORMAT_ARGB;
13701           break;
13702         default:
13703           /* unknown */
13704           break;
13705       }
13706       break;
13707     }
13708     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13709       format = GST_VIDEO_FORMAT_I420;
13710       break;
13711     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13712     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13713       format = GST_VIDEO_FORMAT_I420;
13714       break;
13715     case FOURCC_2vuy:
13716     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13717       format = GST_VIDEO_FORMAT_UYVY;
13718       break;
13719     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13720       format = GST_VIDEO_FORMAT_v308;
13721       break;
13722     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13723       format = GST_VIDEO_FORMAT_v216;
13724       break;
13725     case FOURCC_v210:
13726       format = GST_VIDEO_FORMAT_v210;
13727       break;
13728     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13729       format = GST_VIDEO_FORMAT_r210;
13730       break;
13731       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13732          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13733          format = GST_VIDEO_FORMAT_v410;
13734          break;
13735        */
13736       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13737        * but different order than AYUV
13738        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13739        format = GST_VIDEO_FORMAT_v408;
13740        break;
13741        */
13742     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13743     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13744       _codec ("MPEG-1 video");
13745       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13746           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13747       break;
13748     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13749     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13750     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13751     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13752     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13753     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13754     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13755     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13756     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13757     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13758     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13759     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13760     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13761     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13762     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13763     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13764     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13765     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13766     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13767     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13768     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13769     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13770     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13771     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13772     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13773     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13774     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13775     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13776     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13777     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13778     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13779     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13780     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13781     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13782     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13783     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13784     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13785     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13786     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13787     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13788     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13789     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13790     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13791     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13792     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13793     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13794     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13795       _codec ("MPEG-2 video");
13796       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13797           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13798       break;
13799     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13800       _codec ("GIF still images");
13801       caps = gst_caps_new_empty_simple ("image/gif");
13802       break;
13803     case FOURCC_h263:
13804     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13805     case FOURCC_s263:
13806     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13807       _codec ("H.263");
13808       /* ffmpeg uses the height/width props, don't know why */
13809       caps = gst_caps_new_simple ("video/x-h263",
13810           "variant", G_TYPE_STRING, "itu", NULL);
13811       break;
13812     case FOURCC_mp4v:
13813     case FOURCC_MP4V:
13814       _codec ("MPEG-4 video");
13815       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13816           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13817       break;
13818     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13819     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13820       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13821       caps = gst_caps_new_simple ("video/x-msmpeg",
13822           "msmpegversion", G_TYPE_INT, 43, NULL);
13823       break;
13824     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13825       _codec ("DivX 3");
13826       caps = gst_caps_new_simple ("video/x-divx",
13827           "divxversion", G_TYPE_INT, 3, NULL);
13828       break;
13829     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13830     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13831       _codec ("DivX 4");
13832       caps = gst_caps_new_simple ("video/x-divx",
13833           "divxversion", G_TYPE_INT, 4, NULL);
13834       break;
13835     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13836       _codec ("DivX 5");
13837       caps = gst_caps_new_simple ("video/x-divx",
13838           "divxversion", G_TYPE_INT, 5, NULL);
13839       break;
13840
13841     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13842       _codec ("FFV1");
13843       caps = gst_caps_new_simple ("video/x-ffv",
13844           "ffvversion", G_TYPE_INT, 1, NULL);
13845       break;
13846
13847     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13848     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13849     case FOURCC_XVID:
13850     case FOURCC_xvid:
13851     case FOURCC_FMP4:
13852     case FOURCC_fmp4:
13853     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13854       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13855           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13856       _codec ("MPEG-4");
13857       break;
13858
13859     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13860       _codec ("Cinepak");
13861       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13862       break;
13863     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13864       _codec ("Apple QuickDraw");
13865       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13866       break;
13867     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13868       _codec ("Apple video");
13869       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13870       break;
13871     case FOURCC_H264:
13872     case FOURCC_avc1:
13873       _codec ("H.264 / AVC");
13874       caps = gst_caps_new_simple ("video/x-h264",
13875           "stream-format", G_TYPE_STRING, "avc",
13876           "alignment", G_TYPE_STRING, "au", NULL);
13877       break;
13878     case FOURCC_avc3:
13879       _codec ("H.264 / AVC");
13880       caps = gst_caps_new_simple ("video/x-h264",
13881           "stream-format", G_TYPE_STRING, "avc3",
13882           "alignment", G_TYPE_STRING, "au", NULL);
13883       break;
13884     case FOURCC_H265:
13885     case FOURCC_hvc1:
13886       _codec ("H.265 / HEVC");
13887       caps = gst_caps_new_simple ("video/x-h265",
13888           "stream-format", G_TYPE_STRING, "hvc1",
13889           "alignment", G_TYPE_STRING, "au", NULL);
13890       break;
13891     case FOURCC_hev1:
13892       _codec ("H.265 / HEVC");
13893       caps = gst_caps_new_simple ("video/x-h265",
13894           "stream-format", G_TYPE_STRING, "hev1",
13895           "alignment", G_TYPE_STRING, "au", NULL);
13896       break;
13897     case FOURCC_rle_:
13898       _codec ("Run-length encoding");
13899       caps = gst_caps_new_simple ("video/x-rle",
13900           "layout", G_TYPE_STRING, "quicktime", NULL);
13901       break;
13902     case FOURCC_WRLE:
13903       _codec ("Run-length encoding");
13904       caps = gst_caps_new_simple ("video/x-rle",
13905           "layout", G_TYPE_STRING, "microsoft", NULL);
13906       break;
13907     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13908     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13909       _codec ("Indeo Video 3");
13910       caps = gst_caps_new_simple ("video/x-indeo",
13911           "indeoversion", G_TYPE_INT, 3, NULL);
13912       break;
13913     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13914     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13915       _codec ("Intel Video 4");
13916       caps = gst_caps_new_simple ("video/x-indeo",
13917           "indeoversion", G_TYPE_INT, 4, NULL);
13918       break;
13919     case FOURCC_dvcp:
13920     case FOURCC_dvc_:
13921     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13922     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13923     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13924     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13925     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13926     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13927       _codec ("DV Video");
13928       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13929           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13930       break;
13931     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13932     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13933       _codec ("DVCPro50 Video");
13934       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13935           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13936       break;
13937     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13938     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13939       _codec ("DVCProHD Video");
13940       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13941           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13942       break;
13943     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13944       _codec ("Apple Graphics (SMC)");
13945       caps = gst_caps_new_empty_simple ("video/x-smc");
13946       break;
13947     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13948       _codec ("VP3");
13949       caps = gst_caps_new_empty_simple ("video/x-vp3");
13950       break;
13951     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13952       _codec ("VP6 Flash");
13953       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13954       break;
13955     case FOURCC_XiTh:
13956       _codec ("Theora");
13957       caps = gst_caps_new_empty_simple ("video/x-theora");
13958       /* theora uses one byte of padding in the data stream because it does not
13959        * allow 0 sized packets while theora does */
13960       entry->padding = 1;
13961       break;
13962     case FOURCC_drac:
13963       _codec ("Dirac");
13964       caps = gst_caps_new_empty_simple ("video/x-dirac");
13965       break;
13966     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13967       _codec ("TIFF still images");
13968       caps = gst_caps_new_empty_simple ("image/tiff");
13969       break;
13970     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13971       _codec ("Apple Intermediate Codec");
13972       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13973       break;
13974     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13975       _codec ("AVID DNxHD");
13976       caps = gst_caps_from_string ("video/x-dnxhd");
13977       break;
13978     case FOURCC_VP80:
13979     case FOURCC_vp08:
13980       _codec ("On2 VP8");
13981       caps = gst_caps_from_string ("video/x-vp8");
13982       break;
13983     case FOURCC_vp09:
13984       _codec ("Google VP9");
13985       caps = gst_caps_from_string ("video/x-vp9");
13986       break;
13987     case FOURCC_apcs:
13988       _codec ("Apple ProRes LT");
13989       caps =
13990           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13991           NULL);
13992       break;
13993     case FOURCC_apch:
13994       _codec ("Apple ProRes HQ");
13995       caps =
13996           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13997           NULL);
13998       break;
13999     case FOURCC_apcn:
14000       _codec ("Apple ProRes");
14001       caps =
14002           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14003           "standard", NULL);
14004       break;
14005     case FOURCC_apco:
14006       _codec ("Apple ProRes Proxy");
14007       caps =
14008           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14009           "proxy", NULL);
14010       break;
14011     case FOURCC_ap4h:
14012       _codec ("Apple ProRes 4444");
14013       caps =
14014           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14015           "4444", NULL);
14016       break;
14017     case FOURCC_ap4x:
14018       _codec ("Apple ProRes 4444 XQ");
14019       caps =
14020           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14021           "4444xq", NULL);
14022       break;
14023     case FOURCC_cfhd:
14024       _codec ("GoPro CineForm");
14025       caps = gst_caps_from_string ("video/x-cineform");
14026       break;
14027     case FOURCC_vc_1:
14028     case FOURCC_ovc1:
14029       _codec ("VC-1");
14030       caps = gst_caps_new_simple ("video/x-wmv",
14031           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14032       break;
14033     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14034     default:
14035     {
14036       caps = _get_unknown_codec_name ("video", fourcc);
14037       break;
14038     }
14039   }
14040
14041   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14042     GstVideoInfo info;
14043
14044     gst_video_info_init (&info);
14045     gst_video_info_set_format (&info, format, entry->width, entry->height);
14046
14047     caps = gst_video_info_to_caps (&info);
14048     *codec_name = gst_pb_utils_get_codec_description (caps);
14049
14050     /* enable clipping for raw video streams */
14051     stream->need_clip = TRUE;
14052     stream->alignment = 32;
14053   }
14054
14055   return caps;
14056 }
14057
14058 static guint
14059 round_up_pow2 (guint n)
14060 {
14061   n = n - 1;
14062   n = n | (n >> 1);
14063   n = n | (n >> 2);
14064   n = n | (n >> 4);
14065   n = n | (n >> 8);
14066   n = n | (n >> 16);
14067   return n + 1;
14068 }
14069
14070 static GstCaps *
14071 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14072     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14073     int len, gchar ** codec_name)
14074 {
14075   GstCaps *caps;
14076   const GstStructure *s;
14077   const gchar *name;
14078   gint endian = 0;
14079   GstAudioFormat format = 0;
14080   gint depth;
14081
14082   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14083
14084   depth = entry->bytes_per_packet * 8;
14085
14086   switch (fourcc) {
14087     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14088     case FOURCC_raw_:
14089       /* 8-bit audio is unsigned */
14090       if (depth == 8)
14091         format = GST_AUDIO_FORMAT_U8;
14092       /* otherwise it's signed and big-endian just like 'twos' */
14093     case FOURCC_twos:
14094       endian = G_BIG_ENDIAN;
14095       /* fall-through */
14096     case FOURCC_sowt:
14097     {
14098       gchar *str;
14099
14100       if (!endian)
14101         endian = G_LITTLE_ENDIAN;
14102
14103       if (!format)
14104         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14105
14106       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14107       _codec (str);
14108       g_free (str);
14109
14110       caps = gst_caps_new_simple ("audio/x-raw",
14111           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14112           "layout", G_TYPE_STRING, "interleaved", NULL);
14113       stream->alignment = GST_ROUND_UP_8 (depth);
14114       stream->alignment = round_up_pow2 (stream->alignment);
14115       break;
14116     }
14117     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14118       _codec ("Raw 64-bit floating-point audio");
14119       caps = gst_caps_new_simple ("audio/x-raw",
14120           "format", G_TYPE_STRING, "F64BE",
14121           "layout", G_TYPE_STRING, "interleaved", NULL);
14122       stream->alignment = 8;
14123       break;
14124     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14125       _codec ("Raw 32-bit floating-point audio");
14126       caps = gst_caps_new_simple ("audio/x-raw",
14127           "format", G_TYPE_STRING, "F32BE",
14128           "layout", G_TYPE_STRING, "interleaved", NULL);
14129       stream->alignment = 4;
14130       break;
14131     case FOURCC_in24:
14132       _codec ("Raw 24-bit PCM audio");
14133       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14134        * endian later */
14135       caps = gst_caps_new_simple ("audio/x-raw",
14136           "format", G_TYPE_STRING, "S24BE",
14137           "layout", G_TYPE_STRING, "interleaved", NULL);
14138       stream->alignment = 4;
14139       break;
14140     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14141       _codec ("Raw 32-bit PCM audio");
14142       caps = gst_caps_new_simple ("audio/x-raw",
14143           "format", G_TYPE_STRING, "S32BE",
14144           "layout", G_TYPE_STRING, "interleaved", NULL);
14145       stream->alignment = 4;
14146       break;
14147     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14148       _codec ("Raw 16-bit PCM audio");
14149       caps = gst_caps_new_simple ("audio/x-raw",
14150           "format", G_TYPE_STRING, "S16LE",
14151           "layout", G_TYPE_STRING, "interleaved", NULL);
14152       stream->alignment = 2;
14153       break;
14154     case FOURCC_ulaw:
14155       _codec ("Mu-law audio");
14156       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14157       break;
14158     case FOURCC_alaw:
14159       _codec ("A-law audio");
14160       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14161       break;
14162     case 0x0200736d:
14163     case 0x6d730002:
14164       _codec ("Microsoft ADPCM");
14165       /* Microsoft ADPCM-ACM code 2 */
14166       caps = gst_caps_new_simple ("audio/x-adpcm",
14167           "layout", G_TYPE_STRING, "microsoft", NULL);
14168       break;
14169     case 0x1100736d:
14170     case 0x6d730011:
14171       _codec ("DVI/IMA ADPCM");
14172       caps = gst_caps_new_simple ("audio/x-adpcm",
14173           "layout", G_TYPE_STRING, "dvi", NULL);
14174       break;
14175     case 0x1700736d:
14176     case 0x6d730017:
14177       _codec ("DVI/Intel IMA ADPCM");
14178       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14179       caps = gst_caps_new_simple ("audio/x-adpcm",
14180           "layout", G_TYPE_STRING, "quicktime", NULL);
14181       break;
14182     case 0x5500736d:
14183     case 0x6d730055:
14184       /* MPEG layer 3, CBR only (pre QT4.1) */
14185     case FOURCC__mp3:
14186       _codec ("MPEG-1 layer 3");
14187       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14188       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14189           "mpegversion", G_TYPE_INT, 1, NULL);
14190       break;
14191     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14192       _codec ("MPEG-1 layer 2");
14193       /* MPEG layer 2 */
14194       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14195           "mpegversion", G_TYPE_INT, 1, NULL);
14196       break;
14197     case 0x20736d:
14198     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14199       _codec ("EAC-3 audio");
14200       caps = gst_caps_new_simple ("audio/x-eac3",
14201           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14202       entry->sampled = TRUE;
14203       break;
14204     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14205     case FOURCC_ac_3:
14206       _codec ("AC-3 audio");
14207       caps = gst_caps_new_simple ("audio/x-ac3",
14208           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14209       entry->sampled = TRUE;
14210       break;
14211     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14212     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14213       _codec ("DTS audio");
14214       caps = gst_caps_new_simple ("audio/x-dts",
14215           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14216       entry->sampled = TRUE;
14217       break;
14218     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14219     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14220       _codec ("DTS-HD audio");
14221       caps = gst_caps_new_simple ("audio/x-dts",
14222           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14223       entry->sampled = TRUE;
14224       break;
14225     case FOURCC_MAC3:
14226       _codec ("MACE-3");
14227       caps = gst_caps_new_simple ("audio/x-mace",
14228           "maceversion", G_TYPE_INT, 3, NULL);
14229       break;
14230     case FOURCC_MAC6:
14231       _codec ("MACE-6");
14232       caps = gst_caps_new_simple ("audio/x-mace",
14233           "maceversion", G_TYPE_INT, 6, NULL);
14234       break;
14235     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14236       /* ogg/vorbis */
14237       caps = gst_caps_new_empty_simple ("application/ogg");
14238       break;
14239     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14240       _codec ("DV audio");
14241       caps = gst_caps_new_empty_simple ("audio/x-dv");
14242       break;
14243     case FOURCC_mp4a:
14244       _codec ("MPEG-4 AAC audio");
14245       caps = gst_caps_new_simple ("audio/mpeg",
14246           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14247           "stream-format", G_TYPE_STRING, "raw", NULL);
14248       break;
14249     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14250       _codec ("QDesign Music");
14251       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14252       break;
14253     case FOURCC_QDM2:
14254       _codec ("QDesign Music v.2");
14255       /* FIXME: QDesign music version 2 (no constant) */
14256       if (FALSE && data) {
14257         caps = gst_caps_new_simple ("audio/x-qdm2",
14258             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14259             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14260             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14261       } else {
14262         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14263       }
14264       break;
14265     case FOURCC_agsm:
14266       _codec ("GSM audio");
14267       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14268       break;
14269     case FOURCC_samr:
14270       _codec ("AMR audio");
14271       caps = gst_caps_new_empty_simple ("audio/AMR");
14272       break;
14273     case FOURCC_sawb:
14274       _codec ("AMR-WB audio");
14275       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14276       break;
14277     case FOURCC_ima4:
14278       _codec ("Quicktime IMA ADPCM");
14279       caps = gst_caps_new_simple ("audio/x-adpcm",
14280           "layout", G_TYPE_STRING, "quicktime", NULL);
14281       break;
14282     case FOURCC_alac:
14283       _codec ("Apple lossless audio");
14284       caps = gst_caps_new_empty_simple ("audio/x-alac");
14285       break;
14286     case FOURCC_fLaC:
14287       _codec ("Free Lossless Audio Codec");
14288       caps = gst_caps_new_simple ("audio/x-flac",
14289           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14290       break;
14291     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14292       _codec ("QualComm PureVoice");
14293       caps = gst_caps_from_string ("audio/qcelp");
14294       break;
14295     case FOURCC_wma_:
14296     case FOURCC_owma:
14297       _codec ("WMA");
14298       caps = gst_caps_new_empty_simple ("audio/x-wma");
14299       break;
14300     case FOURCC_opus:
14301       _codec ("Opus");
14302       caps = gst_caps_new_empty_simple ("audio/x-opus");
14303       break;
14304     case FOURCC_lpcm:
14305     {
14306       guint32 flags = 0;
14307       guint32 depth = 0;
14308       guint32 width = 0;
14309       GstAudioFormat format;
14310       enum
14311       {
14312         FLAG_IS_FLOAT = 0x1,
14313         FLAG_IS_BIG_ENDIAN = 0x2,
14314         FLAG_IS_SIGNED = 0x4,
14315         FLAG_IS_PACKED = 0x8,
14316         FLAG_IS_ALIGNED_HIGH = 0x10,
14317         FLAG_IS_NON_INTERLEAVED = 0x20
14318       };
14319       _codec ("Raw LPCM audio");
14320
14321       if (data && len >= 36) {
14322         depth = QT_UINT32 (data + 24);
14323         flags = QT_UINT32 (data + 28);
14324         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14325       }
14326       if ((flags & FLAG_IS_FLOAT) == 0) {
14327         if (depth == 0)
14328           depth = 16;
14329         if (width == 0)
14330           width = 16;
14331         if ((flags & FLAG_IS_ALIGNED_HIGH))
14332           depth = width;
14333
14334         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14335             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14336             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14337         caps = gst_caps_new_simple ("audio/x-raw",
14338             "format", G_TYPE_STRING,
14339             format !=
14340             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14341             "UNKNOWN", "layout", G_TYPE_STRING,
14342             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14343             "interleaved", NULL);
14344         stream->alignment = GST_ROUND_UP_8 (depth);
14345         stream->alignment = round_up_pow2 (stream->alignment);
14346       } else {
14347         if (width == 0)
14348           width = 32;
14349         if (width == 64) {
14350           if (flags & FLAG_IS_BIG_ENDIAN)
14351             format = GST_AUDIO_FORMAT_F64BE;
14352           else
14353             format = GST_AUDIO_FORMAT_F64LE;
14354         } else {
14355           if (flags & FLAG_IS_BIG_ENDIAN)
14356             format = GST_AUDIO_FORMAT_F32BE;
14357           else
14358             format = GST_AUDIO_FORMAT_F32LE;
14359         }
14360         caps = gst_caps_new_simple ("audio/x-raw",
14361             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14362             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14363             "non-interleaved" : "interleaved", NULL);
14364         stream->alignment = width / 8;
14365       }
14366       break;
14367     }
14368     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14369       /* ? */
14370     default:
14371     {
14372       caps = _get_unknown_codec_name ("audio", fourcc);
14373       break;
14374     }
14375   }
14376
14377   if (caps) {
14378     GstCaps *templ_caps =
14379         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14380     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14381     gst_caps_unref (caps);
14382     gst_caps_unref (templ_caps);
14383     caps = intersection;
14384   }
14385
14386   /* enable clipping for raw audio streams */
14387   s = gst_caps_get_structure (caps, 0);
14388   name = gst_structure_get_name (s);
14389   if (g_str_has_prefix (name, "audio/x-raw")) {
14390     stream->need_clip = TRUE;
14391     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14392     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14393   }
14394   return caps;
14395 }
14396
14397 static GstCaps *
14398 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14399     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14400     const guint8 * stsd_entry_data, gchar ** codec_name)
14401 {
14402   GstCaps *caps;
14403
14404   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14405
14406   switch (fourcc) {
14407     case FOURCC_mp4s:
14408       _codec ("DVD subtitle");
14409       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14410       stream->need_process = TRUE;
14411       break;
14412     case FOURCC_text:
14413       _codec ("Quicktime timed text");
14414       goto text;
14415     case FOURCC_tx3g:
14416       _codec ("3GPP timed text");
14417     text:
14418       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14419           "utf8", NULL);
14420       /* actual text piece needs to be extracted */
14421       stream->need_process = TRUE;
14422       break;
14423     case FOURCC_stpp:
14424       _codec ("XML subtitles");
14425       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14426       break;
14427     default:
14428     {
14429       caps = _get_unknown_codec_name ("text", fourcc);
14430       break;
14431     }
14432   }
14433   return caps;
14434 }
14435
14436 static GstCaps *
14437 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14438     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14439     const guint8 * stsd_entry_data, gchar ** codec_name)
14440 {
14441   GstCaps *caps;
14442
14443   switch (fourcc) {
14444     case FOURCC_m1v:
14445       _codec ("MPEG 1 video");
14446       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14447           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14448       break;
14449     default:
14450       caps = NULL;
14451       break;
14452   }
14453   return caps;
14454 }
14455
14456 static void
14457 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14458     const gchar * system_id)
14459 {
14460   gint i;
14461
14462   if (!qtdemux->protection_system_ids)
14463     qtdemux->protection_system_ids =
14464         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14465   /* Check whether we already have an entry for this system ID. */
14466   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14467     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14468     if (g_ascii_strcasecmp (system_id, id) == 0) {
14469       return;
14470     }
14471   }
14472   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14473   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14474           -1));
14475 }