d4f4c99c710f18d7279a3229332210a966ee126b
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public
24  * License along with this library; if not, write to the
25  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 /**
30  * SECTION:element-qtdemux
31  *
32  * Demuxes a .mov file into raw or compressed audio and/or video streams.
33  *
34  * This element supports both push and pull-based scheduling, depending on the
35  * capabilities of the upstream elements.
36  *
37  * <refsect2>
38  * <title>Example launch line</title>
39  * |[
40  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
41  * ]| Play (parse and decode) a .mov file and try to output it to
42  * an automatically detected soundcard and videosink. If the MOV file contains
43  * compressed audio or video data, this will only work if you have the
44  * right decoder elements/plugins installed.
45  * </refsect2>
46  */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #include "gst/gst-i18n-plugin.h"
53
54 #include <glib/gprintf.h>
55 #include <gst/tag/tag.h>
56 #include <gst/audio/audio.h>
57 #include <gst/video/video.h>
58
59 #include "qtatomparser.h"
60 #include "qtdemux_types.h"
61 #include "qtdemux_dump.h"
62 #include "fourcc.h"
63 #include "descriptors.h"
64 #include "qtdemux_lang.h"
65 #include "qtdemux.h"
66 #include "qtpalette.h"
67
68 #include "gst/riff/riff-media.h"
69 #include "gst/riff/riff-read.h"
70
71 #include <gst/pbutils/pbutils.h>
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include <math.h>
78 #include <gst/math-compat.h>
79
80 #ifdef HAVE_ZLIB
81 # include <zlib.h>
82 #endif
83
84 /* max. size considered 'sane' for non-mdat atoms */
85 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
86
87 /* if the sample index is larger than this, something is likely wrong */
88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
89
90 /* For converting qt creation times to unix epoch times */
91 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
92 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
93 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
94     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
95
96 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
97
98 GST_DEBUG_CATEGORY (qtdemux_debug);
99
100 /*typedef struct _QtNode QtNode; */
101 typedef struct _QtDemuxSegment QtDemuxSegment;
102 typedef struct _QtDemuxSample QtDemuxSample;
103
104 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
105
106 /*struct _QtNode
107 {
108   guint32 type;
109   guint8 *data;
110   gint len;
111 };*/
112
113 struct _QtDemuxSample
114 {
115   guint32 size;
116   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
117   guint64 offset;
118   guint64 timestamp;            /* DTS In mov time */
119   guint32 duration;             /* In mov time */
120   gboolean keyframe;            /* TRUE when this packet is a keyframe */
121 };
122
123 /* Macros for converting to/from timescale */
124 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
125 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
126
127 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
128 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
129
130 /* timestamp is the DTS */
131 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
132 /* timestamp + offset is the PTS */
133 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
134 /* timestamp + duration - dts is the duration */
135 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
136
137 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
138
139 /*
140  * Quicktime has tracks and segments. A track is a continuous piece of
141  * multimedia content. The track is not always played from start to finish but
142  * instead, pieces of the track are 'cut out' and played in sequence. This is
143  * what the segments do.
144  *
145  * Inside the track we have keyframes (K) and delta frames. The track has its
146  * own timing, which starts from 0 and extends to end. The position in the track
147  * is called the media_time.
148  *
149  * The segments now describe the pieces that should be played from this track
150  * and are basically tuples of media_time/duration/rate entries. We can have
151  * multiple segments and they are all played after one another. An example:
152  *
153  * segment 1: media_time: 1 second, duration: 1 second, rate 1
154  * segment 2: media_time: 3 second, duration: 2 second, rate 2
155  *
156  * To correctly play back this track, one must play: 1 second of media starting
157  * from media_time 1 followed by 2 seconds of media starting from media_time 3
158  * at a rate of 2.
159  *
160  * Each of the segments will be played at a specific time, the first segment at
161  * time 0, the second one after the duration of the first one, etc.. Note that
162  * the time in resulting playback is not identical to the media_time of the
163  * track anymore.
164  *
165  * Visually, assuming the track has 4 second of media_time:
166  *
167  *                (a)                   (b)          (c)              (d)
168  *         .-----------------------------------------------------------.
169  * track:  | K.....K.........K........K.......K.......K...........K... |
170  *         '-----------------------------------------------------------'
171  *         0              1              2              3              4
172  *           .------------^              ^   .----------^              ^
173  *          /              .-------------'  /       .------------------'
174  *         /              /          .-----'       /
175  *         .--------------.         .--------------.
176  *         | segment 1    |         | segment 2    |
177  *         '--------------'         '--------------'
178  *
179  * The challenge here is to cut out the right pieces of the track for each of
180  * the playback segments. This fortunately can easily be done with the SEGMENT
181  * events of GStreamer.
182  *
183  * For playback of segment 1, we need to provide the decoder with the keyframe
184  * (a), in the above figure, but we must instruct it only to output the decoded
185  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
186  * position set to the time of the segment: 0.
187  *
188  * We then proceed to push data from keyframe (a) to frame (b). The decoder
189  * decodes but clips all before media_time 1.
190  *
191  * After finishing a segment, we push out a new SEGMENT event with the clipping
192  * boundaries of the new data.
193  *
194  * This is a good usecase for the GStreamer accumulated SEGMENT events.
195  */
196
197 struct _QtDemuxSegment
198 {
199   /* global time and duration, all gst time */
200   GstClockTime time;
201   GstClockTime stop_time;
202   GstClockTime duration;
203   /* media time of trak, all gst time */
204   GstClockTime media_start;
205   GstClockTime media_stop;
206   gdouble rate;
207   /* Media start time in trak timescale units */
208   guint32 trak_media_start;
209 };
210
211 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
212
213 /* Used with fragmented MP4 files (mfra atom) */
214 typedef struct
215 {
216   GstClockTime ts;
217   guint64 moof_offset;
218 } QtDemuxRandomAccessEntry;
219
220 struct _QtDemuxStream
221 {
222   GstPad *pad;
223
224   /* stream type */
225   guint32 subtype;
226   GstCaps *caps;
227   guint32 fourcc;
228   gboolean sparse;
229
230   gboolean new_caps;
231   gboolean new_stream;          /* signals that a stream_start is required */
232   gboolean on_keyframe;         /* if this stream last pushed buffer was a
233                                  * keyframe. This is important to identify
234                                  * where to stop pushing buffers after a
235                                  * segment stop time */
236
237   /* if the stream has a redirect URI in its headers, we store it here */
238   gchar *redirect_uri;
239
240   /* track id */
241   guint track_id;
242
243   /* duration/scale */
244   guint64 duration;             /* in timescale */
245   guint32 timescale;
246
247   /* language */
248   gchar lang_id[4];             /* ISO 639-2T language code */
249
250   /* our samples */
251   guint32 n_samples;
252   QtDemuxSample *samples;
253   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
254   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
255                                    the framerate, in timescale units */
256   guint32 n_samples_moof;       /* sample count in a moof */
257   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
258                                  * the framerate of fragmented format stream */
259   guint32 offset_in_sample;
260   guint32 max_buffer_size;
261
262   /* if we use chunks or samples */
263   gboolean sampled;
264   guint padding;
265
266   /* video info */
267   gint width;
268   gint height;
269   /* aspect ratio */
270   gint display_width;
271   gint display_height;
272   gint par_w;
273   gint par_h;
274   /* Numerator/denominator framerate */
275   gint fps_n;
276   gint fps_d;
277   guint16 bits_per_sample;
278   guint16 color_table_id;
279   GstMemory *rgb8_palette;
280
281   /* audio info */
282   gdouble rate;
283   gint n_channels;
284   guint samples_per_packet;
285   guint samples_per_frame;
286   guint bytes_per_packet;
287   guint bytes_per_sample;
288   guint bytes_per_frame;
289   guint compression;
290
291   /* allocation */
292   gboolean use_allocator;
293   GstAllocator *allocator;
294   GstAllocationParams params;
295
296   /* when a discontinuity is pending */
297   gboolean discont;
298
299   /* list of buffers to push first */
300   GSList *buffers;
301
302   /* if we need to clip this buffer. This is only needed for uncompressed
303    * data */
304   gboolean need_clip;
305
306   /* buffer needs some custom processing, e.g. subtitles */
307   gboolean need_process;
308
309   /* current position */
310   guint32 segment_index;
311   guint32 sample_index;
312   GstClockTime time_position;   /* in gst time */
313   guint64 accumulated_base;
314
315   /* the Gst segment we are processing out, used for clipping */
316   GstSegment segment;
317
318   /* quicktime segments */
319   guint32 n_segments;
320   QtDemuxSegment *segments;
321   gboolean dummy_segment;
322   guint32 from_sample;
323   guint32 to_sample;
324
325   gboolean sent_eos;
326   GstTagList *pending_tags;
327   gboolean send_global_tags;
328
329   GstEvent *pending_event;
330
331   GstByteReader stco;
332   GstByteReader stsz;
333   GstByteReader stsc;
334   GstByteReader stts;
335   GstByteReader stss;
336   GstByteReader stps;
337   GstByteReader ctts;
338
339   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
340   gint64 stbl_index;
341   /* stco */
342   guint co_size;
343   GstByteReader co_chunk;
344   guint32 first_chunk;
345   guint32 current_chunk;
346   guint32 last_chunk;
347   guint32 samples_per_chunk;
348   guint32 stco_sample_index;
349   /* stsz */
350   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
351   /* stsc */
352   guint32 stsc_index;
353   guint32 n_samples_per_chunk;
354   guint32 stsc_chunk_index;
355   guint32 stsc_sample_index;
356   guint64 chunk_offset;
357   /* stts */
358   guint32 stts_index;
359   guint32 stts_samples;
360   guint32 n_sample_times;
361   guint32 stts_sample_index;
362   guint64 stts_time;
363   guint32 stts_duration;
364   /* stss */
365   gboolean stss_present;
366   guint32 n_sample_syncs;
367   guint32 stss_index;
368   /* stps */
369   gboolean stps_present;
370   guint32 n_sample_partial_syncs;
371   guint32 stps_index;
372   QtDemuxRandomAccessEntry *ra_entries;
373   guint n_ra_entries;
374
375   const QtDemuxRandomAccessEntry *pending_seek;
376
377   /* ctts */
378   gboolean ctts_present;
379   guint32 n_composition_times;
380   guint32 ctts_index;
381   guint32 ctts_sample_index;
382   guint32 ctts_count;
383   gint32 ctts_soffset;
384
385   /* cslg */
386   guint32 cslg_shift;
387
388   /* fragmented */
389   gboolean parsed_trex;
390   guint32 def_sample_duration;
391   guint32 def_sample_size;
392   guint32 def_sample_flags;
393
394   gboolean disabled;
395
396   /* stereoscopic video streams */
397   GstVideoMultiviewMode multiview_mode;
398   GstVideoMultiviewFlags multiview_flags;
399
400   /* protected streams */
401   gboolean protected;
402   guint32 protection_scheme_type;
403   guint32 protection_scheme_version;
404   gpointer protection_scheme_info;      /* specific to the protection scheme */
405   GQueue protection_scheme_event_queue;
406 };
407
408 /* Contains properties and cryptographic info for a set of samples from a
409  * track protected using Common Encryption (cenc) */
410 struct _QtDemuxCencSampleSetInfo
411 {
412   GstStructure *default_properties;
413
414   /* @crypto_info holds one GstStructure per sample */
415   GPtrArray *crypto_info;
416 };
417
418 enum QtDemuxState
419 {
420   QTDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
421   QTDEMUX_STATE_HEADER,         /* Parsing the header */
422   QTDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
423   QTDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
424 };
425
426 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
427 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
428     guint32 fourcc, GstByteReader * parser);
429 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
430 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
431     guint32 fourcc, GstByteReader * parser);
432
433 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
434
435 static GstStaticPadTemplate gst_qtdemux_sink_template =
436     GST_STATIC_PAD_TEMPLATE ("sink",
437     GST_PAD_SINK,
438     GST_PAD_ALWAYS,
439     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
440         "application/x-3gp")
441     );
442
443 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
444 GST_STATIC_PAD_TEMPLATE ("video_%u",
445     GST_PAD_SRC,
446     GST_PAD_SOMETIMES,
447     GST_STATIC_CAPS_ANY);
448
449 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
450 GST_STATIC_PAD_TEMPLATE ("audio_%u",
451     GST_PAD_SRC,
452     GST_PAD_SOMETIMES,
453     GST_STATIC_CAPS_ANY);
454
455 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
456 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
457     GST_PAD_SRC,
458     GST_PAD_SOMETIMES,
459     GST_STATIC_CAPS_ANY);
460
461 #define gst_qtdemux_parent_class parent_class
462 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
463
464 static void gst_qtdemux_dispose (GObject * object);
465
466 static guint32
467 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
468     GstClockTime media_time);
469 static guint32
470 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
471     QtDemuxStream * str, gint64 media_offset);
472
473 #if 0
474 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
475 static GstIndex *gst_qtdemux_get_index (GstElement * element);
476 #endif
477 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
478     GstStateChange transition);
479 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
480 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
481     GstObject * parent, GstPadMode mode, gboolean active);
482
483 static void gst_qtdemux_loop (GstPad * pad);
484 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
485     GstBuffer * inbuf);
486 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
487     GstEvent * event);
488 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
489 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
490     QtDemuxStream * stream);
491 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
492     gboolean force);
493
494 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
495     const guint8 * buffer, guint length);
496 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
497     const guint8 * buffer, guint length);
498 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
499 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
500     GNode * udta);
501
502 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
503     QtDemuxStream * stream, GNode * esds, GstTagList * list);
504 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
505     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
506     gchar ** codec_name);
507 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
508     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
509     gchar ** codec_name);
510 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
511     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
512     gchar ** codec_name);
513 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
514     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
515     gchar ** codec_name);
516
517 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
518     QtDemuxStream * stream, guint32 n);
519 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
520 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
521     QtDemuxStream * stream);
522 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
523     QtDemuxStream * stream);
524 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
525 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
526 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
527     QtDemuxStream * stream);
528 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
529     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
530 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
531     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
532     GstClockTime * _start, GstClockTime * _stop);
533 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
534     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
535
536 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
537 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
538
539 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
540
541 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
542     QtDemuxStream * stream, guint sample_index);
543 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
544     const gchar * id);
545 static void qtdemux_gst_structure_free (GstStructure * gststructure);
546
547 static void
548 gst_qtdemux_class_init (GstQTDemuxClass * klass)
549 {
550   GObjectClass *gobject_class;
551   GstElementClass *gstelement_class;
552
553   gobject_class = (GObjectClass *) klass;
554   gstelement_class = (GstElementClass *) klass;
555
556   parent_class = g_type_class_peek_parent (klass);
557
558   gobject_class->dispose = gst_qtdemux_dispose;
559
560   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
561 #if 0
562   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
563   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
564 #endif
565
566   gst_tag_register_musicbrainz_tags ();
567
568   gst_element_class_add_static_pad_template (gstelement_class,
569       &gst_qtdemux_sink_template);
570   gst_element_class_add_static_pad_template (gstelement_class,
571       &gst_qtdemux_videosrc_template);
572   gst_element_class_add_static_pad_template (gstelement_class,
573       &gst_qtdemux_audiosrc_template);
574   gst_element_class_add_static_pad_template (gstelement_class,
575       &gst_qtdemux_subsrc_template);
576   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
577       "Codec/Demuxer",
578       "Demultiplex a QuickTime file into audio and video streams",
579       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
580
581   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
582
583 }
584
585 static void
586 gst_qtdemux_init (GstQTDemux * qtdemux)
587 {
588   qtdemux->sinkpad =
589       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
590   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
591   gst_pad_set_activatemode_function (qtdemux->sinkpad,
592       qtdemux_sink_activate_mode);
593   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
594   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
595   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
596
597   qtdemux->state = QTDEMUX_STATE_INITIAL;
598   qtdemux->pullbased = FALSE;
599   qtdemux->posted_redirect = FALSE;
600   qtdemux->neededbytes = 16;
601   qtdemux->todrop = 0;
602   qtdemux->adapter = gst_adapter_new ();
603   qtdemux->offset = 0;
604   qtdemux->first_mdat = -1;
605   qtdemux->got_moov = FALSE;
606   qtdemux->mdatoffset = -1;
607   qtdemux->mdatbuffer = NULL;
608   qtdemux->restoredata_buffer = NULL;
609   qtdemux->restoredata_offset = -1;
610   qtdemux->fragment_start = -1;
611   qtdemux->fragment_start_offset = -1;
612   qtdemux->media_caps = NULL;
613   qtdemux->exposed = FALSE;
614   qtdemux->mss_mode = FALSE;
615   qtdemux->pending_newsegment = NULL;
616   qtdemux->upstream_format_is_time = FALSE;
617   qtdemux->have_group_id = FALSE;
618   qtdemux->group_id = G_MAXUINT;
619   qtdemux->cenc_aux_info_offset = 0;
620   qtdemux->cenc_aux_info_sizes = NULL;
621   qtdemux->cenc_aux_sample_count = 0;
622   qtdemux->protection_system_ids = NULL;
623   g_queue_init (&qtdemux->protection_event_queue);
624   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
625   qtdemux->flowcombiner = gst_flow_combiner_new ();
626
627   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
628 }
629
630 static void
631 gst_qtdemux_dispose (GObject * object)
632 {
633   GstQTDemux *qtdemux = GST_QTDEMUX (object);
634
635   if (qtdemux->adapter) {
636     g_object_unref (G_OBJECT (qtdemux->adapter));
637     qtdemux->adapter = NULL;
638   }
639   gst_flow_combiner_free (qtdemux->flowcombiner);
640   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
641       NULL);
642   g_queue_clear (&qtdemux->protection_event_queue);
643
644   g_free (qtdemux->cenc_aux_info_sizes);
645   qtdemux->cenc_aux_info_sizes = NULL;
646
647   G_OBJECT_CLASS (parent_class)->dispose (object);
648 }
649
650 static void
651 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
652 {
653   if (qtdemux->posted_redirect) {
654     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
655         (_("This file contains no playable streams.")),
656         ("no known streams found, a redirect message has been posted"));
657   } else {
658     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
659         (_("This file contains no playable streams.")),
660         ("no known streams found"));
661   }
662 }
663
664 static GstBuffer *
665 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
666 {
667   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
668       mem, size, 0, size, mem, free_func);
669 }
670
671 static GstFlowReturn
672 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
673     GstBuffer ** buf)
674 {
675   GstFlowReturn flow;
676   GstMapInfo map;
677   gsize bsize;
678
679   if (G_UNLIKELY (size == 0)) {
680     GstFlowReturn ret;
681     GstBuffer *tmp = NULL;
682
683     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
684     if (ret != GST_FLOW_OK)
685       return ret;
686
687     gst_buffer_map (tmp, &map, GST_MAP_READ);
688     size = QT_UINT32 (map.data);
689     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
690
691     gst_buffer_unmap (tmp, &map);
692     gst_buffer_unref (tmp);
693   }
694
695   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
696   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
697     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
698       /* we're pulling header but already got most interesting bits,
699        * so never mind the rest (e.g. tags) (that much) */
700       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
701           size);
702       return GST_FLOW_EOS;
703     } else {
704       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
705           (_("This file is invalid and cannot be played.")),
706           ("atom has bogus size %" G_GUINT64_FORMAT, size));
707       return GST_FLOW_ERROR;
708     }
709   }
710
711   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
712
713   if (G_UNLIKELY (flow != GST_FLOW_OK))
714     return flow;
715
716   bsize = gst_buffer_get_size (*buf);
717   /* Catch short reads - we don't want any partial atoms */
718   if (G_UNLIKELY (bsize < size)) {
719     GST_WARNING_OBJECT (qtdemux,
720         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
721     gst_buffer_unref (*buf);
722     *buf = NULL;
723     return GST_FLOW_EOS;
724   }
725
726   return flow;
727 }
728
729 #if 1
730 static gboolean
731 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
732     GstFormat src_format, gint64 src_value, GstFormat dest_format,
733     gint64 * dest_value)
734 {
735   gboolean res = TRUE;
736   QtDemuxStream *stream = gst_pad_get_element_private (pad);
737   gint32 index;
738
739   if (stream->subtype != FOURCC_vide) {
740     res = FALSE;
741     goto done;
742   }
743
744   switch (src_format) {
745     case GST_FORMAT_TIME:
746       switch (dest_format) {
747         case GST_FORMAT_BYTES:{
748           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
749           if (-1 == index) {
750             res = FALSE;
751             goto done;
752           }
753
754           *dest_value = stream->samples[index].offset;
755
756           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
757               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
758               GST_TIME_ARGS (src_value), *dest_value);
759           break;
760         }
761         default:
762           res = FALSE;
763           break;
764       }
765       break;
766     case GST_FORMAT_BYTES:
767       switch (dest_format) {
768         case GST_FORMAT_TIME:{
769           index =
770               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
771               stream, src_value);
772
773           if (-1 == index) {
774             res = FALSE;
775             goto done;
776           }
777
778           *dest_value =
779               QTSTREAMTIME_TO_GSTTIME (stream,
780               stream->samples[index].timestamp);
781           GST_DEBUG_OBJECT (qtdemux,
782               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
783               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
784           break;
785         }
786         default:
787           res = FALSE;
788           break;
789       }
790       break;
791     default:
792       res = FALSE;
793       break;
794   }
795
796 done:
797   return res;
798 }
799 #endif
800
801 static gboolean
802 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
803 {
804   gboolean res = FALSE;
805
806   *duration = GST_CLOCK_TIME_NONE;
807
808   if (qtdemux->duration != 0 &&
809       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
810     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
811     res = TRUE;
812   } else {
813     *duration = GST_CLOCK_TIME_NONE;
814   }
815
816   return res;
817 }
818
819 static gboolean
820 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
821     GstQuery * query)
822 {
823   gboolean res = FALSE;
824   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
825
826   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
827
828   switch (GST_QUERY_TYPE (query)) {
829     case GST_QUERY_POSITION:{
830       GstFormat fmt;
831
832       gst_query_parse_position (query, &fmt, NULL);
833       if (fmt == GST_FORMAT_TIME
834           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
835         gst_query_set_position (query, GST_FORMAT_TIME,
836             qtdemux->segment.position);
837         res = TRUE;
838       }
839     }
840       break;
841     case GST_QUERY_DURATION:{
842       GstFormat fmt;
843
844       gst_query_parse_duration (query, &fmt, NULL);
845       if (fmt == GST_FORMAT_TIME) {
846         /* First try to query upstream */
847         res = gst_pad_query_default (pad, parent, query);
848         if (!res) {
849           GstClockTime duration;
850           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
851             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
852             res = TRUE;
853           }
854         }
855       }
856       break;
857     }
858     case GST_QUERY_CONVERT:{
859       GstFormat src_fmt, dest_fmt;
860       gint64 src_value, dest_value = 0;
861
862       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
863
864       res = gst_qtdemux_src_convert (qtdemux, pad,
865           src_fmt, src_value, dest_fmt, &dest_value);
866       if (res) {
867         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
868         res = TRUE;
869       }
870       break;
871     }
872     case GST_QUERY_FORMATS:
873       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
874       res = TRUE;
875       break;
876     case GST_QUERY_SEEKING:{
877       GstFormat fmt;
878       gboolean seekable;
879
880       /* try upstream first */
881       res = gst_pad_query_default (pad, parent, query);
882
883       if (!res) {
884         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
885         if (fmt == GST_FORMAT_TIME) {
886           GstClockTime duration;
887
888           gst_qtdemux_get_duration (qtdemux, &duration);
889           seekable = TRUE;
890           if (!qtdemux->pullbased) {
891             GstQuery *q;
892
893             /* we might be able with help from upstream */
894             seekable = FALSE;
895             q = gst_query_new_seeking (GST_FORMAT_BYTES);
896             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
897               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
898               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
899             }
900             gst_query_unref (q);
901           }
902           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
903           res = TRUE;
904         }
905       }
906       break;
907     }
908     case GST_QUERY_SEGMENT:
909     {
910       GstFormat format;
911       gint64 start, stop;
912
913       format = qtdemux->segment.format;
914
915       start =
916           gst_segment_to_stream_time (&qtdemux->segment, format,
917           qtdemux->segment.start);
918       if ((stop = qtdemux->segment.stop) == -1)
919         stop = qtdemux->segment.duration;
920       else
921         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
922
923       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
924       res = TRUE;
925       break;
926     }
927     default:
928       res = gst_pad_query_default (pad, parent, query);
929       break;
930   }
931
932   return res;
933 }
934
935 static void
936 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
937 {
938   if (G_LIKELY (stream->pad)) {
939     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
940         GST_DEBUG_PAD_NAME (stream->pad));
941
942     if (G_UNLIKELY (stream->pending_tags)) {
943       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
944           stream->pending_tags);
945       gst_pad_push_event (stream->pad,
946           gst_event_new_tag (stream->pending_tags));
947       stream->pending_tags = NULL;
948     }
949
950     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
951       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
952           qtdemux->tag_list);
953       gst_pad_push_event (stream->pad,
954           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
955       stream->send_global_tags = FALSE;
956     }
957   }
958 }
959
960 /* push event on all source pads; takes ownership of the event */
961 static void
962 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
963 {
964   guint n;
965   gboolean has_valid_stream = FALSE;
966   GstEventType etype = GST_EVENT_TYPE (event);
967
968   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
969       GST_EVENT_TYPE_NAME (event));
970
971   for (n = 0; n < qtdemux->n_streams; n++) {
972     GstPad *pad;
973     QtDemuxStream *stream = qtdemux->streams[n];
974     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
975
976     if ((pad = stream->pad)) {
977       has_valid_stream = TRUE;
978
979       if (etype == GST_EVENT_EOS) {
980         /* let's not send twice */
981         if (stream->sent_eos)
982           continue;
983         stream->sent_eos = TRUE;
984       }
985
986       gst_pad_push_event (pad, gst_event_ref (event));
987     }
988   }
989
990   gst_event_unref (event);
991
992   /* if it is EOS and there are no pads, post an error */
993   if (!has_valid_stream && etype == GST_EVENT_EOS) {
994     gst_qtdemux_post_no_playable_stream_error (qtdemux);
995   }
996 }
997
998 /* push a pending newsegment event, if any from the streaming thread */
999 static void
1000 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1001 {
1002   if (qtdemux->pending_newsegment) {
1003     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1004     qtdemux->pending_newsegment = NULL;
1005   }
1006 }
1007
1008 typedef struct
1009 {
1010   guint64 media_time;
1011 } FindData;
1012
1013 static gint
1014 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1015 {
1016   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1017     return 1;
1018   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1019     return 0;
1020
1021   return -1;
1022 }
1023
1024 /* find the index of the sample that includes the data for @media_time using a
1025  * binary search.  Only to be called in optimized cases of linear search below.
1026  *
1027  * Returns the index of the sample.
1028  */
1029 static guint32
1030 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1031     guint64 media_time)
1032 {
1033   QtDemuxSample *result;
1034   guint32 index;
1035
1036   /* convert media_time to mov format */
1037   media_time =
1038       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1039
1040   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1041       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1042       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1043
1044   if (G_LIKELY (result))
1045     index = result - str->samples;
1046   else
1047     index = 0;
1048
1049   return index;
1050 }
1051
1052
1053
1054 /* find the index of the sample that includes the data for @media_offset using a
1055  * linear search
1056  *
1057  * Returns the index of the sample.
1058  */
1059 static guint32
1060 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1061     QtDemuxStream * str, gint64 media_offset)
1062 {
1063   QtDemuxSample *result = str->samples;
1064   guint32 index = 0;
1065
1066   if (result == NULL || str->n_samples == 0)
1067     return -1;
1068
1069   if (media_offset == result->offset)
1070     return index;
1071
1072   result++;
1073   while (index < str->n_samples - 1) {
1074     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1075       goto parse_failed;
1076
1077     if (media_offset < result->offset)
1078       break;
1079
1080     index++;
1081     result++;
1082   }
1083   return index;
1084
1085   /* ERRORS */
1086 parse_failed:
1087   {
1088     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1089     return -1;
1090   }
1091 }
1092
1093 /* find the index of the sample that includes the data for @media_time using a
1094  * linear search, and keeping in mind that not all samples may have been parsed
1095  * yet.  If possible, it will delegate to binary search.
1096  *
1097  * Returns the index of the sample.
1098  */
1099 static guint32
1100 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1101     GstClockTime media_time)
1102 {
1103   guint32 index = 0;
1104   guint64 mov_time;
1105   QtDemuxSample *sample;
1106
1107   /* convert media_time to mov format */
1108   mov_time =
1109       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1110
1111   sample = str->samples;
1112   if (mov_time == sample->timestamp + sample->pts_offset)
1113     return index;
1114
1115   /* use faster search if requested time in already parsed range */
1116   sample = str->samples + str->stbl_index;
1117   if (str->stbl_index >= 0 &&
1118       mov_time <= (sample->timestamp + sample->pts_offset))
1119     return gst_qtdemux_find_index (qtdemux, str, media_time);
1120
1121   while (index < str->n_samples - 1) {
1122     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1123       goto parse_failed;
1124
1125     sample = str->samples + index + 1;
1126     if (mov_time < (sample->timestamp + sample->pts_offset))
1127       break;
1128
1129     index++;
1130   }
1131   return index;
1132
1133   /* ERRORS */
1134 parse_failed:
1135   {
1136     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1137     return -1;
1138   }
1139 }
1140
1141 /* find the index of the keyframe needed to decode the sample at @index
1142  * of stream @str.
1143  *
1144  * Returns the index of the keyframe.
1145  */
1146 static guint32
1147 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1148     guint32 index)
1149 {
1150   guint32 new_index = index;
1151
1152   if (index >= str->n_samples) {
1153     new_index = str->n_samples;
1154     goto beach;
1155   }
1156
1157   /* all keyframes, return index */
1158   if (str->all_keyframe) {
1159     new_index = index;
1160     goto beach;
1161   }
1162
1163   /* else go back until we have a keyframe */
1164   while (TRUE) {
1165     if (str->samples[new_index].keyframe)
1166       break;
1167
1168     if (new_index == 0)
1169       break;
1170
1171     new_index--;
1172   }
1173
1174 beach:
1175   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1176       "gave %u", index, new_index);
1177
1178   return new_index;
1179 }
1180
1181 /* find the segment for @time_position for @stream
1182  *
1183  * Returns the index of the segment containing @time_position.
1184  * Returns the last segment and sets the @eos variable to TRUE
1185  * if the time is beyond the end. @eos may be NULL
1186  */
1187 static guint32
1188 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1189     GstClockTime time_position)
1190 {
1191   gint i;
1192   guint32 seg_idx;
1193
1194   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1195       GST_TIME_ARGS (time_position));
1196
1197   seg_idx = -1;
1198   for (i = 0; i < stream->n_segments; i++) {
1199     QtDemuxSegment *segment = &stream->segments[i];
1200
1201     GST_LOG_OBJECT (stream->pad,
1202         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1203         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1204
1205     /* For the last segment we include stop_time in the last segment */
1206     if (i < stream->n_segments - 1) {
1207       if (segment->time <= time_position && time_position < segment->stop_time) {
1208         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1209         seg_idx = i;
1210         break;
1211       }
1212     } else {
1213       /* Last segment always matches */
1214       seg_idx = i;
1215       break;
1216     }
1217   }
1218   return seg_idx;
1219 }
1220
1221 /* move the stream @str to the sample position @index.
1222  *
1223  * Updates @str->sample_index and marks discontinuity if needed.
1224  */
1225 static void
1226 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1227     guint32 index)
1228 {
1229   /* no change needed */
1230   if (index == str->sample_index)
1231     return;
1232
1233   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1234       str->n_samples);
1235
1236   /* position changed, we have a discont */
1237   str->sample_index = index;
1238   str->offset_in_sample = 0;
1239   /* Each time we move in the stream we store the position where we are
1240    * starting from */
1241   str->from_sample = index;
1242   str->discont = TRUE;
1243 }
1244
1245 static void
1246 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1247     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1248 {
1249   guint64 min_offset;
1250   gint64 min_byte_offset = -1;
1251   gint n;
1252
1253   min_offset = desired_time;
1254
1255   /* for each stream, find the index of the sample in the segment
1256    * and move back to the previous keyframe. */
1257   for (n = 0; n < qtdemux->n_streams; n++) {
1258     QtDemuxStream *str;
1259     guint32 index, kindex;
1260     guint32 seg_idx;
1261     GstClockTime media_start;
1262     GstClockTime media_time;
1263     GstClockTime seg_time;
1264     QtDemuxSegment *seg;
1265     gboolean empty_segment = FALSE;
1266
1267     str = qtdemux->streams[n];
1268
1269     if (str->sparse && !use_sparse)
1270       continue;
1271
1272     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1273     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1274
1275     /* get segment and time in the segment */
1276     seg = &str->segments[seg_idx];
1277     seg_time = (desired_time - seg->time) * seg->rate;
1278
1279     while (QTSEGMENT_IS_EMPTY (seg)) {
1280       seg_time = 0;
1281       empty_segment = TRUE;
1282       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1283           seg_idx);
1284       seg_idx++;
1285       if (seg_idx == str->n_segments)
1286         break;
1287       seg = &str->segments[seg_idx];
1288     }
1289
1290     if (seg_idx == str->n_segments) {
1291       /* FIXME track shouldn't have the last segment as empty, but if it
1292        * happens we better handle it */
1293       continue;
1294     }
1295
1296     /* get the media time in the segment */
1297     media_start = seg->media_start + seg_time;
1298
1299     /* get the index of the sample with media time */
1300     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1301     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1302         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1303         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1304         empty_segment);
1305
1306     if (!empty_segment) {
1307       /* find previous keyframe */
1308       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1309
1310       /* if the keyframe is at a different position, we need to update the
1311        * requested seek time */
1312       if (index != kindex) {
1313         index = kindex;
1314
1315         /* get timestamp of keyframe */
1316         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1317         GST_DEBUG_OBJECT (qtdemux,
1318             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1319             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1320             str->samples[kindex].offset);
1321
1322         /* keyframes in the segment get a chance to change the
1323          * desired_offset. keyframes out of the segment are
1324          * ignored. */
1325         if (media_time >= seg->media_start) {
1326           GstClockTime seg_time;
1327
1328           /* this keyframe is inside the segment, convert back to
1329            * segment time */
1330           seg_time = (media_time - seg->media_start) + seg->time;
1331           if (seg_time < min_offset)
1332             min_offset = seg_time;
1333         }
1334       }
1335     }
1336
1337     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1338       min_byte_offset = str->samples[index].offset;
1339   }
1340
1341   if (key_time)
1342     *key_time = min_offset;
1343   if (key_offset)
1344     *key_offset = min_byte_offset;
1345 }
1346
1347 static gboolean
1348 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1349     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1350 {
1351   gboolean res;
1352
1353   g_return_val_if_fail (format != NULL, FALSE);
1354   g_return_val_if_fail (cur != NULL, FALSE);
1355   g_return_val_if_fail (stop != NULL, FALSE);
1356
1357   if (*format == GST_FORMAT_TIME)
1358     return TRUE;
1359
1360   res = TRUE;
1361   if (cur_type != GST_SEEK_TYPE_NONE)
1362     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1363   if (res && stop_type != GST_SEEK_TYPE_NONE)
1364     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1365
1366   if (res)
1367     *format = GST_FORMAT_TIME;
1368
1369   return res;
1370 }
1371
1372 /* perform seek in push based mode:
1373    find BYTE position to move to based on time and delegate to upstream
1374 */
1375 static gboolean
1376 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1377 {
1378   gdouble rate;
1379   GstFormat format;
1380   GstSeekFlags flags;
1381   GstSeekType cur_type, stop_type;
1382   gint64 cur, stop, key_cur;
1383   gboolean res;
1384   gint64 byte_cur;
1385   gint64 original_stop;
1386   guint32 seqnum;
1387
1388   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1389
1390   gst_event_parse_seek (event, &rate, &format, &flags,
1391       &cur_type, &cur, &stop_type, &stop);
1392   seqnum = gst_event_get_seqnum (event);
1393
1394   /* only forward streaming and seeking is possible */
1395   if (rate <= 0)
1396     goto unsupported_seek;
1397
1398   /* convert to TIME if needed and possible */
1399   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1400           stop_type, &stop))
1401     goto no_format;
1402
1403   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1404    * the original stop position to use when upstream pushes the new segment
1405    * for this seek */
1406   original_stop = stop;
1407   stop = -1;
1408
1409   /* find reasonable corresponding BYTE position,
1410    * also try to mind about keyframes, since we can not go back a bit for them
1411    * later on */
1412   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1413
1414   if (byte_cur == -1)
1415     goto abort_seek;
1416
1417   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1418       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1419       stop);
1420
1421   GST_OBJECT_LOCK (qtdemux);
1422   qtdemux->seek_offset = byte_cur;
1423   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1424     qtdemux->push_seek_start = cur;
1425   } else {
1426     qtdemux->push_seek_start = key_cur;
1427   }
1428
1429   if (stop_type == GST_SEEK_TYPE_NONE) {
1430     qtdemux->push_seek_stop = qtdemux->segment.stop;
1431   } else {
1432     qtdemux->push_seek_stop = original_stop;
1433   }
1434   GST_OBJECT_UNLOCK (qtdemux);
1435
1436   /* BYTE seek event */
1437   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1438       stop_type, stop);
1439   gst_event_set_seqnum (event, seqnum);
1440   res = gst_pad_push_event (qtdemux->sinkpad, event);
1441
1442   return res;
1443
1444   /* ERRORS */
1445 abort_seek:
1446   {
1447     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1448         "seek aborted.");
1449     return FALSE;
1450   }
1451 unsupported_seek:
1452   {
1453     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1454     return FALSE;
1455   }
1456 no_format:
1457   {
1458     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1459     return FALSE;
1460   }
1461 }
1462
1463 /* perform the seek.
1464  *
1465  * We set all segment_indexes in the streams to unknown and
1466  * adjust the time_position to the desired position. this is enough
1467  * to trigger a segment switch in the streaming thread to start
1468  * streaming from the desired position.
1469  *
1470  * Keyframe seeking is a little more complicated when dealing with
1471  * segments. Ideally we want to move to the previous keyframe in
1472  * the segment but there might not be a keyframe in the segment. In
1473  * fact, none of the segments could contain a keyframe. We take a
1474  * practical approach: seek to the previous keyframe in the segment,
1475  * if there is none, seek to the beginning of the segment.
1476  *
1477  * Called with STREAM_LOCK
1478  */
1479 static gboolean
1480 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1481     guint32 seqnum, GstSeekFlags flags)
1482 {
1483   gint64 desired_offset;
1484   gint n;
1485
1486   desired_offset = segment->position;
1487
1488   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1489       GST_TIME_ARGS (desired_offset));
1490
1491   /* may not have enough fragmented info to do this adjustment,
1492    * and we can't scan (and probably should not) at this time with
1493    * possibly flushing upstream */
1494   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1495     gint64 min_offset;
1496
1497     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1498     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1499         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1500     desired_offset = min_offset;
1501   }
1502
1503   /* and set all streams to the final position */
1504   gst_flow_combiner_reset (qtdemux->flowcombiner);
1505   qtdemux->segment_seqnum = seqnum;
1506   for (n = 0; n < qtdemux->n_streams; n++) {
1507     QtDemuxStream *stream = qtdemux->streams[n];
1508
1509     stream->time_position = desired_offset;
1510     stream->accumulated_base = 0;
1511     stream->sample_index = -1;
1512     stream->offset_in_sample = 0;
1513     stream->segment_index = -1;
1514     stream->sent_eos = FALSE;
1515
1516     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1517       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1518   }
1519   segment->position = desired_offset;
1520   segment->time = desired_offset;
1521   if (segment->rate >= 0) {
1522     segment->start = desired_offset;
1523
1524     /* we stop at the end */
1525     if (segment->stop == -1)
1526       segment->stop = segment->duration;
1527   } else {
1528     segment->stop = desired_offset;
1529   }
1530
1531   if (qtdemux->fragmented)
1532     qtdemux->fragmented_seek_pending = TRUE;
1533
1534   return TRUE;
1535 }
1536
1537 /* do a seek in pull based mode */
1538 static gboolean
1539 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1540 {
1541   gdouble rate;
1542   GstFormat format;
1543   GstSeekFlags flags;
1544   GstSeekType cur_type, stop_type;
1545   gint64 cur, stop;
1546   gboolean flush;
1547   gboolean update;
1548   GstSegment seeksegment;
1549   guint32 seqnum = 0;
1550   GstEvent *flush_event;
1551
1552   if (event) {
1553     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1554
1555     gst_event_parse_seek (event, &rate, &format, &flags,
1556         &cur_type, &cur, &stop_type, &stop);
1557     seqnum = gst_event_get_seqnum (event);
1558
1559     /* we have to have a format as the segment format. Try to convert
1560      * if not. */
1561     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1562             stop_type, &stop))
1563       goto no_format;
1564
1565     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1566   } else {
1567     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1568     flags = 0;
1569   }
1570
1571   flush = flags & GST_SEEK_FLAG_FLUSH;
1572
1573   /* stop streaming, either by flushing or by pausing the task */
1574   if (flush) {
1575     flush_event = gst_event_new_flush_start ();
1576     if (seqnum)
1577       gst_event_set_seqnum (flush_event, seqnum);
1578     /* unlock upstream pull_range */
1579     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1580     /* make sure out loop function exits */
1581     gst_qtdemux_push_event (qtdemux, flush_event);
1582   } else {
1583     /* non flushing seek, pause the task */
1584     gst_pad_pause_task (qtdemux->sinkpad);
1585   }
1586
1587   /* wait for streaming to finish */
1588   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1589
1590   /* copy segment, we need this because we still need the old
1591    * segment when we close the current segment. */
1592   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1593
1594   if (event) {
1595     /* configure the segment with the seek variables */
1596     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1597     gst_segment_do_seek (&seeksegment, rate, format, flags,
1598         cur_type, cur, stop_type, stop, &update);
1599   }
1600
1601   /* now do the seek, this actually never returns FALSE */
1602   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1603
1604   /* prepare for streaming again */
1605   if (flush) {
1606     flush_event = gst_event_new_flush_stop (TRUE);
1607     if (seqnum)
1608       gst_event_set_seqnum (flush_event, seqnum);
1609
1610     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1611     gst_qtdemux_push_event (qtdemux, flush_event);
1612   }
1613
1614   /* commit the new segment */
1615   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1616
1617   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1618     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1619         qtdemux->segment.format, qtdemux->segment.position);
1620     if (seqnum)
1621       gst_message_set_seqnum (msg, seqnum);
1622     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1623   }
1624
1625   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1626   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1627       qtdemux->sinkpad, NULL);
1628
1629   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1630
1631   return TRUE;
1632
1633   /* ERRORS */
1634 no_format:
1635   {
1636     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1637     return FALSE;
1638   }
1639 }
1640
1641 static gboolean
1642 qtdemux_ensure_index (GstQTDemux * qtdemux)
1643 {
1644   guint i;
1645
1646   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1647
1648   /* Build complete index */
1649   for (i = 0; i < qtdemux->n_streams; i++) {
1650     QtDemuxStream *stream = qtdemux->streams[i];
1651
1652     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1653       goto parse_error;
1654   }
1655   return TRUE;
1656
1657   /* ERRORS */
1658 parse_error:
1659   {
1660     GST_LOG_OBJECT (qtdemux,
1661         "Building complete index of stream %u for seeking failed!", i);
1662     return FALSE;
1663   }
1664 }
1665
1666 static gboolean
1667 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1668     GstEvent * event)
1669 {
1670   gboolean res = TRUE;
1671   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1672
1673   switch (GST_EVENT_TYPE (event)) {
1674     case GST_EVENT_SEEK:
1675     {
1676 #ifndef GST_DISABLE_GST_DEBUG
1677       GstClockTime ts = gst_util_get_timestamp ();
1678 #endif
1679
1680       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1681         /* seek should be handled by upstream, we might need to re-download fragments */
1682         GST_DEBUG_OBJECT (qtdemux,
1683             "let upstream handle seek for fragmented playback");
1684         goto upstream;
1685       }
1686
1687       /* Build complete index for seeking;
1688        * if not a fragmented file at least */
1689       if (!qtdemux->fragmented)
1690         if (!qtdemux_ensure_index (qtdemux))
1691           goto index_failed;
1692 #ifndef GST_DISABLE_GST_DEBUG
1693       ts = gst_util_get_timestamp () - ts;
1694       GST_INFO_OBJECT (qtdemux,
1695           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1696 #endif
1697     }
1698       if (qtdemux->pullbased) {
1699         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1700       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1701         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1702         res = TRUE;
1703       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1704           && !qtdemux->fragmented) {
1705         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1706       } else {
1707         GST_DEBUG_OBJECT (qtdemux,
1708             "ignoring seek in push mode in current state");
1709         res = FALSE;
1710       }
1711       gst_event_unref (event);
1712       break;
1713     case GST_EVENT_QOS:
1714     case GST_EVENT_NAVIGATION:
1715       res = FALSE;
1716       gst_event_unref (event);
1717       break;
1718     default:
1719     upstream:
1720       res = gst_pad_event_default (pad, parent, event);
1721       break;
1722   }
1723
1724 done:
1725   return res;
1726
1727   /* ERRORS */
1728 index_failed:
1729   {
1730     GST_ERROR_OBJECT (qtdemux, "Index failed");
1731     gst_event_unref (event);
1732     res = FALSE;
1733     goto done;
1734   }
1735 }
1736
1737 /* stream/index return sample that is min/max w.r.t. byte position,
1738  * time is min/max w.r.t. time of samples,
1739  * the latter need not be time of the former sample */
1740 static void
1741 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1742     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1743 {
1744   gint i, n, index;
1745   gint64 time, min_time;
1746   QtDemuxStream *stream;
1747
1748   min_time = -1;
1749   stream = NULL;
1750   index = -1;
1751
1752   for (n = 0; n < qtdemux->n_streams; ++n) {
1753     QtDemuxStream *str;
1754     gint inc;
1755     gboolean set_sample;
1756
1757     str = qtdemux->streams[n];
1758     set_sample = !set;
1759
1760     if (fw) {
1761       i = 0;
1762       inc = 1;
1763     } else {
1764       i = str->n_samples - 1;
1765       inc = -1;
1766     }
1767
1768     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1769       if (str->samples[i].size == 0)
1770         continue;
1771
1772       if (fw && (str->samples[i].offset < byte_pos))
1773         continue;
1774
1775       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1776         continue;
1777
1778       /* move stream to first available sample */
1779       if (set) {
1780         gst_qtdemux_move_stream (qtdemux, str, i);
1781         set_sample = TRUE;
1782       }
1783
1784       /* avoid index from sparse streams since they might be far away */
1785       if (!str->sparse) {
1786         /* determine min/max time */
1787         time = QTSAMPLE_PTS (str, &str->samples[i]);
1788         if (min_time == -1 || (!fw && time > min_time) ||
1789             (fw && time < min_time)) {
1790           min_time = time;
1791         }
1792
1793         /* determine stream with leading sample, to get its position */
1794         if (!stream ||
1795             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1796             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1797           stream = str;
1798           index = i;
1799         }
1800       }
1801       break;
1802     }
1803
1804     /* no sample for this stream, mark eos */
1805     if (!set_sample)
1806       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1807   }
1808
1809   if (_time)
1810     *_time = min_time;
1811   if (_stream)
1812     *_stream = stream;
1813   if (_index)
1814     *_index = index;
1815 }
1816
1817 static QtDemuxStream *
1818 _create_stream (void)
1819 {
1820   QtDemuxStream *stream;
1821
1822   stream = g_new0 (QtDemuxStream, 1);
1823   /* new streams always need a discont */
1824   stream->discont = TRUE;
1825   /* we enable clipping for raw audio/video streams */
1826   stream->need_clip = FALSE;
1827   stream->need_process = FALSE;
1828   stream->segment_index = -1;
1829   stream->time_position = 0;
1830   stream->sample_index = -1;
1831   stream->offset_in_sample = 0;
1832   stream->new_stream = TRUE;
1833   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1834   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1835   stream->protected = FALSE;
1836   stream->protection_scheme_type = 0;
1837   stream->protection_scheme_version = 0;
1838   stream->protection_scheme_info = NULL;
1839   stream->n_samples_moof = 0;
1840   stream->duration_moof = 0;
1841   g_queue_init (&stream->protection_scheme_event_queue);
1842   return stream;
1843 }
1844
1845 static gboolean
1846 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1847 {
1848   GstStructure *structure;
1849   const gchar *variant;
1850   const GstCaps *mediacaps = NULL;
1851
1852   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1853
1854   structure = gst_caps_get_structure (caps, 0);
1855   variant = gst_structure_get_string (structure, "variant");
1856
1857   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1858     QtDemuxStream *stream;
1859     const GValue *value;
1860
1861     demux->fragmented = TRUE;
1862     demux->mss_mode = TRUE;
1863
1864     if (demux->n_streams > 1) {
1865       /* can't do this, we can only renegotiate for another mss format */
1866       return FALSE;
1867     }
1868
1869     value = gst_structure_get_value (structure, "media-caps");
1870     /* create stream */
1871     if (value) {
1872       const GValue *timescale_v;
1873
1874       /* TODO update when stream changes during playback */
1875
1876       if (demux->n_streams == 0) {
1877         stream = _create_stream ();
1878         demux->streams[demux->n_streams] = stream;
1879         demux->n_streams = 1;
1880       } else {
1881         stream = demux->streams[0];
1882       }
1883
1884       timescale_v = gst_structure_get_value (structure, "timescale");
1885       if (timescale_v) {
1886         stream->timescale = g_value_get_uint64 (timescale_v);
1887       } else {
1888         /* default mss timescale */
1889         stream->timescale = 10000000;
1890       }
1891       demux->timescale = stream->timescale;
1892
1893       mediacaps = gst_value_get_caps (value);
1894       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1895         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1896             mediacaps);
1897         stream->new_caps = TRUE;
1898       }
1899       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1900       structure = gst_caps_get_structure (mediacaps, 0);
1901       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1902         stream->subtype = FOURCC_vide;
1903
1904         gst_structure_get_int (structure, "width", &stream->width);
1905         gst_structure_get_int (structure, "height", &stream->height);
1906         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1907             &stream->fps_d);
1908       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1909         gint rate = 0;
1910         stream->subtype = FOURCC_soun;
1911         gst_structure_get_int (structure, "channels", &stream->n_channels);
1912         gst_structure_get_int (structure, "rate", &rate);
1913         stream->rate = rate;
1914       }
1915     }
1916     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1917   } else {
1918     demux->mss_mode = FALSE;
1919   }
1920
1921   return TRUE;
1922 }
1923
1924 static void
1925 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1926 {
1927   gint n;
1928
1929   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1930   gst_pad_stop_task (qtdemux->sinkpad);
1931
1932   if (hard || qtdemux->upstream_format_is_time) {
1933     qtdemux->state = QTDEMUX_STATE_INITIAL;
1934     qtdemux->neededbytes = 16;
1935     qtdemux->todrop = 0;
1936     qtdemux->pullbased = FALSE;
1937     qtdemux->posted_redirect = FALSE;
1938     qtdemux->first_mdat = -1;
1939     qtdemux->header_size = 0;
1940     qtdemux->mdatoffset = -1;
1941     qtdemux->restoredata_offset = -1;
1942     if (qtdemux->mdatbuffer)
1943       gst_buffer_unref (qtdemux->mdatbuffer);
1944     if (qtdemux->restoredata_buffer)
1945       gst_buffer_unref (qtdemux->restoredata_buffer);
1946     qtdemux->mdatbuffer = NULL;
1947     qtdemux->restoredata_buffer = NULL;
1948     qtdemux->mdatleft = 0;
1949     if (qtdemux->comp_brands)
1950       gst_buffer_unref (qtdemux->comp_brands);
1951     qtdemux->comp_brands = NULL;
1952     qtdemux->last_moov_offset = -1;
1953     if (qtdemux->moov_node)
1954       g_node_destroy (qtdemux->moov_node);
1955     qtdemux->moov_node = NULL;
1956     qtdemux->moov_node_compressed = NULL;
1957     if (qtdemux->tag_list)
1958       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1959     qtdemux->tag_list = NULL;
1960 #if 0
1961     if (qtdemux->element_index)
1962       gst_object_unref (qtdemux->element_index);
1963     qtdemux->element_index = NULL;
1964 #endif
1965     qtdemux->major_brand = 0;
1966     if (qtdemux->pending_newsegment)
1967       gst_event_unref (qtdemux->pending_newsegment);
1968     qtdemux->pending_newsegment = NULL;
1969     qtdemux->upstream_format_is_time = FALSE;
1970     qtdemux->upstream_seekable = FALSE;
1971     qtdemux->upstream_size = 0;
1972
1973     qtdemux->fragment_start = -1;
1974     qtdemux->fragment_start_offset = -1;
1975     qtdemux->duration = 0;
1976     qtdemux->moof_offset = 0;
1977     qtdemux->chapters_track_id = 0;
1978     qtdemux->have_group_id = FALSE;
1979     qtdemux->group_id = G_MAXUINT;
1980
1981     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1982         NULL);
1983     g_queue_clear (&qtdemux->protection_event_queue);
1984   }
1985   qtdemux->offset = 0;
1986   gst_adapter_clear (qtdemux->adapter);
1987   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1988   qtdemux->segment_seqnum = 0;
1989
1990   if (hard) {
1991     for (n = 0; n < qtdemux->n_streams; n++) {
1992       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
1993       qtdemux->streams[n] = NULL;
1994     }
1995     qtdemux->n_streams = 0;
1996     qtdemux->n_video_streams = 0;
1997     qtdemux->n_audio_streams = 0;
1998     qtdemux->n_sub_streams = 0;
1999     qtdemux->exposed = FALSE;
2000     qtdemux->fragmented = FALSE;
2001     qtdemux->mss_mode = FALSE;
2002     gst_caps_replace (&qtdemux->media_caps, NULL);
2003     qtdemux->timescale = 0;
2004     qtdemux->got_moov = FALSE;
2005     if (qtdemux->protection_system_ids) {
2006       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2007       qtdemux->protection_system_ids = NULL;
2008     }
2009   } else if (qtdemux->mss_mode) {
2010     gst_flow_combiner_reset (qtdemux->flowcombiner);
2011     for (n = 0; n < qtdemux->n_streams; n++)
2012       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2013   } else {
2014     gst_flow_combiner_reset (qtdemux->flowcombiner);
2015     for (n = 0; n < qtdemux->n_streams; n++) {
2016       qtdemux->streams[n]->sent_eos = FALSE;
2017       qtdemux->streams[n]->time_position = 0;
2018       qtdemux->streams[n]->accumulated_base = 0;
2019     }
2020     if (!qtdemux->pending_newsegment) {
2021       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2022       if (qtdemux->segment_seqnum)
2023         gst_event_set_seqnum (qtdemux->pending_newsegment,
2024             qtdemux->segment_seqnum);
2025     }
2026   }
2027 }
2028
2029
2030 /* Maps the @segment to the qt edts internal segments and pushes
2031  * the correspnding segment event.
2032  *
2033  * If it ends up being at a empty segment, a gap will be pushed and the next
2034  * edts segment will be activated in sequence.
2035  *
2036  * To be used in push-mode only */
2037 static void
2038 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2039 {
2040   gint n, i;
2041
2042   for (n = 0; n < qtdemux->n_streams; n++) {
2043     QtDemuxStream *stream = qtdemux->streams[n];
2044
2045     stream->time_position = segment->start;
2046
2047     /* in push mode we should be guaranteed that we will have empty segments
2048      * at the beginning and then one segment after, other scenarios are not
2049      * supported and are discarded when parsing the edts */
2050     for (i = 0; i < stream->n_segments; i++) {
2051       if (stream->segments[i].stop_time > segment->start) {
2052         gst_qtdemux_activate_segment (qtdemux, stream, i,
2053             stream->time_position);
2054         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2055           /* push the empty segment and move to the next one */
2056           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2057               stream->time_position);
2058           continue;
2059         }
2060
2061         g_assert (i == stream->n_segments - 1);
2062       }
2063     }
2064   }
2065 }
2066
2067 static gboolean
2068 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2069     GstEvent * event)
2070 {
2071   GstQTDemux *demux = GST_QTDEMUX (parent);
2072   gboolean res = TRUE;
2073
2074   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2075
2076   switch (GST_EVENT_TYPE (event)) {
2077     case GST_EVENT_SEGMENT:
2078     {
2079       gint64 offset = 0;
2080       QtDemuxStream *stream;
2081       gint idx;
2082       GstSegment segment;
2083       GstEvent *segment_event;
2084
2085       /* some debug output */
2086       gst_event_copy_segment (event, &segment);
2087       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2088           &segment);
2089
2090       if (segment.format == GST_FORMAT_TIME) {
2091         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2092         gst_event_replace (&demux->pending_newsegment, event);
2093         demux->upstream_format_is_time = TRUE;
2094       } else {
2095         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2096             "not in time format");
2097
2098         /* chain will send initial newsegment after pads have been added */
2099         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2100           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2101           goto exit;
2102         }
2103       }
2104
2105       /* check if this matches a time seek we received previously
2106        * FIXME for backwards compatibility reasons we use the
2107        * seek_offset here to compare. In the future we might want to
2108        * change this to use the seqnum as it uniquely should identify
2109        * the segment that corresponds to the seek. */
2110       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2111           ", received segment offset %" G_GINT64_FORMAT,
2112           demux->seek_offset, segment.start);
2113       if (segment.format == GST_FORMAT_BYTES
2114           && demux->seek_offset == segment.start) {
2115         GST_OBJECT_LOCK (demux);
2116         offset = segment.start;
2117
2118         segment.format = GST_FORMAT_TIME;
2119         segment.start = demux->push_seek_start;
2120         segment.stop = demux->push_seek_stop;
2121         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2122             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2123             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2124         GST_OBJECT_UNLOCK (demux);
2125       }
2126
2127       /* we only expect a BYTE segment, e.g. following a seek */
2128       if (segment.format == GST_FORMAT_BYTES) {
2129         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2130           offset = segment.start;
2131
2132           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2133               NULL, (gint64 *) & segment.start);
2134           if ((gint64) segment.start < 0)
2135             segment.start = 0;
2136         }
2137         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2138           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2139               NULL, (gint64 *) & segment.stop);
2140           /* keyframe seeking should already arrange for start >= stop,
2141            * but make sure in other rare cases */
2142           segment.stop = MAX (segment.stop, segment.start);
2143         }
2144       } else if (segment.format == GST_FORMAT_TIME) {
2145         /* push all data on the adapter before starting this
2146          * new segment */
2147         gst_qtdemux_process_adapter (demux, TRUE);
2148       } else {
2149         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2150         goto exit;
2151       }
2152
2153       /* accept upstream's notion of segment and distribute along */
2154       segment.format = GST_FORMAT_TIME;
2155       segment.position = segment.time = segment.start;
2156       segment.duration = demux->segment.duration;
2157       segment.base = gst_segment_to_running_time (&demux->segment,
2158           GST_FORMAT_TIME, demux->segment.position);
2159
2160       gst_segment_copy_into (&segment, &demux->segment);
2161       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2162       /* erase any previously set segment */
2163       gst_event_replace (&demux->pending_newsegment, NULL);
2164
2165       /* For pull mode, segment activation will be handled in the looping task
2166        * For push mode, need to do it here */
2167       if (demux->pullbased) {
2168         segment_event = gst_event_new_segment (&segment);
2169         gst_event_set_seqnum (segment_event, gst_event_get_seqnum (event));
2170         gst_qtdemux_push_event (demux, segment_event);
2171       } else {
2172         /* map segment to internal qt segments and push on each stream */
2173         gst_qtdemux_map_and_push_segments (demux, &segment);
2174       }
2175
2176       /* clear leftover in current segment, if any */
2177       gst_adapter_clear (demux->adapter);
2178
2179       /* set up streaming thread */
2180       demux->offset = offset;
2181       if (demux->upstream_format_is_time) {
2182         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2183             "set values to restart reading from a new atom");
2184         demux->neededbytes = 16;
2185         demux->todrop = 0;
2186       } else {
2187         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2188             NULL);
2189         if (stream) {
2190           demux->todrop = stream->samples[idx].offset - offset;
2191           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2192         } else {
2193           /* set up for EOS */
2194           demux->neededbytes = -1;
2195           demux->todrop = 0;
2196         }
2197       }
2198     exit:
2199       gst_event_unref (event);
2200       res = TRUE;
2201       goto drop;
2202     }
2203     case GST_EVENT_FLUSH_START:
2204     {
2205       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2206         gst_event_unref (event);
2207         goto drop;
2208       }
2209       break;
2210     }
2211     case GST_EVENT_FLUSH_STOP:
2212     {
2213       guint64 dur;
2214
2215       dur = demux->segment.duration;
2216       gst_qtdemux_reset (demux, FALSE);
2217       demux->segment.duration = dur;
2218
2219       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2220         gst_event_unref (event);
2221         goto drop;
2222       }
2223       break;
2224     }
2225     case GST_EVENT_EOS:
2226       /* If we are in push mode, and get an EOS before we've seen any streams,
2227        * then error out - we have nowhere to send the EOS */
2228       if (!demux->pullbased) {
2229         gint i;
2230         gboolean has_valid_stream = FALSE;
2231         for (i = 0; i < demux->n_streams; i++) {
2232           if (demux->streams[i]->pad != NULL) {
2233             has_valid_stream = TRUE;
2234             break;
2235           }
2236         }
2237         if (!has_valid_stream)
2238           gst_qtdemux_post_no_playable_stream_error (demux);
2239         else {
2240           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2241               (guint) gst_adapter_available (demux->adapter));
2242           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2243             res = FALSE;
2244           }
2245         }
2246       }
2247       break;
2248     case GST_EVENT_CAPS:{
2249       GstCaps *caps = NULL;
2250
2251       gst_event_parse_caps (event, &caps);
2252       gst_qtdemux_setcaps (demux, caps);
2253       res = TRUE;
2254       gst_event_unref (event);
2255       goto drop;
2256     }
2257     case GST_EVENT_PROTECTION:
2258     {
2259       const gchar *system_id = NULL;
2260
2261       gst_event_parse_protection (event, &system_id, NULL, NULL);
2262       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2263           system_id);
2264       gst_qtdemux_append_protection_system_id (demux, system_id);
2265       /* save the event for later, for source pads that have not been created */
2266       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2267       /* send it to all pads that already exist */
2268       gst_qtdemux_push_event (demux, event);
2269       res = TRUE;
2270       goto drop;
2271     }
2272     default:
2273       break;
2274   }
2275
2276   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2277
2278 drop:
2279   return res;
2280 }
2281
2282 #if 0
2283 static void
2284 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2285 {
2286   GstQTDemux *demux = GST_QTDEMUX (element);
2287
2288   GST_OBJECT_LOCK (demux);
2289   if (demux->element_index)
2290     gst_object_unref (demux->element_index);
2291   if (index) {
2292     demux->element_index = gst_object_ref (index);
2293   } else {
2294     demux->element_index = NULL;
2295   }
2296   GST_OBJECT_UNLOCK (demux);
2297   /* object lock might be taken again */
2298   if (index)
2299     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2300   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2301       demux->element_index, demux->index_id);
2302 }
2303
2304 static GstIndex *
2305 gst_qtdemux_get_index (GstElement * element)
2306 {
2307   GstIndex *result = NULL;
2308   GstQTDemux *demux = GST_QTDEMUX (element);
2309
2310   GST_OBJECT_LOCK (demux);
2311   if (demux->element_index)
2312     result = gst_object_ref (demux->element_index);
2313   GST_OBJECT_UNLOCK (demux);
2314
2315   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2316
2317   return result;
2318 }
2319 #endif
2320
2321 static void
2322 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2323 {
2324   g_free ((gpointer) stream->stco.data);
2325   stream->stco.data = NULL;
2326   g_free ((gpointer) stream->stsz.data);
2327   stream->stsz.data = NULL;
2328   g_free ((gpointer) stream->stsc.data);
2329   stream->stsc.data = NULL;
2330   g_free ((gpointer) stream->stts.data);
2331   stream->stts.data = NULL;
2332   g_free ((gpointer) stream->stss.data);
2333   stream->stss.data = NULL;
2334   g_free ((gpointer) stream->stps.data);
2335   stream->stps.data = NULL;
2336   g_free ((gpointer) stream->ctts.data);
2337   stream->ctts.data = NULL;
2338 }
2339
2340 static void
2341 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2342     QtDemuxStream * stream)
2343 {
2344   g_free (stream->segments);
2345   stream->segments = NULL;
2346   stream->segment_index = -1;
2347   stream->accumulated_base = 0;
2348 }
2349
2350 static void
2351 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2352     QtDemuxStream * stream)
2353 {
2354   g_free (stream->samples);
2355   stream->samples = NULL;
2356   gst_qtdemux_stbl_free (stream);
2357
2358   /* fragments */
2359   g_free (stream->ra_entries);
2360   stream->ra_entries = NULL;
2361   stream->n_ra_entries = 0;
2362
2363   stream->sample_index = -1;
2364   stream->stbl_index = -1;
2365   stream->n_samples = 0;
2366   stream->time_position = 0;
2367
2368   stream->n_samples_moof = 0;
2369   stream->duration_moof = 0;
2370 }
2371
2372 static void
2373 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2374 {
2375   if (stream->allocator)
2376     gst_object_unref (stream->allocator);
2377   while (stream->buffers) {
2378     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2379     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2380   }
2381   if (stream->rgb8_palette) {
2382     gst_memory_unref (stream->rgb8_palette);
2383     stream->rgb8_palette = NULL;
2384   }
2385
2386   if (stream->pending_tags)
2387     gst_tag_list_unref (stream->pending_tags);
2388   stream->pending_tags = NULL;
2389   g_free (stream->redirect_uri);
2390   stream->redirect_uri = NULL;
2391   stream->sent_eos = FALSE;
2392   stream->sparse = FALSE;
2393   stream->protected = FALSE;
2394   if (stream->protection_scheme_info) {
2395     if (stream->protection_scheme_type == FOURCC_cenc) {
2396       QtDemuxCencSampleSetInfo *info =
2397           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2398       if (info->default_properties)
2399         gst_structure_free (info->default_properties);
2400       if (info->crypto_info)
2401         g_ptr_array_free (info->crypto_info, TRUE);
2402     }
2403     g_free (stream->protection_scheme_info);
2404     stream->protection_scheme_info = NULL;
2405   }
2406   stream->protection_scheme_type = 0;
2407   stream->protection_scheme_version = 0;
2408   g_queue_foreach (&stream->protection_scheme_event_queue,
2409       (GFunc) gst_event_unref, NULL);
2410   g_queue_clear (&stream->protection_scheme_event_queue);
2411   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2412   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2413 }
2414
2415 static void
2416 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2417 {
2418   gst_qtdemux_stream_clear (qtdemux, stream);
2419   if (stream->caps)
2420     gst_caps_unref (stream->caps);
2421   stream->caps = NULL;
2422   if (stream->pad) {
2423     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2424     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2425   }
2426   g_free (stream);
2427 }
2428
2429 static void
2430 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2431 {
2432   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2433
2434   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2435   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2436   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2437   qtdemux->n_streams--;
2438 }
2439
2440 static GstStateChangeReturn
2441 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2442 {
2443   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2444   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2445
2446   switch (transition) {
2447     case GST_STATE_CHANGE_PAUSED_TO_READY:
2448       break;
2449     default:
2450       break;
2451   }
2452
2453   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2454
2455   switch (transition) {
2456     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2457       gst_qtdemux_reset (qtdemux, TRUE);
2458       break;
2459     }
2460     default:
2461       break;
2462   }
2463
2464   return result;
2465 }
2466
2467 static void
2468 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2469 {
2470   /* counts as header data */
2471   qtdemux->header_size += length;
2472
2473   /* only consider at least a sufficiently complete ftyp atom */
2474   if (length >= 20) {
2475     GstBuffer *buf;
2476
2477     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2478     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2479         GST_FOURCC_ARGS (qtdemux->major_brand));
2480     if (qtdemux->comp_brands)
2481       gst_buffer_unref (qtdemux->comp_brands);
2482     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2483     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2484   }
2485 }
2486
2487 static void
2488 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2489     GstTagList * xmptaglist)
2490 {
2491   /* Strip out bogus fields */
2492   if (xmptaglist) {
2493     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2494       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2495       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2496     } else {
2497       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2498     }
2499
2500     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2501
2502     /* prioritize native tags using _KEEP mode */
2503     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2504     gst_tag_list_unref (xmptaglist);
2505   }
2506 }
2507
2508 static void
2509 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2510     guint offset)
2511 {
2512   GstByteReader br;
2513   guint8 version;
2514   guint32 flags = 0;
2515   guint i;
2516   guint8 iv_size = 8;
2517   QtDemuxStream *stream;
2518   GstStructure *structure;
2519   QtDemuxCencSampleSetInfo *ss_info = NULL;
2520   const gchar *system_id;
2521   gboolean uses_sub_sample_encryption = FALSE;
2522
2523   if (qtdemux->n_streams == 0)
2524     return;
2525
2526   stream = qtdemux->streams[0];
2527
2528   structure = gst_caps_get_structure (stream->caps, 0);
2529   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2530     GST_WARNING_OBJECT (qtdemux,
2531         "Attempting PIFF box parsing on an unencrypted stream.");
2532     return;
2533   }
2534
2535   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2536       G_TYPE_STRING, &system_id, NULL);
2537   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2538
2539   stream->protected = TRUE;
2540   stream->protection_scheme_type = FOURCC_cenc;
2541
2542   if (!stream->protection_scheme_info)
2543     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2544
2545   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2546
2547   if (ss_info->default_properties)
2548     gst_structure_free (ss_info->default_properties);
2549
2550   ss_info->default_properties =
2551       gst_structure_new ("application/x-cenc",
2552       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2553
2554   if (ss_info->crypto_info) {
2555     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2556     g_ptr_array_free (ss_info->crypto_info, TRUE);
2557     ss_info->crypto_info = NULL;
2558   }
2559
2560   /* skip UUID */
2561   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2562
2563   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2564     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2565     return;
2566   }
2567
2568   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2569     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2570     return;
2571   }
2572
2573   if ((flags & 0x000001)) {
2574     guint32 algorithm_id = 0;
2575     const guint8 *kid;
2576     GstBuffer *kid_buf;
2577     gboolean is_encrypted = TRUE;
2578
2579     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2580       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2581       return;
2582     }
2583
2584     algorithm_id >>= 8;
2585     if (algorithm_id == 0) {
2586       is_encrypted = FALSE;
2587     } else if (algorithm_id == 1) {
2588       /* FIXME: maybe store this in properties? */
2589       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2590     } else if (algorithm_id == 2) {
2591       /* FIXME: maybe store this in properties? */
2592       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2593     }
2594
2595     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2596       return;
2597
2598     if (!gst_byte_reader_get_data (&br, 16, &kid))
2599       return;
2600
2601     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2602     gst_buffer_fill (kid_buf, 0, kid, 16);
2603     if (ss_info->default_properties)
2604       gst_structure_free (ss_info->default_properties);
2605     ss_info->default_properties =
2606         gst_structure_new ("application/x-cenc",
2607         "iv_size", G_TYPE_UINT, iv_size,
2608         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2609         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2610     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2611         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2612     gst_buffer_unref (kid_buf);
2613   } else if ((flags & 0x000002)) {
2614     uses_sub_sample_encryption = TRUE;
2615   }
2616
2617   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2618     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2619     return;
2620   }
2621
2622   ss_info->crypto_info =
2623       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2624       (GDestroyNotify) qtdemux_gst_structure_free);
2625
2626   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2627     GstStructure *properties;
2628     guint8 *data;
2629     GstBuffer *buf;
2630
2631     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2632     if (properties == NULL) {
2633       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2634       return;
2635     }
2636
2637     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2638       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2639       gst_structure_free (properties);
2640       return;
2641     }
2642     buf = gst_buffer_new_wrapped (data, iv_size);
2643     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2644     gst_buffer_unref (buf);
2645
2646     if (uses_sub_sample_encryption) {
2647       guint16 n_subsamples;
2648
2649       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2650           || n_subsamples == 0) {
2651         GST_ERROR_OBJECT (qtdemux,
2652             "failed to get subsample count for sample %u", i);
2653         gst_structure_free (properties);
2654         return;
2655       }
2656       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2657       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2658         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2659             i);
2660         gst_structure_free (properties);
2661         return;
2662       }
2663       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2664       gst_structure_set (properties,
2665           "subsample_count", G_TYPE_UINT, n_subsamples,
2666           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2667       gst_buffer_unref (buf);
2668     } else {
2669       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2670     }
2671
2672     g_ptr_array_add (ss_info->crypto_info, properties);
2673   }
2674 }
2675
2676 static void
2677 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2678 {
2679   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2680     0x97, 0xA9, 0x42, 0xE8,
2681     0x9C, 0x71, 0x99, 0x94,
2682     0x91, 0xE3, 0xAF, 0xAC
2683   };
2684   static const guint8 playready_uuid[] = {
2685     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2686     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2687   };
2688
2689   static const guint8 piff_sample_encryption_uuid[] = {
2690     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2691     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2692   };
2693
2694   guint offset;
2695
2696   /* counts as header data */
2697   qtdemux->header_size += length;
2698
2699   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2700
2701   if (length <= offset + 16) {
2702     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2703     return;
2704   }
2705
2706   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2707     GstBuffer *buf;
2708     GstTagList *taglist;
2709
2710     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2711         length - offset - 16, NULL);
2712     taglist = gst_tag_list_from_xmp_buffer (buf);
2713     gst_buffer_unref (buf);
2714
2715     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2716
2717   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2718     int len;
2719     const gunichar2 *s_utf16;
2720     char *contents;
2721
2722     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2723     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2724     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2725     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2726
2727     g_free (contents);
2728
2729     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2730         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2731         (NULL));
2732   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2733     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2734   } else {
2735     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2736         GST_READ_UINT32_LE (buffer + offset),
2737         GST_READ_UINT32_LE (buffer + offset + 4),
2738         GST_READ_UINT32_LE (buffer + offset + 8),
2739         GST_READ_UINT32_LE (buffer + offset + 12));
2740   }
2741 }
2742
2743 static void
2744 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2745 {
2746   GstSidxParser sidx_parser;
2747   GstIsoffParserResult res;
2748   guint consumed;
2749
2750   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2751
2752   res =
2753       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2754       &consumed);
2755   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2756   if (res == GST_ISOFF_QT_PARSER_DONE) {
2757     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2758   }
2759   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2760 }
2761
2762 /* caller verifies at least 8 bytes in buf */
2763 static void
2764 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2765     guint64 * plength, guint32 * pfourcc)
2766 {
2767   guint64 length;
2768   guint32 fourcc;
2769
2770   length = QT_UINT32 (data);
2771   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2772   fourcc = QT_FOURCC (data + 4);
2773   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2774
2775   if (length == 0) {
2776     length = G_MAXUINT64;
2777   } else if (length == 1 && size >= 16) {
2778     /* this means we have an extended size, which is the 64 bit value of
2779      * the next 8 bytes */
2780     length = QT_UINT64 (data + 8);
2781     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2782   }
2783
2784   if (plength)
2785     *plength = length;
2786   if (pfourcc)
2787     *pfourcc = fourcc;
2788 }
2789
2790 static gboolean
2791 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2792 {
2793   guint32 version = 0;
2794   GstClockTime duration = 0;
2795
2796   if (!gst_byte_reader_get_uint32_be (br, &version))
2797     goto failed;
2798
2799   version >>= 24;
2800   if (version == 1) {
2801     if (!gst_byte_reader_get_uint64_be (br, &duration))
2802       goto failed;
2803   } else {
2804     guint32 dur = 0;
2805
2806     if (!gst_byte_reader_get_uint32_be (br, &dur))
2807       goto failed;
2808     duration = dur;
2809   }
2810
2811   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2812   qtdemux->duration = duration;
2813
2814   return TRUE;
2815
2816 failed:
2817   {
2818     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2819     return FALSE;
2820   }
2821 }
2822
2823 static gboolean
2824 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2825     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2826 {
2827   if (!stream->parsed_trex && qtdemux->moov_node) {
2828     GNode *mvex, *trex;
2829     GstByteReader trex_data;
2830
2831     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2832     if (mvex) {
2833       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2834           &trex_data);
2835       while (trex) {
2836         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2837
2838         /* skip version/flags */
2839         if (!gst_byte_reader_skip (&trex_data, 4))
2840           goto next;
2841         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2842           goto next;
2843         if (id != stream->track_id)
2844           goto next;
2845         /* sample description index; ignore */
2846         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2847           goto next;
2848         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2849           goto next;
2850         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2851           goto next;
2852         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2853           goto next;
2854
2855         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2856             "duration %d,  size %d, flags 0x%x", stream->track_id,
2857             dur, size, flags);
2858
2859         stream->parsed_trex = TRUE;
2860         stream->def_sample_duration = dur;
2861         stream->def_sample_size = size;
2862         stream->def_sample_flags = flags;
2863
2864       next:
2865         /* iterate all siblings */
2866         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2867             &trex_data);
2868       }
2869     }
2870   }
2871
2872   *ds_duration = stream->def_sample_duration;
2873   *ds_size = stream->def_sample_size;
2874   *ds_flags = stream->def_sample_flags;
2875
2876   /* even then, above values are better than random ... */
2877   if (G_UNLIKELY (!stream->parsed_trex)) {
2878     GST_WARNING_OBJECT (qtdemux,
2879         "failed to find fragment defaults for stream %d", stream->track_id);
2880     return FALSE;
2881   }
2882
2883   return TRUE;
2884 }
2885
2886 /* This method should be called whenever a more accurate duration might
2887  * have been found. It will update all relevant variables if/where needed
2888  */
2889 static void
2890 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2891 {
2892   guint i;
2893   guint64 movdur;
2894   GstClockTime prevdur;
2895
2896   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2897
2898   if (movdur > qtdemux->duration) {
2899     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2900     GST_DEBUG_OBJECT (qtdemux,
2901         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2902         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2903     qtdemux->duration = movdur;
2904     GST_DEBUG_OBJECT (qtdemux,
2905         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2906         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2907         GST_TIME_ARGS (qtdemux->segment.stop));
2908     if (qtdemux->segment.duration == prevdur) {
2909       /* If the current segment has duration/stop identical to previous duration
2910        * update them also (because they were set at that point in time with
2911        * the wrong duration */
2912       /* We convert the value *from* the timescale version to avoid rounding errors */
2913       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2914       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2915       qtdemux->segment.duration = fixeddur;
2916       qtdemux->segment.stop = fixeddur;
2917     }
2918   }
2919   for (i = 0; i < qtdemux->n_streams; i++) {
2920     QtDemuxStream *stream = qtdemux->streams[i];
2921     if (stream) {
2922       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2923       if (movdur > stream->duration) {
2924         GST_DEBUG_OBJECT (qtdemux,
2925             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2926             GST_TIME_ARGS (duration));
2927         stream->duration = movdur;
2928         if (stream->dummy_segment) {
2929           /* Update all dummy values to new duration */
2930           stream->segments[0].stop_time = duration;
2931           stream->segments[0].duration = duration;
2932           stream->segments[0].media_stop = duration;
2933
2934           /* let downstream know we possibly have a new stop time */
2935           if (stream->segment_index != -1) {
2936             GstClockTime pos;
2937
2938             if (qtdemux->segment.rate >= 0) {
2939               pos = stream->segment.start;
2940             } else {
2941               pos = stream->segment.stop;
2942             }
2943
2944             gst_qtdemux_stream_update_segment (qtdemux, stream,
2945                 stream->segment_index, pos, NULL, NULL);
2946           }
2947         }
2948       }
2949     }
2950   }
2951 }
2952
2953 static gboolean
2954 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2955     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2956     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2957     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2958 {
2959   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2960   guint64 timestamp;
2961   gint32 data_offset = 0;
2962   guint32 flags = 0, first_flags = 0, samples_count = 0;
2963   gint i;
2964   guint8 *data;
2965   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2966   QtDemuxSample *sample;
2967   gboolean ismv = FALSE;
2968
2969   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2970       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2971       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2972       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2973
2974   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2975     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2976     return TRUE;
2977   }
2978
2979   /* presence of stss or not can't really tell us much,
2980    * and flags and so on tend to be marginally reliable in these files */
2981   if (stream->subtype == FOURCC_soun) {
2982     GST_DEBUG_OBJECT (qtdemux,
2983         "sound track in fragmented file; marking all keyframes");
2984     stream->all_keyframe = TRUE;
2985   }
2986
2987   if (!gst_byte_reader_skip (trun, 1) ||
2988       !gst_byte_reader_get_uint24_be (trun, &flags))
2989     goto fail;
2990
2991   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
2992     goto fail;
2993
2994   if (flags & TR_DATA_OFFSET) {
2995     /* note this is really signed */
2996     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
2997       goto fail;
2998     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
2999     /* default base offset = first byte of moof */
3000     if (*base_offset == -1) {
3001       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3002       *base_offset = moof_offset;
3003     }
3004     *running_offset = *base_offset + data_offset;
3005   } else {
3006     /* if no offset at all, that would mean data starts at moof start,
3007      * which is a bit wrong and is ismv crappy way, so compensate
3008      * assuming data is in mdat following moof */
3009     if (*base_offset == -1) {
3010       *base_offset = moof_offset + moof_length + 8;
3011       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3012       ismv = TRUE;
3013     }
3014     if (*running_offset == -1)
3015       *running_offset = *base_offset;
3016   }
3017
3018   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3019       *running_offset);
3020   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3021       data_offset, flags, samples_count);
3022
3023   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3024     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3025       GST_DEBUG_OBJECT (qtdemux,
3026           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3027       flags ^= TR_FIRST_SAMPLE_FLAGS;
3028     } else {
3029       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3030         goto fail;
3031       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3032     }
3033   }
3034
3035   /* FIXME ? spec says other bits should also be checked to determine
3036    * entry size (and prefix size for that matter) */
3037   entry_size = 0;
3038   dur_offset = size_offset = 0;
3039   if (flags & TR_SAMPLE_DURATION) {
3040     GST_LOG_OBJECT (qtdemux, "entry duration present");
3041     dur_offset = entry_size;
3042     entry_size += 4;
3043   }
3044   if (flags & TR_SAMPLE_SIZE) {
3045     GST_LOG_OBJECT (qtdemux, "entry size present");
3046     size_offset = entry_size;
3047     entry_size += 4;
3048   }
3049   if (flags & TR_SAMPLE_FLAGS) {
3050     GST_LOG_OBJECT (qtdemux, "entry flags present");
3051     flags_offset = entry_size;
3052     entry_size += 4;
3053   }
3054   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3055     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3056     ct_offset = entry_size;
3057     entry_size += 4;
3058   }
3059
3060   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3061     goto fail;
3062   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3063
3064   if (stream->n_samples + samples_count >=
3065       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3066     goto index_too_big;
3067
3068   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3069       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3070       (stream->n_samples + samples_count) *
3071       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3072
3073   /* create a new array of samples if it's the first sample parsed */
3074   if (stream->n_samples == 0) {
3075     g_assert (stream->samples == NULL);
3076     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3077     /* or try to reallocate it with space enough to insert the new samples */
3078   } else
3079     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3080         stream->n_samples + samples_count);
3081   if (stream->samples == NULL)
3082     goto out_of_memory;
3083
3084   if (qtdemux->fragment_start != -1) {
3085     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3086     qtdemux->fragment_start = -1;
3087   } else {
3088     if (stream->n_samples == 0) {
3089       if (decode_ts > 0) {
3090         timestamp = decode_ts;
3091       } else if (stream->pending_seek != NULL) {
3092         /* if we don't have a timestamp from a tfdt box, we'll use the one
3093          * from the mfra seek table */
3094         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3095             GST_TIME_ARGS (stream->pending_seek->ts));
3096
3097         /* FIXME: this is not fully correct, the timestamp refers to the random
3098          * access sample refered to in the tfra entry, which may not necessarily
3099          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3100         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3101       } else {
3102         timestamp = 0;
3103       }
3104
3105       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3106       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3107           GST_TIME_ARGS (gst_ts));
3108     } else {
3109       /* subsequent fragments extend stream */
3110       timestamp =
3111           stream->samples[stream->n_samples - 1].timestamp +
3112           stream->samples[stream->n_samples - 1].duration;
3113
3114       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3115       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3116           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3117     }
3118   }
3119
3120   sample = stream->samples + stream->n_samples;
3121   for (i = 0; i < samples_count; i++) {
3122     guint32 dur, size, sflags, ct;
3123
3124     /* first read sample data */
3125     if (flags & TR_SAMPLE_DURATION) {
3126       dur = QT_UINT32 (data + dur_offset);
3127     } else {
3128       dur = d_sample_duration;
3129     }
3130     if (flags & TR_SAMPLE_SIZE) {
3131       size = QT_UINT32 (data + size_offset);
3132     } else {
3133       size = d_sample_size;
3134     }
3135     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3136       if (i == 0) {
3137         sflags = first_flags;
3138       } else {
3139         sflags = d_sample_flags;
3140       }
3141     } else if (flags & TR_SAMPLE_FLAGS) {
3142       sflags = QT_UINT32 (data + flags_offset);
3143     } else {
3144       sflags = d_sample_flags;
3145     }
3146     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3147       ct = QT_UINT32 (data + ct_offset);
3148     } else {
3149       ct = 0;
3150     }
3151     data += entry_size;
3152
3153     /* fill the sample information */
3154     sample->offset = *running_offset;
3155     sample->pts_offset = ct;
3156     sample->size = size;
3157     sample->timestamp = timestamp;
3158     sample->duration = dur;
3159     /* sample-is-difference-sample */
3160     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3161      * now idea how it relates to bitfield other than massive LE/BE confusion */
3162     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3163     *running_offset += size;
3164     timestamp += dur;
3165     stream->duration_moof += dur;
3166     sample++;
3167   }
3168
3169   /* Update total duration if needed */
3170   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3171
3172   stream->n_samples += samples_count;
3173   stream->n_samples_moof += samples_count;
3174
3175   if (stream->pending_seek != NULL)
3176     stream->pending_seek = NULL;
3177
3178   return TRUE;
3179
3180 fail:
3181   {
3182     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3183     return FALSE;
3184   }
3185 out_of_memory:
3186   {
3187     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3188         stream->n_samples);
3189     return FALSE;
3190   }
3191 index_too_big:
3192   {
3193     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3194         "be larger than %uMB (broken file?)", stream->n_samples,
3195         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3196     return FALSE;
3197   }
3198 }
3199
3200 /* find stream with @id */
3201 static inline QtDemuxStream *
3202 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3203 {
3204   QtDemuxStream *stream;
3205   gint i;
3206
3207   /* check */
3208   if (G_UNLIKELY (!id)) {
3209     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3210     return NULL;
3211   }
3212
3213   /* try to get it fast and simple */
3214   if (G_LIKELY (id <= qtdemux->n_streams)) {
3215     stream = qtdemux->streams[id - 1];
3216     if (G_LIKELY (stream->track_id == id))
3217       return stream;
3218   }
3219
3220   /* linear search otherwise */
3221   for (i = 0; i < qtdemux->n_streams; i++) {
3222     stream = qtdemux->streams[i];
3223     if (stream->track_id == id)
3224       return stream;
3225   }
3226   if (qtdemux->mss_mode) {
3227     /* mss should have only 1 stream anyway */
3228     return qtdemux->streams[0];
3229   }
3230
3231   return NULL;
3232 }
3233
3234 static gboolean
3235 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3236     guint32 * fragment_number)
3237 {
3238   if (!gst_byte_reader_skip (mfhd, 4))
3239     goto fail;
3240   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3241     goto fail;
3242   return TRUE;
3243 fail:
3244   {
3245     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3246     return FALSE;
3247   }
3248 }
3249
3250 static gboolean
3251 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3252     QtDemuxStream ** stream, guint32 * default_sample_duration,
3253     guint32 * default_sample_size, guint32 * default_sample_flags,
3254     gint64 * base_offset)
3255 {
3256   guint32 flags = 0;
3257   guint32 track_id = 0;
3258
3259   if (!gst_byte_reader_skip (tfhd, 1) ||
3260       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3261     goto invalid_track;
3262
3263   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3264     goto invalid_track;
3265
3266   *stream = qtdemux_find_stream (qtdemux, track_id);
3267   if (G_UNLIKELY (!*stream))
3268     goto unknown_stream;
3269
3270   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3271     *base_offset = qtdemux->moof_offset;
3272
3273   if (flags & TF_BASE_DATA_OFFSET)
3274     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3275       goto invalid_track;
3276
3277   /* obtain stream defaults */
3278   qtdemux_parse_trex (qtdemux, *stream,
3279       default_sample_duration, default_sample_size, default_sample_flags);
3280
3281   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3282   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3283     if (!gst_byte_reader_skip (tfhd, 4))
3284       goto invalid_track;
3285
3286   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3287     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3288       goto invalid_track;
3289
3290   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3291     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3292       goto invalid_track;
3293
3294   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3295     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3296       goto invalid_track;
3297
3298   return TRUE;
3299
3300 invalid_track:
3301   {
3302     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3303     return FALSE;
3304   }
3305 unknown_stream:
3306   {
3307     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3308     return TRUE;
3309   }
3310 }
3311
3312 static gboolean
3313 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3314     guint64 * decode_time)
3315 {
3316   guint32 version = 0;
3317
3318   if (!gst_byte_reader_get_uint32_be (br, &version))
3319     return FALSE;
3320
3321   version >>= 24;
3322   if (version == 1) {
3323     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3324       goto failed;
3325   } else {
3326     guint32 dec_time = 0;
3327     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3328       goto failed;
3329     *decode_time = dec_time;
3330   }
3331
3332   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3333       *decode_time);
3334
3335   return TRUE;
3336
3337 failed:
3338   {
3339     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3340     return FALSE;
3341   }
3342 }
3343
3344 /* Returns a pointer to a GstStructure containing the properties of
3345  * the stream sample identified by @sample_index. The caller must unref
3346  * the returned object after use. Returns NULL if unsuccessful. */
3347 static GstStructure *
3348 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3349     QtDemuxStream * stream, guint sample_index)
3350 {
3351   QtDemuxCencSampleSetInfo *info = NULL;
3352
3353   g_return_val_if_fail (stream != NULL, NULL);
3354   g_return_val_if_fail (stream->protected, NULL);
3355   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3356
3357   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3358
3359   /* Currently, cenc properties for groups of samples are not supported, so
3360    * simply return a copy of the default sample properties */
3361   return gst_structure_copy (info->default_properties);
3362 }
3363
3364 /* Parses the sizes of sample auxiliary information contained within a stream,
3365  * as given in a saiz box. Returns array of sample_count guint8 size values,
3366  * or NULL on failure */
3367 static guint8 *
3368 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3369     GstByteReader * br, guint32 * sample_count)
3370 {
3371   guint32 flags = 0;
3372   guint8 *info_sizes;
3373   guint8 default_info_size;
3374
3375   g_return_val_if_fail (qtdemux != NULL, NULL);
3376   g_return_val_if_fail (stream != NULL, NULL);
3377   g_return_val_if_fail (br != NULL, NULL);
3378   g_return_val_if_fail (sample_count != NULL, NULL);
3379
3380   if (!gst_byte_reader_get_uint32_be (br, &flags))
3381     return NULL;
3382
3383   if (flags & 0x1) {
3384     /* aux_info_type and aux_info_type_parameter are ignored */
3385     if (!gst_byte_reader_skip (br, 8))
3386       return NULL;
3387   }
3388
3389   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3390     return NULL;
3391   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3392
3393   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3394     return NULL;
3395   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3396
3397
3398   if (default_info_size == 0) {
3399     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3400       return NULL;
3401     }
3402   } else {
3403     info_sizes = g_new (guint8, *sample_count);
3404     memset (info_sizes, default_info_size, *sample_count);
3405   }
3406
3407   return info_sizes;
3408 }
3409
3410 /* Parses the offset of sample auxiliary information contained within a stream,
3411  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3412 static gboolean
3413 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3414     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3415     guint64 * offset)
3416 {
3417   guint8 version = 0;
3418   guint32 flags = 0;
3419   guint32 aux_info_type = 0;
3420   guint32 aux_info_type_parameter = 0;
3421   guint32 entry_count;
3422   guint32 off_32;
3423   guint64 off_64;
3424   const guint8 *aux_info_type_data = NULL;
3425
3426   g_return_val_if_fail (qtdemux != NULL, FALSE);
3427   g_return_val_if_fail (stream != NULL, FALSE);
3428   g_return_val_if_fail (br != NULL, FALSE);
3429   g_return_val_if_fail (offset != NULL, FALSE);
3430
3431   if (!gst_byte_reader_get_uint8 (br, &version))
3432     return FALSE;
3433
3434   if (!gst_byte_reader_get_uint24_be (br, &flags))
3435     return FALSE;
3436
3437   if (flags & 0x1) {
3438
3439     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3440       return FALSE;
3441     aux_info_type = QT_FOURCC (aux_info_type_data);
3442
3443     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3444       return FALSE;
3445   } else if (stream->protected) {
3446     aux_info_type = stream->protection_scheme_type;
3447   } else {
3448     aux_info_type = stream->fourcc;
3449   }
3450
3451   if (info_type)
3452     *info_type = aux_info_type;
3453   if (info_type_parameter)
3454     *info_type_parameter = aux_info_type_parameter;
3455
3456   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3457       "aux_info_type_parameter:  %#06x",
3458       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3459
3460   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3461     return FALSE;
3462
3463   if (entry_count != 1) {
3464     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3465     return FALSE;
3466   }
3467
3468   if (version == 0) {
3469     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3470       return FALSE;
3471     *offset = (guint64) off_32;
3472   } else {
3473     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3474       return FALSE;
3475     *offset = off_64;
3476   }
3477
3478   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3479   return TRUE;
3480 }
3481
3482 static void
3483 qtdemux_gst_structure_free (GstStructure * gststructure)
3484 {
3485   if (gststructure) {
3486     gst_structure_free (gststructure);
3487   }
3488 }
3489
3490 /* Parses auxiliary information relating to samples protected using Common
3491  * Encryption (cenc); the format of this information is defined in
3492  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3493 static gboolean
3494 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3495     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3496 {
3497   QtDemuxCencSampleSetInfo *ss_info = NULL;
3498   guint8 size;
3499   gint i;
3500
3501   g_return_val_if_fail (qtdemux != NULL, FALSE);
3502   g_return_val_if_fail (stream != NULL, FALSE);
3503   g_return_val_if_fail (br != NULL, FALSE);
3504   g_return_val_if_fail (stream->protected, FALSE);
3505   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3506
3507   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3508
3509   if (ss_info->crypto_info) {
3510     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3511     g_ptr_array_free (ss_info->crypto_info, TRUE);
3512   }
3513
3514   ss_info->crypto_info =
3515       g_ptr_array_new_full (sample_count,
3516       (GDestroyNotify) qtdemux_gst_structure_free);
3517
3518   for (i = 0; i < sample_count; ++i) {
3519     GstStructure *properties;
3520     guint16 n_subsamples = 0;
3521     guint8 *data;
3522     guint iv_size;
3523     GstBuffer *buf;
3524
3525     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3526     if (properties == NULL) {
3527       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3528       return FALSE;
3529     }
3530     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3531       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3532       gst_structure_free (properties);
3533       return FALSE;
3534     }
3535     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3536       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3537       gst_structure_free (properties);
3538       return FALSE;
3539     }
3540     buf = gst_buffer_new_wrapped (data, iv_size);
3541     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3542     gst_buffer_unref (buf);
3543     size = info_sizes[i];
3544     if (size > iv_size) {
3545       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3546           || !(n_subsamples > 0)) {
3547         gst_structure_free (properties);
3548         GST_ERROR_OBJECT (qtdemux,
3549             "failed to get subsample count for sample %u", i);
3550         return FALSE;
3551       }
3552       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3553       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3554         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3555             i);
3556         gst_structure_free (properties);
3557         return FALSE;
3558       }
3559       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3560       if (!buf) {
3561         gst_structure_free (properties);
3562         return FALSE;
3563       }
3564       gst_structure_set (properties,
3565           "subsample_count", G_TYPE_UINT, n_subsamples,
3566           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3567       gst_buffer_unref (buf);
3568     } else {
3569       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3570     }
3571     g_ptr_array_add (ss_info->crypto_info, properties);
3572   }
3573   return TRUE;
3574 }
3575
3576 /* Converts a UUID in raw byte form to a string representation, as defined in
3577  * RFC 4122. The caller takes ownership of the returned string and is
3578  * responsible for freeing it after use. */
3579 static gchar *
3580 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3581 {
3582   const guint8 *uuid = (const guint8 *) uuid_bytes;
3583
3584   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3585       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3586       uuid[0], uuid[1], uuid[2], uuid[3],
3587       uuid[4], uuid[5], uuid[6], uuid[7],
3588       uuid[8], uuid[9], uuid[10], uuid[11],
3589       uuid[12], uuid[13], uuid[14], uuid[15]);
3590 }
3591
3592 /* Parses a Protection System Specific Header box (pssh), as defined in the
3593  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3594  * information needed by a specific content protection system in order to
3595  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3596  * otherwise. */
3597 static gboolean
3598 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3599 {
3600   gchar *sysid_string;
3601   guint32 pssh_size = QT_UINT32 (node->data);
3602   GstBuffer *pssh = NULL;
3603   GstEvent *event = NULL;
3604   guint32 parent_box_type;
3605   gint i;
3606
3607   if (G_UNLIKELY (pssh_size < 32U)) {
3608     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3609     return FALSE;
3610   }
3611
3612   sysid_string =
3613       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3614
3615   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3616
3617   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3618   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3619       gst_buffer_get_size (pssh));
3620
3621   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3622
3623   /* Push an event containing the pssh box onto the queues of all streams. */
3624   event = gst_event_new_protection (sysid_string, pssh,
3625       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3626   for (i = 0; i < qtdemux->n_streams; ++i) {
3627     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3628         gst_event_ref (event));
3629   }
3630   g_free (sysid_string);
3631   gst_event_unref (event);
3632   gst_buffer_unref (pssh);
3633   return TRUE;
3634 }
3635
3636 static gboolean
3637 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3638     guint64 moof_offset, QtDemuxStream * stream)
3639 {
3640   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3641   GNode *uuid_node;
3642   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3643   GNode *saiz_node, *saio_node, *pssh_node;
3644   GstByteReader saiz_data, saio_data;
3645   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3646   gint64 base_offset, running_offset;
3647   guint32 frag_num;
3648
3649   /* NOTE @stream ignored */
3650
3651   moof_node = g_node_new ((guint8 *) buffer);
3652   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3653   qtdemux_node_dump (qtdemux, moof_node);
3654
3655   /* Get fragment number from mfhd and check it's valid */
3656   mfhd_node =
3657       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3658   if (mfhd_node == NULL)
3659     goto missing_mfhd;
3660   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3661     goto fail;
3662   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3663
3664   /* unknown base_offset to start with */
3665   base_offset = running_offset = -1;
3666   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3667   while (traf_node) {
3668     guint64 decode_time = 0;
3669
3670     /* Fragment Header node */
3671     tfhd_node =
3672         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3673         &tfhd_data);
3674     if (!tfhd_node)
3675       goto missing_tfhd;
3676     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3677             &ds_size, &ds_flags, &base_offset))
3678       goto missing_tfhd;
3679
3680     /* The following code assumes at most a single set of sample auxiliary
3681      * data in the fragment (consisting of a saiz box and a corresponding saio
3682      * box); in theory, however, there could be multiple sets of sample
3683      * auxiliary data in a fragment. */
3684     saiz_node =
3685         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3686         &saiz_data);
3687     if (saiz_node) {
3688       guint32 info_type = 0;
3689       guint64 offset = 0;
3690       guint32 info_type_parameter = 0;
3691
3692       g_free (qtdemux->cenc_aux_info_sizes);
3693
3694       qtdemux->cenc_aux_info_sizes =
3695           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3696           &qtdemux->cenc_aux_sample_count);
3697       if (qtdemux->cenc_aux_info_sizes == NULL) {
3698         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3699         goto fail;
3700       }
3701       saio_node =
3702           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3703           &saio_data);
3704       if (!saio_node) {
3705         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3706         g_free (qtdemux->cenc_aux_info_sizes);
3707         qtdemux->cenc_aux_info_sizes = NULL;
3708         goto fail;
3709       }
3710
3711       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3712                   &info_type, &info_type_parameter, &offset))) {
3713         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3714         g_free (qtdemux->cenc_aux_info_sizes);
3715         qtdemux->cenc_aux_info_sizes = NULL;
3716         goto fail;
3717       }
3718       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3719         offset += (guint64) (base_offset - qtdemux->moof_offset);
3720       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3721         GstByteReader br;
3722         if (offset > length) {
3723           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3724           qtdemux->cenc_aux_info_offset = offset;
3725         } else {
3726           gst_byte_reader_init (&br, buffer + offset, length - offset);
3727           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3728                   qtdemux->cenc_aux_info_sizes,
3729                   qtdemux->cenc_aux_sample_count)) {
3730             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3731             g_free (qtdemux->cenc_aux_info_sizes);
3732             qtdemux->cenc_aux_info_sizes = NULL;
3733             goto fail;
3734           }
3735         }
3736       }
3737     }
3738
3739     tfdt_node =
3740         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3741         &tfdt_data);
3742     if (tfdt_node) {
3743       GstClockTime decode_time_ts;
3744
3745       /* We'll use decode_time to interpolate timestamps
3746        * in case the input timestamps are missing */
3747       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3748
3749       decode_time_ts = QTSTREAMTIME_TO_GSTTIME (stream, decode_time);
3750
3751       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3752           " (%" GST_TIME_FORMAT ")", decode_time,
3753           GST_TIME_ARGS (decode_time_ts));
3754
3755       /* Discard the fragment buffer timestamp info to avoid using it.
3756        * Rely on tfdt instead as it is more accurate than the timestamp
3757        * that is fetched from a manifest/playlist and is usually
3758        * less accurate. */
3759       qtdemux->fragment_start = -1;
3760     }
3761
3762     if (G_UNLIKELY (!stream)) {
3763       /* we lost track of offset, we'll need to regain it,
3764        * but can delay complaining until later or avoid doing so altogether */
3765       base_offset = -2;
3766       goto next;
3767     }
3768     if (G_UNLIKELY (base_offset < -1))
3769       goto lost_offset;
3770
3771     if (qtdemux->upstream_format_is_time)
3772       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3773
3774     /* initialise moof sample data */
3775     stream->n_samples_moof = 0;
3776     stream->duration_moof = 0;
3777
3778     /* Track Run node */
3779     trun_node =
3780         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3781         &trun_data);
3782     while (trun_node) {
3783       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3784           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3785           &running_offset, decode_time);
3786       /* iterate all siblings */
3787       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3788           &trun_data);
3789     }
3790
3791     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3792     if (uuid_node) {
3793       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3794       guint32 box_length = QT_UINT32 (uuid_buffer);
3795
3796       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3797     }
3798
3799     /* if no new base_offset provided for next traf,
3800      * base is end of current traf */
3801     base_offset = running_offset;
3802     running_offset = -1;
3803
3804     if (stream->n_samples_moof && stream->duration_moof)
3805       stream->new_caps = TRUE;
3806
3807   next:
3808     /* iterate all siblings */
3809     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3810   }
3811
3812   /* parse any protection system info */
3813   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3814   while (pssh_node) {
3815     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3816     qtdemux_parse_pssh (qtdemux, pssh_node);
3817     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3818   }
3819
3820   g_node_destroy (moof_node);
3821   return TRUE;
3822
3823 missing_tfhd:
3824   {
3825     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3826     goto fail;
3827   }
3828 missing_mfhd:
3829   {
3830     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3831     goto fail;
3832   }
3833 lost_offset:
3834   {
3835     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3836     goto fail;
3837   }
3838 fail:
3839   {
3840     g_node_destroy (moof_node);
3841     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3842         (_("This file is corrupt and cannot be played.")), (NULL));
3843     return FALSE;
3844   }
3845 }
3846
3847 #if 0
3848 /* might be used if some day we actually use mfra & co
3849  * for random access to fragments,
3850  * but that will require quite some modifications and much less relying
3851  * on a sample array */
3852 #endif
3853
3854 static gboolean
3855 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3856 {
3857   QtDemuxStream *stream;
3858   guint32 ver_flags, track_id, len, num_entries, i;
3859   guint value_size, traf_size, trun_size, sample_size;
3860   guint64 time = 0, moof_offset = 0;
3861 #if 0
3862   GstBuffer *buf = NULL;
3863   GstFlowReturn ret;
3864 #endif
3865   GstByteReader tfra;
3866
3867   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3868
3869   if (!gst_byte_reader_skip (&tfra, 8))
3870     return FALSE;
3871
3872   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3873     return FALSE;
3874
3875   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3876       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3877       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3878     return FALSE;
3879
3880   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3881
3882   stream = qtdemux_find_stream (qtdemux, track_id);
3883   if (stream == NULL)
3884     goto unknown_trackid;
3885
3886   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3887   sample_size = (len & 3) + 1;
3888   trun_size = ((len & 12) >> 2) + 1;
3889   traf_size = ((len & 48) >> 4) + 1;
3890
3891   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3892       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3893
3894   if (num_entries == 0)
3895     goto no_samples;
3896
3897   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3898           value_size + value_size + traf_size + trun_size + sample_size))
3899     goto corrupt_file;
3900
3901   g_free (stream->ra_entries);
3902   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3903   stream->n_ra_entries = num_entries;
3904
3905   for (i = 0; i < num_entries; i++) {
3906     qt_atom_parser_get_offset (&tfra, value_size, &time);
3907     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3908     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3909     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3910     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3911
3912     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3913
3914     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3915         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3916
3917     stream->ra_entries[i].ts = time;
3918     stream->ra_entries[i].moof_offset = moof_offset;
3919
3920     /* don't want to go through the entire file and read all moofs at startup */
3921 #if 0
3922     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3923     if (ret != GST_FLOW_OK)
3924       goto corrupt_file;
3925     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3926         moof_offset, stream);
3927     gst_buffer_unref (buf);
3928 #endif
3929   }
3930
3931   check_update_duration (qtdemux, time);
3932
3933   return TRUE;
3934
3935 /* ERRORS */
3936 unknown_trackid:
3937   {
3938     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3939     return FALSE;
3940   }
3941 corrupt_file:
3942   {
3943     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3944     return FALSE;
3945   }
3946 no_samples:
3947   {
3948     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3949     return FALSE;
3950   }
3951 }
3952
3953 static gboolean
3954 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3955 {
3956   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3957   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3958   GstBuffer *mfro = NULL, *mfra = NULL;
3959   GstFlowReturn flow;
3960   gboolean ret = FALSE;
3961   GNode *mfra_node, *tfra_node;
3962   guint64 mfra_offset = 0;
3963   guint32 fourcc, mfra_size;
3964   gint64 len;
3965
3966   /* query upstream size in bytes */
3967   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3968     goto size_query_failed;
3969
3970   /* mfro box should be at the very end of the file */
3971   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3972   if (flow != GST_FLOW_OK)
3973     goto exit;
3974
3975   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3976
3977   fourcc = QT_FOURCC (mfro_map.data + 4);
3978   if (fourcc != FOURCC_mfro)
3979     goto exit;
3980
3981   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3982   if (mfro_map.size < 16)
3983     goto invalid_mfro_size;
3984
3985   mfra_size = QT_UINT32 (mfro_map.data + 12);
3986   if (mfra_size >= len)
3987     goto invalid_mfra_size;
3988
3989   mfra_offset = len - mfra_size;
3990
3991   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
3992       mfra_offset, mfra_size);
3993
3994   /* now get and parse mfra box */
3995   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
3996   if (flow != GST_FLOW_OK)
3997     goto broken_file;
3998
3999   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4000
4001   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4002   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4003
4004   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4005
4006   while (tfra_node) {
4007     qtdemux_parse_tfra (qtdemux, tfra_node);
4008     /* iterate all siblings */
4009     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4010   }
4011   g_node_destroy (mfra_node);
4012
4013   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4014   ret = TRUE;
4015
4016 exit:
4017
4018   if (mfro) {
4019     if (mfro_map.memory != NULL)
4020       gst_buffer_unmap (mfro, &mfro_map);
4021     gst_buffer_unref (mfro);
4022   }
4023   if (mfra) {
4024     if (mfra_map.memory != NULL)
4025       gst_buffer_unmap (mfra, &mfra_map);
4026     gst_buffer_unref (mfra);
4027   }
4028   return ret;
4029
4030 /* ERRORS */
4031 size_query_failed:
4032   {
4033     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4034     goto exit;
4035   }
4036 invalid_mfro_size:
4037   {
4038     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4039     goto exit;
4040   }
4041 invalid_mfra_size:
4042   {
4043     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4044     goto exit;
4045   }
4046 broken_file:
4047   {
4048     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4049     goto exit;
4050   }
4051 }
4052
4053 static guint64
4054 add_offset (guint64 offset, guint64 advance)
4055 {
4056   /* Avoid 64-bit overflow by clamping */
4057   if (offset > G_MAXUINT64 - advance)
4058     return G_MAXUINT64;
4059   return offset + advance;
4060 }
4061
4062 static GstFlowReturn
4063 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4064 {
4065   guint64 length = 0;
4066   guint32 fourcc = 0;
4067   GstBuffer *buf = NULL;
4068   GstFlowReturn ret = GST_FLOW_OK;
4069   guint64 cur_offset = qtdemux->offset;
4070   GstMapInfo map;
4071
4072   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4073   if (G_UNLIKELY (ret != GST_FLOW_OK))
4074     goto beach;
4075   gst_buffer_map (buf, &map, GST_MAP_READ);
4076   if (G_LIKELY (map.size >= 8))
4077     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4078   gst_buffer_unmap (buf, &map);
4079   gst_buffer_unref (buf);
4080
4081   /* maybe we already got most we needed, so only consider this eof */
4082   if (G_UNLIKELY (length == 0)) {
4083     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4084         (_("Invalid atom size.")),
4085         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4086             GST_FOURCC_ARGS (fourcc)));
4087     ret = GST_FLOW_EOS;
4088     goto beach;
4089   }
4090
4091   switch (fourcc) {
4092     case FOURCC_moof:
4093       /* record for later parsing when needed */
4094       if (!qtdemux->moof_offset) {
4095         qtdemux->moof_offset = qtdemux->offset;
4096       }
4097       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4098         /* FIXME */
4099       } else {
4100         qtdemux->offset += length;      /* skip moof and keep going */
4101       }
4102       if (qtdemux->got_moov) {
4103         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4104         ret = GST_FLOW_EOS;
4105         goto beach;
4106       }
4107       break;
4108     case FOURCC_mdat:
4109     case FOURCC_free:
4110     case FOURCC_wide:
4111     case FOURCC_PICT:
4112     case FOURCC_pnot:
4113     {
4114       GST_LOG_OBJECT (qtdemux,
4115           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4116           GST_FOURCC_ARGS (fourcc), cur_offset);
4117       qtdemux->offset = add_offset (qtdemux->offset, length);
4118       break;
4119     }
4120     case FOURCC_moov:
4121     {
4122       GstBuffer *moov = NULL;
4123
4124       if (qtdemux->got_moov) {
4125         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4126         qtdemux->offset = add_offset (qtdemux->offset, length);
4127         goto beach;
4128       }
4129
4130       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4131       if (ret != GST_FLOW_OK)
4132         goto beach;
4133       gst_buffer_map (moov, &map, GST_MAP_READ);
4134
4135       if (length != map.size) {
4136         /* Some files have a 'moov' atom at the end of the file which contains
4137          * a terminal 'free' atom where the body of the atom is missing.
4138          * Check for, and permit, this special case.
4139          */
4140         if (map.size >= 8) {
4141           guint8 *final_data = map.data + (map.size - 8);
4142           guint32 final_length = QT_UINT32 (final_data);
4143           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4144
4145           if (final_fourcc == FOURCC_free
4146               && map.size + final_length - 8 == length) {
4147             /* Ok, we've found that special case. Allocate a new buffer with
4148              * that free atom actually present. */
4149             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4150             gst_buffer_fill (newmoov, 0, map.data, map.size);
4151             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4152             gst_buffer_unmap (moov, &map);
4153             gst_buffer_unref (moov);
4154             moov = newmoov;
4155             gst_buffer_map (moov, &map, GST_MAP_READ);
4156           }
4157         }
4158       }
4159
4160       if (length != map.size) {
4161         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4162             (_("This file is incomplete and cannot be played.")),
4163             ("We got less than expected (received %" G_GSIZE_FORMAT
4164                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4165                 (guint) length, cur_offset));
4166         gst_buffer_unmap (moov, &map);
4167         gst_buffer_unref (moov);
4168         ret = GST_FLOW_ERROR;
4169         goto beach;
4170       }
4171       qtdemux->offset += length;
4172
4173       qtdemux_parse_moov (qtdemux, map.data, length);
4174       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4175
4176       qtdemux_parse_tree (qtdemux);
4177       g_node_destroy (qtdemux->moov_node);
4178       gst_buffer_unmap (moov, &map);
4179       gst_buffer_unref (moov);
4180       qtdemux->moov_node = NULL;
4181       qtdemux->got_moov = TRUE;
4182
4183       break;
4184     }
4185     case FOURCC_ftyp:
4186     {
4187       GstBuffer *ftyp = NULL;
4188
4189       /* extract major brand; might come in handy for ISO vs QT issues */
4190       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4191       if (ret != GST_FLOW_OK)
4192         goto beach;
4193       qtdemux->offset += length;
4194       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4195       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4196       gst_buffer_unmap (ftyp, &map);
4197       gst_buffer_unref (ftyp);
4198       break;
4199     }
4200     case FOURCC_uuid:
4201     {
4202       GstBuffer *uuid = NULL;
4203
4204       /* uuid are extension atoms */
4205       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4206       if (ret != GST_FLOW_OK)
4207         goto beach;
4208       qtdemux->offset += length;
4209       gst_buffer_map (uuid, &map, GST_MAP_READ);
4210       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4211       gst_buffer_unmap (uuid, &map);
4212       gst_buffer_unref (uuid);
4213       break;
4214     }
4215     case FOURCC_sidx:
4216     {
4217       GstBuffer *sidx = NULL;
4218       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4219       if (ret != GST_FLOW_OK)
4220         goto beach;
4221       qtdemux->offset += length;
4222       gst_buffer_map (sidx, &map, GST_MAP_READ);
4223       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4224       gst_buffer_unmap (sidx, &map);
4225       gst_buffer_unref (sidx);
4226       break;
4227     }
4228     default:
4229     {
4230       GstBuffer *unknown = NULL;
4231
4232       GST_LOG_OBJECT (qtdemux,
4233           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4234           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4235           cur_offset);
4236       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4237       if (ret != GST_FLOW_OK)
4238         goto beach;
4239       gst_buffer_map (unknown, &map, GST_MAP_READ);
4240       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4241       gst_buffer_unmap (unknown, &map);
4242       gst_buffer_unref (unknown);
4243       qtdemux->offset += length;
4244       break;
4245     }
4246   }
4247
4248 beach:
4249   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4250     /* digested all data, show what we have */
4251     qtdemux_prepare_streams (qtdemux);
4252     ret = qtdemux_expose_streams (qtdemux);
4253
4254     qtdemux->state = QTDEMUX_STATE_MOVIE;
4255     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4256         qtdemux->state);
4257     return ret;
4258   }
4259   return ret;
4260 }
4261
4262 /* Seeks to the previous keyframe of the indexed stream and
4263  * aligns other streams with respect to the keyframe timestamp
4264  * of indexed stream. Only called in case of Reverse Playback
4265  */
4266 static GstFlowReturn
4267 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4268 {
4269   guint8 n = 0;
4270   guint32 seg_idx = 0, k_index = 0;
4271   guint32 ref_seg_idx, ref_k_index;
4272   GstClockTime k_pos = 0, last_stop = 0;
4273   QtDemuxSegment *seg = NULL;
4274   QtDemuxStream *ref_str = NULL;
4275   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4276   guint64 target_ts;
4277
4278   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4279    * and finally align all the other streams on that timestamp with their
4280    * respective keyframes */
4281   for (n = 0; n < qtdemux->n_streams; n++) {
4282     QtDemuxStream *str = qtdemux->streams[n];
4283
4284     /* No candidate yet, take the first stream */
4285     if (!ref_str) {
4286       ref_str = str;
4287       continue;
4288     }
4289
4290     /* So that stream has a segment, we prefer video streams */
4291     if (str->subtype == FOURCC_vide) {
4292       ref_str = str;
4293       break;
4294     }
4295   }
4296
4297   if (G_UNLIKELY (!ref_str)) {
4298     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4299     goto eos;
4300   }
4301
4302   if (G_UNLIKELY (!ref_str->from_sample)) {
4303     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4304     goto eos;
4305   }
4306
4307   /* So that stream has been playing from from_sample to to_sample. We will
4308    * get the timestamp of the previous sample and search for a keyframe before
4309    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4310   if (ref_str->subtype == FOURCC_vide) {
4311     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4312         ref_str->from_sample - 1);
4313   } else {
4314     if (ref_str->from_sample >= 10)
4315       k_index = ref_str->from_sample - 10;
4316     else
4317       k_index = 0;
4318   }
4319
4320   target_ts =
4321       ref_str->samples[k_index].timestamp +
4322       ref_str->samples[k_index].pts_offset;
4323
4324   /* get current segment for that stream */
4325   seg = &ref_str->segments[ref_str->segment_index];
4326   /* Use segment start in original timescale for comparisons */
4327   seg_media_start_mov = seg->trak_media_start;
4328
4329   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4330       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4331       k_index, target_ts, seg_media_start_mov,
4332       GST_TIME_ARGS (seg->media_start));
4333
4334   /* Crawl back through segments to find the one containing this I frame */
4335   while (target_ts < seg_media_start_mov) {
4336     GST_DEBUG_OBJECT (qtdemux,
4337         "keyframe position (sample %u) is out of segment %u " " target %"
4338         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4339         ref_str->segment_index, target_ts, seg_media_start_mov);
4340
4341     if (G_UNLIKELY (!ref_str->segment_index)) {
4342       /* Reached first segment, let's consider it's EOS */
4343       goto eos;
4344     }
4345     ref_str->segment_index--;
4346     seg = &ref_str->segments[ref_str->segment_index];
4347     /* Use segment start in original timescale for comparisons */
4348     seg_media_start_mov = seg->trak_media_start;
4349   }
4350   /* Calculate time position of the keyframe and where we should stop */
4351   k_pos =
4352       QTSTREAMTIME_TO_GSTTIME (ref_str,
4353       target_ts - seg->trak_media_start) + seg->time;
4354   last_stop =
4355       QTSTREAMTIME_TO_GSTTIME (ref_str,
4356       ref_str->samples[ref_str->from_sample].timestamp -
4357       seg->trak_media_start) + seg->time;
4358
4359   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4360       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4361       k_index, GST_TIME_ARGS (k_pos));
4362
4363   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4364   qtdemux->segment.position = last_stop;
4365   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4366       GST_TIME_ARGS (last_stop));
4367
4368   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4369     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4370     goto eos;
4371   }
4372
4373   ref_seg_idx = ref_str->segment_index;
4374   ref_k_index = k_index;
4375
4376   /* Align them all on this */
4377   for (n = 0; n < qtdemux->n_streams; n++) {
4378     guint32 index = 0;
4379     GstClockTime seg_time = 0;
4380     QtDemuxStream *str = qtdemux->streams[n];
4381
4382     /* aligning reference stream again might lead to backing up to yet another
4383      * keyframe (due to timestamp rounding issues),
4384      * potentially putting more load on downstream; so let's try to avoid */
4385     if (str == ref_str) {
4386       seg_idx = ref_seg_idx;
4387       seg = &str->segments[seg_idx];
4388       k_index = ref_k_index;
4389       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4390           "sample at index %d", n, ref_str->segment_index, k_index);
4391     } else {
4392       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4393       GST_DEBUG_OBJECT (qtdemux,
4394           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4395           seg_idx, GST_TIME_ARGS (k_pos));
4396
4397       /* get segment and time in the segment */
4398       seg = &str->segments[seg_idx];
4399       seg_time = k_pos - seg->time;
4400
4401       /* get the media time in the segment.
4402        * No adjustment for empty "filler" segments */
4403       if (seg->media_start != GST_CLOCK_TIME_NONE)
4404         seg_time += seg->media_start;
4405
4406       /* get the index of the sample with media time */
4407       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4408       GST_DEBUG_OBJECT (qtdemux,
4409           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4410           GST_TIME_ARGS (seg_time), index);
4411
4412       /* find previous keyframe */
4413       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4414     }
4415
4416     /* Remember until where we want to go */
4417     str->to_sample = str->from_sample - 1;
4418     /* Define our time position */
4419     target_ts =
4420         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4421     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4422     if (seg->media_start != GST_CLOCK_TIME_NONE)
4423       str->time_position -= seg->media_start;
4424
4425     /* Now seek back in time */
4426     gst_qtdemux_move_stream (qtdemux, str, k_index);
4427     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4428         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4429         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4430   }
4431
4432   return GST_FLOW_OK;
4433
4434 eos:
4435   return GST_FLOW_EOS;
4436 }
4437
4438 /*
4439  * Gets the current qt segment start, stop and position for the
4440  * given time offset. This is used in update_segment()
4441  */
4442 static void
4443 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4444     QtDemuxStream * stream, GstClockTime offset,
4445     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4446 {
4447   GstClockTime seg_time;
4448   GstClockTime start, stop, time;
4449   QtDemuxSegment *segment;
4450
4451   segment = &stream->segments[stream->segment_index];
4452
4453   /* get time in this segment */
4454   seg_time = (offset - segment->time) * segment->rate;
4455
4456   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4457       GST_TIME_ARGS (seg_time));
4458
4459   if (G_UNLIKELY (seg_time > segment->duration)) {
4460     GST_LOG_OBJECT (stream->pad,
4461         "seg_time > segment->duration %" GST_TIME_FORMAT,
4462         GST_TIME_ARGS (segment->duration));
4463     seg_time = segment->duration;
4464   }
4465
4466   /* qtdemux->segment.stop is in outside-time-realm, whereas
4467    * segment->media_stop is in track-time-realm.
4468    *
4469    * In order to compare the two, we need to bring segment.stop
4470    * into the track-time-realm
4471    *
4472    * FIXME - does this comment still hold? Don't see any conversion here */
4473
4474   stop = qtdemux->segment.stop;
4475   if (stop == GST_CLOCK_TIME_NONE)
4476     stop = qtdemux->segment.duration;
4477   if (stop == GST_CLOCK_TIME_NONE)
4478     stop = segment->media_stop;
4479   else
4480     stop =
4481         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4482
4483   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4484     start = segment->time + seg_time;
4485     time = offset;
4486     stop = start - seg_time + segment->duration;
4487   } else if (qtdemux->segment.rate >= 0) {
4488     start = MIN (segment->media_start + seg_time, stop);
4489     time = offset;
4490   } else {
4491     if (segment->media_start >= qtdemux->segment.start) {
4492       time = segment->time;
4493     } else {
4494       time = segment->time + (qtdemux->segment.start - segment->media_start);
4495     }
4496
4497     start = MAX (segment->media_start, qtdemux->segment.start);
4498     stop = MIN (segment->media_start + seg_time, stop);
4499   }
4500
4501   *_start = start;
4502   *_stop = stop;
4503   *_time = time;
4504 }
4505
4506 /*
4507  * Updates the qt segment used for the stream and pushes a new segment event
4508  * downstream on this stream's pad.
4509  */
4510 static gboolean
4511 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4512     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4513     GstClockTime * _stop)
4514 {
4515   QtDemuxSegment *segment;
4516   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4517   gdouble rate;
4518   GstEvent *event;
4519
4520   /* update the current segment */
4521   stream->segment_index = seg_idx;
4522
4523   /* get the segment */
4524   segment = &stream->segments[seg_idx];
4525
4526   if (G_UNLIKELY (offset < segment->time)) {
4527     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4528         GST_TIME_ARGS (segment->time));
4529     return FALSE;
4530   }
4531
4532   /* segment lies beyond total indicated duration */
4533   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4534           segment->time > qtdemux->segment.duration)) {
4535     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4536         " < segment->time %" GST_TIME_FORMAT,
4537         GST_TIME_ARGS (qtdemux->segment.duration),
4538         GST_TIME_ARGS (segment->time));
4539     return FALSE;
4540   }
4541
4542   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4543       &start, &stop, &time);
4544
4545   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4546       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4547       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4548
4549   /* combine global rate with that of the segment */
4550   rate = segment->rate * qtdemux->segment.rate;
4551
4552   /* Copy flags from main segment */
4553   stream->segment.flags = qtdemux->segment.flags;
4554
4555   /* update the segment values used for clipping */
4556   stream->segment.offset = qtdemux->segment.offset;
4557   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4558   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4559   stream->segment.rate = rate;
4560   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4561       stream->cslg_shift);
4562   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4563       stream->cslg_shift);
4564   stream->segment.time = time;
4565   stream->segment.position = stream->segment.start;
4566
4567   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4568       &stream->segment);
4569
4570   /* now prepare and send the segment */
4571   if (stream->pad) {
4572     event = gst_event_new_segment (&stream->segment);
4573     if (qtdemux->segment_seqnum) {
4574       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4575     }
4576     gst_pad_push_event (stream->pad, event);
4577     /* assume we can send more data now */
4578     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4579     /* clear to send tags on this pad now */
4580     gst_qtdemux_push_tags (qtdemux, stream);
4581   }
4582
4583   if (_start)
4584     *_start = start;
4585   if (_stop)
4586     *_stop = stop;
4587
4588   return TRUE;
4589 }
4590
4591 /* activate the given segment number @seg_idx of @stream at time @offset.
4592  * @offset is an absolute global position over all the segments.
4593  *
4594  * This will push out a NEWSEGMENT event with the right values and
4595  * position the stream index to the first decodable sample before
4596  * @offset.
4597  */
4598 static gboolean
4599 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4600     guint32 seg_idx, GstClockTime offset)
4601 {
4602   QtDemuxSegment *segment;
4603   guint32 index, kf_index;
4604   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4605
4606   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4607       seg_idx, GST_TIME_ARGS (offset));
4608
4609   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4610           &start, &stop))
4611     return FALSE;
4612
4613   segment = &stream->segments[stream->segment_index];
4614
4615   /* in the fragmented case, we pick a fragment that starts before our
4616    * desired position and rely on downstream to wait for a keyframe
4617    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4618    * tfra entries tells us which trun/sample the key unit is in, but we don't
4619    * make use of this additional information at the moment) */
4620   if (qtdemux->fragmented) {
4621     stream->to_sample = G_MAXUINT32;
4622     return TRUE;
4623   }
4624
4625   /* We don't need to look for a sample in push-based */
4626   if (!qtdemux->pullbased)
4627     return TRUE;
4628
4629   /* and move to the keyframe before the indicated media time of the
4630    * segment */
4631   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4632     if (qtdemux->segment.rate >= 0) {
4633       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4634       stream->to_sample = G_MAXUINT32;
4635       GST_DEBUG_OBJECT (stream->pad,
4636           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4637           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4638           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4639     } else {
4640       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4641       stream->to_sample = index;
4642       GST_DEBUG_OBJECT (stream->pad,
4643           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4644           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4645           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4646     }
4647   } else {
4648     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4649         "this is an empty segment");
4650     return TRUE;
4651   }
4652
4653   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4654    * encountered an error and printed a message so we return appropriately */
4655   if (index == -1)
4656     return FALSE;
4657
4658   /* we're at the right spot */
4659   if (index == stream->sample_index) {
4660     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4661     return TRUE;
4662   }
4663
4664   /* find keyframe of the target index */
4665   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4666
4667 /* *INDENT-OFF* */
4668 /* indent does stupid stuff with stream->samples[].timestamp */
4669
4670   /* if we move forwards, we don't have to go back to the previous
4671    * keyframe since we already sent that. We can also just jump to
4672    * the keyframe right before the target index if there is one. */
4673   if (index > stream->sample_index) {
4674     /* moving forwards check if we move past a keyframe */
4675     if (kf_index > stream->sample_index) {
4676       GST_DEBUG_OBJECT (stream->pad,
4677            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4678            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4679            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4680       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4681     } else {
4682       GST_DEBUG_OBJECT (stream->pad,
4683           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4684           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4685           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4686     }
4687   } else {
4688     GST_DEBUG_OBJECT (stream->pad,
4689         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4690         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4691         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4692     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4693   }
4694
4695 /* *INDENT-ON* */
4696
4697   return TRUE;
4698 }
4699
4700 /* prepare to get the current sample of @stream, getting essential values.
4701  *
4702  * This function will also prepare and send the segment when needed.
4703  *
4704  * Return FALSE if the stream is EOS.
4705  *
4706  * PULL-BASED
4707  */
4708 static gboolean
4709 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4710     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4711     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4712     gboolean * keyframe)
4713 {
4714   QtDemuxSample *sample;
4715   GstClockTime time_position;
4716   guint32 seg_idx;
4717
4718   g_return_val_if_fail (stream != NULL, FALSE);
4719
4720   time_position = stream->time_position;
4721   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4722     goto eos;
4723
4724   seg_idx = stream->segment_index;
4725   if (G_UNLIKELY (seg_idx == -1)) {
4726     /* find segment corresponding to time_position if we are looking
4727      * for a segment. */
4728     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4729   }
4730
4731   /* different segment, activate it, sample_index will be set. */
4732   if (G_UNLIKELY (stream->segment_index != seg_idx))
4733     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4734
4735   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4736                   segment_index]))) {
4737     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4738
4739     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4740         " prepare empty sample");
4741
4742     *empty = TRUE;
4743     *pts = *dts = time_position;
4744     *duration = seg->duration - (time_position - seg->time);
4745
4746     return TRUE;
4747   }
4748
4749   *empty = FALSE;
4750
4751   if (stream->sample_index == -1)
4752     stream->sample_index = 0;
4753
4754   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4755       stream->sample_index, stream->n_samples);
4756
4757   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4758     if (!qtdemux->fragmented)
4759       goto eos;
4760
4761     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4762     do {
4763       GstFlowReturn flow;
4764
4765       GST_OBJECT_LOCK (qtdemux);
4766       flow = qtdemux_add_fragmented_samples (qtdemux);
4767       GST_OBJECT_UNLOCK (qtdemux);
4768
4769       if (flow != GST_FLOW_OK)
4770         goto eos;
4771     }
4772     while (stream->sample_index >= stream->n_samples);
4773   }
4774
4775   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4776     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4777         stream->sample_index);
4778     return FALSE;
4779   }
4780
4781   /* now get the info for the sample we're at */
4782   sample = &stream->samples[stream->sample_index];
4783
4784   *dts = QTSAMPLE_DTS (stream, sample);
4785   *pts = QTSAMPLE_PTS (stream, sample);
4786   *offset = sample->offset;
4787   *size = sample->size;
4788   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4789   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4790
4791   return TRUE;
4792
4793   /* special cases */
4794 eos:
4795   {
4796     stream->time_position = GST_CLOCK_TIME_NONE;
4797     return FALSE;
4798   }
4799 }
4800
4801 /* move to the next sample in @stream.
4802  *
4803  * Moves to the next segment when needed.
4804  */
4805 static void
4806 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4807 {
4808   QtDemuxSample *sample;
4809   QtDemuxSegment *segment;
4810
4811   /* get current segment */
4812   segment = &stream->segments[stream->segment_index];
4813
4814   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4815     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4816     goto next_segment;
4817   }
4818
4819   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4820     /* Mark the stream as EOS */
4821     GST_DEBUG_OBJECT (qtdemux,
4822         "reached max allowed sample %u, mark EOS", stream->to_sample);
4823     stream->time_position = GST_CLOCK_TIME_NONE;
4824     return;
4825   }
4826
4827   /* move to next sample */
4828   stream->sample_index++;
4829   stream->offset_in_sample = 0;
4830
4831   /* reached the last sample, we need the next segment */
4832   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4833     goto next_segment;
4834
4835   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4836     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4837         stream->sample_index);
4838     return;
4839   }
4840
4841   /* get next sample */
4842   sample = &stream->samples[stream->sample_index];
4843
4844   /* see if we are past the segment */
4845   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4846     goto next_segment;
4847
4848   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4849     /* inside the segment, update time_position, looks very familiar to
4850      * GStreamer segments, doesn't it? */
4851     stream->time_position =
4852         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4853   } else {
4854     /* not yet in segment, time does not yet increment. This means
4855      * that we are still prerolling keyframes to the decoder so it can
4856      * decode the first sample of the segment. */
4857     stream->time_position = segment->time;
4858   }
4859   return;
4860
4861   /* move to the next segment */
4862 next_segment:
4863   {
4864     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4865
4866     if (stream->segment_index == stream->n_segments - 1) {
4867       /* are we at the end of the last segment, we're EOS */
4868       stream->time_position = GST_CLOCK_TIME_NONE;
4869     } else {
4870       /* else we're only at the end of the current segment */
4871       stream->time_position = segment->stop_time;
4872     }
4873     /* make sure we select a new segment */
4874
4875     /* accumulate previous segments */
4876     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4877       stream->accumulated_base +=
4878           (stream->segment.stop -
4879           stream->segment.start) / ABS (stream->segment.rate);
4880
4881     stream->segment_index = -1;
4882   }
4883 }
4884
4885 static void
4886 gst_qtdemux_sync_streams (GstQTDemux * demux)
4887 {
4888   gint i;
4889
4890   if (demux->n_streams <= 1)
4891     return;
4892
4893   for (i = 0; i < demux->n_streams; i++) {
4894     QtDemuxStream *stream;
4895     GstClockTime end_time;
4896
4897     stream = demux->streams[i];
4898
4899     if (!stream->pad)
4900       continue;
4901
4902     /* TODO advance time on subtitle streams here, if any some day */
4903
4904     /* some clips/trailers may have unbalanced streams at the end,
4905      * so send EOS on shorter stream to prevent stalling others */
4906
4907     /* do not mess with EOS if SEGMENT seeking */
4908     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4909       continue;
4910
4911     if (demux->pullbased) {
4912       /* loop mode is sample time based */
4913       if (!STREAM_IS_EOS (stream))
4914         continue;
4915     } else {
4916       /* push mode is byte position based */
4917       if (stream->n_samples &&
4918           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4919         continue;
4920     }
4921
4922     if (stream->sent_eos)
4923       continue;
4924
4925     /* only act if some gap */
4926     end_time = stream->segments[stream->n_segments - 1].stop_time;
4927     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4928         ", stream end: %" GST_TIME_FORMAT,
4929         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4930     if (GST_CLOCK_TIME_IS_VALID (end_time)
4931         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4932       GstEvent *event;
4933
4934       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4935           GST_PAD_NAME (stream->pad));
4936       stream->sent_eos = TRUE;
4937       event = gst_event_new_eos ();
4938       if (demux->segment_seqnum)
4939         gst_event_set_seqnum (event, demux->segment_seqnum);
4940       gst_pad_push_event (stream->pad, event);
4941     }
4942   }
4943 }
4944
4945 /* EOS and NOT_LINKED need to be combined. This means that we return:
4946  *
4947  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4948  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4949  */
4950 static GstFlowReturn
4951 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4952     GstFlowReturn ret)
4953 {
4954   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4955
4956   if (stream->pad)
4957     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4958         ret);
4959   else
4960     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4961
4962   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4963   return ret;
4964 }
4965
4966 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4967  * completely clipped
4968  *
4969  * Should be used only with raw buffers */
4970 static GstBuffer *
4971 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4972     GstBuffer * buf)
4973 {
4974   guint64 start, stop, cstart, cstop, diff;
4975   GstClockTime pts, duration;
4976   gsize size, osize;
4977   gint num_rate, denom_rate;
4978   gint frame_size;
4979   gboolean clip_data;
4980   guint offset;
4981
4982   osize = size = gst_buffer_get_size (buf);
4983   offset = 0;
4984
4985   /* depending on the type, setup the clip parameters */
4986   if (stream->subtype == FOURCC_soun) {
4987     frame_size = stream->bytes_per_frame;
4988     num_rate = GST_SECOND;
4989     denom_rate = (gint) stream->rate;
4990     clip_data = TRUE;
4991   } else if (stream->subtype == FOURCC_vide) {
4992     frame_size = size;
4993     num_rate = stream->fps_n;
4994     denom_rate = stream->fps_d;
4995     clip_data = FALSE;
4996   } else
4997     goto wrong_type;
4998
4999   if (frame_size <= 0)
5000     goto bad_frame_size;
5001
5002   /* we can only clip if we have a valid pts */
5003   pts = GST_BUFFER_PTS (buf);
5004   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5005     goto no_pts;
5006
5007   duration = GST_BUFFER_DURATION (buf);
5008
5009   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5010     duration =
5011         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5012   }
5013
5014   start = pts;
5015   stop = start + duration;
5016
5017   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5018               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5019     goto clipped;
5020
5021   /* see if some clipping happened */
5022   diff = cstart - start;
5023   if (diff > 0) {
5024     pts += diff;
5025     duration -= diff;
5026
5027     if (clip_data) {
5028       /* bring clipped time to samples and to bytes */
5029       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5030       diff *= frame_size;
5031
5032       GST_DEBUG_OBJECT (qtdemux,
5033           "clipping start to %" GST_TIME_FORMAT " %"
5034           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5035
5036       offset = diff;
5037       size -= diff;
5038     }
5039   }
5040   diff = stop - cstop;
5041   if (diff > 0) {
5042     duration -= diff;
5043
5044     if (clip_data) {
5045       /* bring clipped time to samples and then to bytes */
5046       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5047       diff *= frame_size;
5048       GST_DEBUG_OBJECT (qtdemux,
5049           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5050           " bytes", GST_TIME_ARGS (cstop), diff);
5051       size -= diff;
5052     }
5053   }
5054
5055   if (offset != 0 || size != osize)
5056     gst_buffer_resize (buf, offset, size);
5057
5058   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5059   GST_BUFFER_PTS (buf) = pts;
5060   GST_BUFFER_DURATION (buf) = duration;
5061
5062   return buf;
5063
5064   /* dropped buffer */
5065 wrong_type:
5066   {
5067     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5068     return buf;
5069   }
5070 bad_frame_size:
5071   {
5072     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5073     return buf;
5074   }
5075 no_pts:
5076   {
5077     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5078     return buf;
5079   }
5080 clipped:
5081   {
5082     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5083     gst_buffer_unref (buf);
5084     return NULL;
5085   }
5086 }
5087
5088 /* the input buffer metadata must be writable,
5089  * but time/duration etc not yet set and need not be preserved */
5090 static GstBuffer *
5091 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5092     GstBuffer * buf)
5093 {
5094   GstMapInfo map;
5095   guint nsize = 0;
5096   gchar *str;
5097
5098   /* not many cases for now */
5099   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5100     /* send a one time dvd clut event */
5101     if (stream->pending_event && stream->pad)
5102       gst_pad_push_event (stream->pad, stream->pending_event);
5103     stream->pending_event = NULL;
5104   }
5105
5106   if (G_UNLIKELY (stream->subtype != FOURCC_text
5107           && stream->subtype != FOURCC_sbtl &&
5108           stream->subtype != FOURCC_subp)) {
5109     return buf;
5110   }
5111
5112   gst_buffer_map (buf, &map, GST_MAP_READ);
5113
5114   /* empty buffer is sent to terminate previous subtitle */
5115   if (map.size <= 2) {
5116     gst_buffer_unmap (buf, &map);
5117     gst_buffer_unref (buf);
5118     return NULL;
5119   }
5120   if (stream->subtype == FOURCC_subp) {
5121     /* That's all the processing needed for subpictures */
5122     gst_buffer_unmap (buf, &map);
5123     return buf;
5124   }
5125
5126   nsize = GST_READ_UINT16_BE (map.data);
5127   nsize = MIN (nsize, map.size - 2);
5128
5129   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5130       nsize, map.size);
5131
5132   /* takes care of UTF-8 validation or UTF-16 recognition,
5133    * no other encoding expected */
5134   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5135   gst_buffer_unmap (buf, &map);
5136   if (str) {
5137     gst_buffer_unref (buf);
5138     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5139   } else {
5140     /* this should not really happen unless the subtitle is corrupted */
5141     gst_buffer_unref (buf);
5142     buf = NULL;
5143   }
5144
5145   /* FIXME ? convert optional subsequent style info to markup */
5146
5147   return buf;
5148 }
5149
5150 /* Sets a buffer's attributes properly and pushes it downstream.
5151  * Also checks for additional actions and custom processing that may
5152  * need to be done first.
5153  */
5154 static GstFlowReturn
5155 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5156     QtDemuxStream * stream, GstBuffer * buf,
5157     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5158     gboolean keyframe, GstClockTime position, guint64 byte_position)
5159 {
5160   GstFlowReturn ret = GST_FLOW_OK;
5161
5162   /* offset the timestamps according to the edit list */
5163
5164   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5165     gchar *url;
5166     GstMapInfo map;
5167
5168     gst_buffer_map (buf, &map, GST_MAP_READ);
5169     url = g_strndup ((gchar *) map.data, map.size);
5170     gst_buffer_unmap (buf, &map);
5171     if (url != NULL && strlen (url) != 0) {
5172       /* we have RTSP redirect now */
5173       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5174           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5175               gst_structure_new ("redirect",
5176                   "new-location", G_TYPE_STRING, url, NULL)));
5177       qtdemux->posted_redirect = TRUE;
5178     } else {
5179       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5180           "posting");
5181     }
5182     g_free (url);
5183   }
5184
5185   /* position reporting */
5186   if (qtdemux->segment.rate >= 0) {
5187     qtdemux->segment.position = position;
5188     gst_qtdemux_sync_streams (qtdemux);
5189   }
5190
5191   if (G_UNLIKELY (!stream->pad)) {
5192     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5193     gst_buffer_unref (buf);
5194     goto exit;
5195   }
5196
5197   /* send out pending buffers */
5198   while (stream->buffers) {
5199     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5200
5201     if (G_UNLIKELY (stream->discont)) {
5202       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5203       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5204       stream->discont = FALSE;
5205     } else {
5206       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5207     }
5208
5209     gst_pad_push (stream->pad, buffer);
5210
5211     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5212   }
5213
5214   /* we're going to modify the metadata */
5215   buf = gst_buffer_make_writable (buf);
5216
5217   if (G_UNLIKELY (stream->need_process))
5218     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5219
5220   if (!buf) {
5221     goto exit;
5222   }
5223
5224   GST_BUFFER_DTS (buf) = dts;
5225   GST_BUFFER_PTS (buf) = pts;
5226   GST_BUFFER_DURATION (buf) = duration;
5227   GST_BUFFER_OFFSET (buf) = -1;
5228   GST_BUFFER_OFFSET_END (buf) = -1;
5229
5230   if (G_UNLIKELY (stream->rgb8_palette))
5231     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5232
5233   if (G_UNLIKELY (stream->padding)) {
5234     gst_buffer_resize (buf, stream->padding, -1);
5235   }
5236 #if 0
5237   if (G_UNLIKELY (qtdemux->element_index)) {
5238     GstClockTime stream_time;
5239
5240     stream_time =
5241         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5242         timestamp);
5243     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5244       GST_LOG_OBJECT (qtdemux,
5245           "adding association %" GST_TIME_FORMAT "-> %"
5246           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5247       gst_index_add_association (qtdemux->element_index,
5248           qtdemux->index_id,
5249           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5250           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5251           GST_FORMAT_BYTES, byte_position, NULL);
5252     }
5253   }
5254 #endif
5255
5256   if (stream->need_clip)
5257     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5258
5259   if (G_UNLIKELY (buf == NULL))
5260     goto exit;
5261
5262   if (G_UNLIKELY (stream->discont)) {
5263     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5264     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5265     stream->discont = FALSE;
5266   } else {
5267     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5268   }
5269
5270   if (!keyframe) {
5271     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5272     stream->on_keyframe = FALSE;
5273   } else {
5274     stream->on_keyframe = TRUE;
5275   }
5276
5277
5278   GST_LOG_OBJECT (qtdemux,
5279       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5280       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5281       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5282       GST_PAD_NAME (stream->pad));
5283
5284   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5285     GstStructure *crypto_info;
5286     QtDemuxCencSampleSetInfo *info =
5287         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5288     gint index;
5289     GstEvent *event;
5290
5291     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5292       gst_pad_push_event (stream->pad, event);
5293     }
5294
5295     if (qtdemux->cenc_aux_info_offset > 0 && info->crypto_info == NULL) {
5296       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5297       gst_buffer_unref (buf);
5298       goto exit;
5299     }
5300
5301     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
5302     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5303       /* steal structure from array */
5304       crypto_info = g_ptr_array_index (info->crypto_info, index);
5305       g_ptr_array_index (info->crypto_info, index) = NULL;
5306       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
5307       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5308         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5309     }
5310   }
5311
5312   ret = gst_pad_push (stream->pad, buf);
5313
5314   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5315     /* mark position in stream, we'll need this to know when to send GAP event */
5316     stream->segment.position = pts + duration;
5317   }
5318
5319 exit:
5320   return ret;
5321 }
5322
5323 static const QtDemuxRandomAccessEntry *
5324 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5325     GstClockTime pos, gboolean after)
5326 {
5327   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5328   guint n_entries = stream->n_ra_entries;
5329   guint i;
5330
5331   /* we assume the table is sorted */
5332   for (i = 0; i < n_entries; ++i) {
5333     if (entries[i].ts > pos)
5334       break;
5335   }
5336
5337   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5338    * probably okay to assume that the index lists the very first fragment */
5339   if (i == 0)
5340     return &entries[0];
5341
5342   if (after)
5343     return &entries[i];
5344   else
5345     return &entries[i - 1];
5346 }
5347
5348 static gboolean
5349 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5350 {
5351   const QtDemuxRandomAccessEntry *best_entry = NULL;
5352   guint i;
5353
5354   GST_OBJECT_LOCK (qtdemux);
5355
5356   g_assert (qtdemux->n_streams > 0);
5357
5358   for (i = 0; i < qtdemux->n_streams; i++) {
5359     const QtDemuxRandomAccessEntry *entry;
5360     QtDemuxStream *stream;
5361     gboolean is_audio_or_video;
5362
5363     stream = qtdemux->streams[i];
5364
5365     g_free (stream->samples);
5366     stream->samples = NULL;
5367     stream->n_samples = 0;
5368     stream->stbl_index = -1;    /* no samples have yet been parsed */
5369     stream->sample_index = -1;
5370
5371     if (stream->ra_entries == NULL)
5372       continue;
5373
5374     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5375       is_audio_or_video = TRUE;
5376     else
5377       is_audio_or_video = FALSE;
5378
5379     entry =
5380         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5381         stream->time_position, !is_audio_or_video);
5382
5383     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5384         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5385
5386     stream->pending_seek = entry;
5387
5388     /* decide position to jump to just based on audio/video tracks, not subs */
5389     if (!is_audio_or_video)
5390       continue;
5391
5392     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5393       best_entry = entry;
5394   }
5395
5396   if (best_entry == NULL) {
5397     GST_OBJECT_UNLOCK (qtdemux);
5398     return FALSE;
5399   }
5400
5401   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5402       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5403       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5404       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5405
5406   qtdemux->moof_offset = best_entry->moof_offset;
5407
5408   qtdemux_add_fragmented_samples (qtdemux);
5409
5410   GST_OBJECT_UNLOCK (qtdemux);
5411   return TRUE;
5412 }
5413
5414 static GstFlowReturn
5415 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5416 {
5417   GstFlowReturn ret = GST_FLOW_OK;
5418   GstBuffer *buf = NULL;
5419   QtDemuxStream *stream;
5420   GstClockTime min_time;
5421   guint64 offset = 0;
5422   GstClockTime dts = GST_CLOCK_TIME_NONE;
5423   GstClockTime pts = GST_CLOCK_TIME_NONE;
5424   GstClockTime duration = 0;
5425   gboolean keyframe = FALSE;
5426   guint sample_size = 0;
5427   gboolean empty = 0;
5428   guint size;
5429   gint index;
5430   gint i;
5431
5432   gst_qtdemux_push_pending_newsegment (qtdemux);
5433
5434   if (qtdemux->fragmented_seek_pending) {
5435     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5436     gst_qtdemux_do_fragmented_seek (qtdemux);
5437     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5438     qtdemux->fragmented_seek_pending = FALSE;
5439   }
5440
5441   /* Figure out the next stream sample to output, min_time is expressed in
5442    * global time and runs over the edit list segments. */
5443   min_time = G_MAXUINT64;
5444   index = -1;
5445   for (i = 0; i < qtdemux->n_streams; i++) {
5446     GstClockTime position;
5447
5448     stream = qtdemux->streams[i];
5449     position = stream->time_position;
5450
5451     /* position of -1 is EOS */
5452     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5453       min_time = position;
5454       index = i;
5455     }
5456   }
5457   /* all are EOS */
5458   if (G_UNLIKELY (index == -1)) {
5459     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5460     goto eos;
5461   }
5462
5463   /* check for segment end */
5464   if (G_UNLIKELY (qtdemux->segment.stop != -1
5465           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5466               || (qtdemux->segment.rate < 0
5467                   && qtdemux->segment.start > min_time))
5468           && qtdemux->streams[index]->on_keyframe)) {
5469     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5470     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5471     goto eos_stream;
5472   }
5473
5474   /* gap events for subtitle streams */
5475   for (i = 0; i < qtdemux->n_streams; i++) {
5476     stream = qtdemux->streams[i];
5477     if (stream->pad && (stream->subtype == FOURCC_subp
5478             || stream->subtype == FOURCC_text
5479             || stream->subtype == FOURCC_sbtl)) {
5480       /* send one second gap events until the stream catches up */
5481       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5482       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5483           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5484           stream->segment.position + GST_SECOND < min_time) {
5485         GstEvent *gap =
5486             gst_event_new_gap (stream->segment.position, GST_SECOND);
5487         gst_pad_push_event (stream->pad, gap);
5488         stream->segment.position += GST_SECOND;
5489       }
5490     }
5491   }
5492
5493   stream = qtdemux->streams[index];
5494   if (stream->new_caps) {
5495     gst_qtdemux_configure_stream (qtdemux, stream);
5496     qtdemux_do_allocation (qtdemux, stream);
5497   }
5498
5499   /* fetch info for the current sample of this stream */
5500   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5501               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5502     goto eos_stream;
5503
5504   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5505   if (G_UNLIKELY (qtdemux->
5506           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5507     if (stream->subtype == FOURCC_vide && !keyframe) {
5508       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5509       goto next;
5510     }
5511   }
5512
5513   GST_DEBUG_OBJECT (qtdemux,
5514       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5515       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5516       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5517       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5518
5519   if (G_UNLIKELY (empty)) {
5520     /* empty segment, push a gap and move to the next one */
5521     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5522     stream->segment.position = pts + duration;
5523     goto next;
5524   }
5525
5526   /* hmm, empty sample, skip and move to next sample */
5527   if (G_UNLIKELY (sample_size <= 0))
5528     goto next;
5529
5530   /* last pushed sample was out of boundary, goto next sample */
5531   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5532     goto next;
5533
5534   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5535     size = sample_size;
5536   } else {
5537     GST_DEBUG_OBJECT (qtdemux,
5538         "size %d larger than stream max_buffer_size %d, trimming",
5539         sample_size, stream->max_buffer_size);
5540     size =
5541         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5542   }
5543
5544   if (qtdemux->cenc_aux_info_offset > 0) {
5545     GstMapInfo map;
5546     GstByteReader br;
5547     GstBuffer *aux_info = NULL;
5548
5549     /* pull the data stored before the sample */
5550     ret =
5551         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5552         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5553     if (G_UNLIKELY (ret != GST_FLOW_OK))
5554       goto beach;
5555     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5556     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5557     gst_byte_reader_init (&br, map.data + 8, map.size);
5558     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5559             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5560       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5561       gst_buffer_unmap (aux_info, &map);
5562       gst_buffer_unref (aux_info);
5563       ret = GST_FLOW_ERROR;
5564       goto beach;
5565     }
5566     gst_buffer_unmap (aux_info, &map);
5567     gst_buffer_unref (aux_info);
5568   }
5569
5570   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5571       offset);
5572
5573   if (stream->use_allocator) {
5574     /* if we have a per-stream allocator, use it */
5575     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5576   }
5577
5578   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5579       size, &buf);
5580   if (G_UNLIKELY (ret != GST_FLOW_OK))
5581     goto beach;
5582
5583   if (size != sample_size) {
5584     pts += gst_util_uint64_scale_int (GST_SECOND,
5585         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5586     dts += gst_util_uint64_scale_int (GST_SECOND,
5587         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5588     duration = gst_util_uint64_scale_int (GST_SECOND,
5589         size / stream->bytes_per_frame, stream->timescale);
5590   }
5591
5592   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5593       dts, pts, duration, keyframe, min_time, offset);
5594
5595   if (size != sample_size) {
5596     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5597     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5598
5599     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5600         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5601     if (time_position >= segment->media_start) {
5602       /* inside the segment, update time_position, looks very familiar to
5603        * GStreamer segments, doesn't it? */
5604       stream->time_position = (time_position - segment->media_start) +
5605           segment->time;
5606     } else {
5607       /* not yet in segment, time does not yet increment. This means
5608        * that we are still prerolling keyframes to the decoder so it can
5609        * decode the first sample of the segment. */
5610       stream->time_position = segment->time;
5611     }
5612   }
5613
5614   /* combine flows */
5615   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5616   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5617    * we have no more data for the pad to push */
5618   if (ret == GST_FLOW_EOS)
5619     ret = GST_FLOW_OK;
5620
5621   stream->offset_in_sample += size;
5622   if (stream->offset_in_sample >= sample_size) {
5623     gst_qtdemux_advance_sample (qtdemux, stream);
5624   }
5625   goto beach;
5626
5627 next:
5628   gst_qtdemux_advance_sample (qtdemux, stream);
5629
5630 beach:
5631   return ret;
5632
5633   /* special cases */
5634 eos:
5635   {
5636     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5637     ret = GST_FLOW_EOS;
5638     goto beach;
5639   }
5640 eos_stream:
5641   {
5642     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5643     /* EOS will be raised if all are EOS */
5644     ret = GST_FLOW_OK;
5645     goto beach;
5646   }
5647 }
5648
5649 static void
5650 gst_qtdemux_loop (GstPad * pad)
5651 {
5652   GstQTDemux *qtdemux;
5653   guint64 cur_offset;
5654   GstFlowReturn ret;
5655
5656   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5657
5658   cur_offset = qtdemux->offset;
5659   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
5660       cur_offset, qtdemux->state);
5661
5662   switch (qtdemux->state) {
5663     case QTDEMUX_STATE_INITIAL:
5664     case QTDEMUX_STATE_HEADER:
5665       ret = gst_qtdemux_loop_state_header (qtdemux);
5666       break;
5667     case QTDEMUX_STATE_MOVIE:
5668       ret = gst_qtdemux_loop_state_movie (qtdemux);
5669       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5670         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5671       }
5672       break;
5673     default:
5674       /* ouch */
5675       goto invalid_state;
5676   }
5677
5678   /* if something went wrong, pause */
5679   if (ret != GST_FLOW_OK)
5680     goto pause;
5681
5682 done:
5683   gst_object_unref (qtdemux);
5684   return;
5685
5686   /* ERRORS */
5687 invalid_state:
5688   {
5689     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5690         (NULL), ("streaming stopped, invalid state"));
5691     gst_pad_pause_task (pad);
5692     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5693     goto done;
5694   }
5695 pause:
5696   {
5697     const gchar *reason = gst_flow_get_name (ret);
5698
5699     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5700
5701     gst_pad_pause_task (pad);
5702
5703     /* fatal errors need special actions */
5704     /* check EOS */
5705     if (ret == GST_FLOW_EOS) {
5706       if (qtdemux->n_streams == 0) {
5707         /* we have no streams, post an error */
5708         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5709       }
5710       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5711         gint64 stop;
5712
5713         if ((stop = qtdemux->segment.stop) == -1)
5714           stop = qtdemux->segment.duration;
5715
5716         if (qtdemux->segment.rate >= 0) {
5717           GstMessage *message;
5718           GstEvent *event;
5719
5720           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5721           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5722               GST_FORMAT_TIME, stop);
5723           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5724           if (qtdemux->segment_seqnum) {
5725             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5726             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5727           }
5728           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5729           gst_qtdemux_push_event (qtdemux, event);
5730         } else {
5731           GstMessage *message;
5732           GstEvent *event;
5733
5734           /*  For Reverse Playback */
5735           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5736           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5737               GST_FORMAT_TIME, qtdemux->segment.start);
5738           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5739               qtdemux->segment.start);
5740           if (qtdemux->segment_seqnum) {
5741             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5742             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5743           }
5744           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5745           gst_qtdemux_push_event (qtdemux, event);
5746         }
5747       } else {
5748         GstEvent *event;
5749
5750         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5751         event = gst_event_new_eos ();
5752         if (qtdemux->segment_seqnum)
5753           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5754         gst_qtdemux_push_event (qtdemux, event);
5755       }
5756     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5757       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5758           (NULL), ("streaming stopped, reason %s", reason));
5759       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5760     }
5761     goto done;
5762   }
5763 }
5764
5765 /*
5766  * has_next_entry
5767  *
5768  * Returns if there are samples to be played.
5769  */
5770 static gboolean
5771 has_next_entry (GstQTDemux * demux)
5772 {
5773   QtDemuxStream *stream;
5774   int i;
5775
5776   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5777
5778   for (i = 0; i < demux->n_streams; i++) {
5779     stream = demux->streams[i];
5780
5781     if (stream->sample_index == -1) {
5782       stream->sample_index = 0;
5783       stream->offset_in_sample = 0;
5784     }
5785
5786     if (stream->sample_index >= stream->n_samples) {
5787       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5788       continue;
5789     }
5790     GST_DEBUG_OBJECT (demux, "Found a sample");
5791     return TRUE;
5792   }
5793
5794   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5795   return FALSE;
5796 }
5797
5798 /*
5799  * next_entry_size
5800  *
5801  * Returns the size of the first entry at the current offset.
5802  * If -1, there are none (which means EOS or empty file).
5803  */
5804 static guint64
5805 next_entry_size (GstQTDemux * demux)
5806 {
5807   QtDemuxStream *stream;
5808   int i;
5809   int smallidx = -1;
5810   guint64 smalloffs = (guint64) - 1;
5811   QtDemuxSample *sample;
5812
5813   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5814       demux->offset);
5815
5816   for (i = 0; i < demux->n_streams; i++) {
5817     stream = demux->streams[i];
5818
5819     if (stream->sample_index == -1) {
5820       stream->sample_index = 0;
5821       stream->offset_in_sample = 0;
5822     }
5823
5824     if (stream->sample_index >= stream->n_samples) {
5825       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5826       continue;
5827     }
5828
5829     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5830       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5831           stream->sample_index);
5832       return -1;
5833     }
5834
5835     sample = &stream->samples[stream->sample_index];
5836
5837     GST_LOG_OBJECT (demux,
5838         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5839         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5840         sample->offset, sample->size);
5841
5842     if (((smalloffs == -1)
5843             || (sample->offset < smalloffs)) && (sample->size)) {
5844       smallidx = i;
5845       smalloffs = sample->offset;
5846     }
5847   }
5848
5849   GST_LOG_OBJECT (demux,
5850       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5851       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5852
5853   if (smallidx == -1)
5854     return -1;
5855
5856   stream = demux->streams[smallidx];
5857   sample = &stream->samples[stream->sample_index];
5858
5859   if (sample->offset >= demux->offset) {
5860     demux->todrop = sample->offset - demux->offset;
5861     return sample->size + demux->todrop;
5862   }
5863
5864   GST_DEBUG_OBJECT (demux,
5865       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5866   return -1;
5867 }
5868
5869 static void
5870 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5871 {
5872   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5873
5874   gst_element_post_message (GST_ELEMENT_CAST (demux),
5875       gst_message_new_element (GST_OBJECT_CAST (demux),
5876           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5877 }
5878
5879 static gboolean
5880 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5881 {
5882   GstEvent *event;
5883   gboolean res = 0;
5884
5885   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5886
5887   event =
5888       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5889       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5890       GST_SEEK_TYPE_NONE, -1);
5891
5892   /* store seqnum to drop flush events, they don't need to reach downstream */
5893   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5894   res = gst_pad_push_event (demux->sinkpad, event);
5895   demux->offset_seek_seqnum = 0;
5896
5897   return res;
5898 }
5899
5900 /* check for seekable upstream, above and beyond a mere query */
5901 static void
5902 gst_qtdemux_check_seekability (GstQTDemux * demux)
5903 {
5904   GstQuery *query;
5905   gboolean seekable = FALSE;
5906   gint64 start = -1, stop = -1;
5907
5908   if (demux->upstream_size)
5909     return;
5910
5911   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5912   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5913     GST_DEBUG_OBJECT (demux, "seeking query failed");
5914     goto done;
5915   }
5916
5917   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5918
5919   /* try harder to query upstream size if we didn't get it the first time */
5920   if (seekable && stop == -1) {
5921     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5922     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5923   }
5924
5925   /* if upstream doesn't know the size, it's likely that it's not seekable in
5926    * practice even if it technically may be seekable */
5927   if (seekable && (start != 0 || stop <= start)) {
5928     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5929     seekable = FALSE;
5930   }
5931
5932 done:
5933   gst_query_unref (query);
5934
5935   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5936       G_GUINT64_FORMAT ")", seekable, start, stop);
5937   demux->upstream_seekable = seekable;
5938   demux->upstream_size = seekable ? stop : -1;
5939 }
5940
5941 static void
5942 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5943 {
5944   g_return_if_fail (bytes <= demux->todrop);
5945
5946   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5947   gst_adapter_flush (demux->adapter, bytes);
5948   demux->neededbytes -= bytes;
5949   demux->offset += bytes;
5950   demux->todrop -= bytes;
5951 }
5952
5953 static void
5954 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5955 {
5956   if (G_UNLIKELY (demux->pending_newsegment)) {
5957     gint i;
5958
5959     gst_qtdemux_push_pending_newsegment (demux);
5960     /* clear to send tags on all streams */
5961     for (i = 0; i < demux->n_streams; i++) {
5962       QtDemuxStream *stream;
5963       stream = demux->streams[i];
5964       gst_qtdemux_push_tags (demux, stream);
5965       if (stream->sparse) {
5966         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5967         gst_pad_push_event (stream->pad,
5968             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
5969       }
5970     }
5971   }
5972 }
5973
5974 static void
5975 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
5976     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
5977 {
5978   GstClockTime ts, dur;
5979   GstEvent *gap;
5980
5981   ts = pos;
5982   dur =
5983       stream->segments[segment_index].duration - (pos -
5984       stream->segments[segment_index].time);
5985   gap = gst_event_new_gap (ts, dur);
5986   stream->time_position += dur;
5987
5988   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
5989       "segment: %" GST_PTR_FORMAT, gap);
5990   gst_pad_push_event (stream->pad, gap);
5991 }
5992
5993 static void
5994 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
5995     QtDemuxStream * stream)
5996 {
5997   gint i;
5998
5999   /* Push any initial gap segments before proceeding to the
6000    * 'real' data */
6001   for (i = 0; i < stream->n_segments; i++) {
6002     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6003
6004     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6005       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6006           stream->time_position);
6007     } else {
6008       /* Only support empty segment at the beginning followed by
6009        * one non-empty segment, this was checked when parsing the
6010        * edts atom, arriving here is unexpected */
6011       g_assert (i + 1 == stream->n_segments);
6012       break;
6013     }
6014   }
6015 }
6016
6017 static GstFlowReturn
6018 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6019 {
6020   GstQTDemux *demux;
6021
6022   demux = GST_QTDEMUX (parent);
6023
6024   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6025     gint i;
6026
6027     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6028
6029     for (i = 0; i < demux->n_streams; i++) {
6030       demux->streams[i]->discont = TRUE;
6031     }
6032
6033     /* Reverse fragmented playback, need to flush all we have before
6034      * consuming a new fragment.
6035      * The samples array have the timestamps calculated by accumulating the
6036      * durations but this won't work for reverse playback of fragments as
6037      * the timestamps of a subsequent fragment should be smaller than the
6038      * previously received one. */
6039     if (demux->fragmented && demux->segment.rate < 0) {
6040       gst_qtdemux_process_adapter (demux, TRUE);
6041       for (i = 0; i < demux->n_streams; i++)
6042         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6043     }
6044   }
6045
6046   gst_adapter_push (demux->adapter, inbuf);
6047
6048   GST_DEBUG_OBJECT (demux,
6049       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6050       demux->neededbytes, gst_adapter_available (demux->adapter));
6051
6052   return gst_qtdemux_process_adapter (demux, FALSE);
6053 }
6054
6055 static GstFlowReturn
6056 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6057 {
6058   GstFlowReturn ret = GST_FLOW_OK;
6059
6060   /* we never really mean to buffer that much */
6061   if (demux->neededbytes == -1) {
6062     goto eos;
6063   }
6064
6065   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6066       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6067
6068     GST_DEBUG_OBJECT (demux,
6069         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
6070         demux->state, demux->neededbytes, demux->offset);
6071
6072     switch (demux->state) {
6073       case QTDEMUX_STATE_INITIAL:{
6074         const guint8 *data;
6075         guint32 fourcc;
6076         guint64 size;
6077
6078         gst_qtdemux_check_seekability (demux);
6079
6080         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6081
6082         /* get fourcc/length, set neededbytes */
6083         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6084             &size, &fourcc);
6085         gst_adapter_unmap (demux->adapter);
6086         data = NULL;
6087         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6088             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6089         if (size == 0) {
6090           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6091               (_("This file is invalid and cannot be played.")),
6092               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6093                   GST_FOURCC_ARGS (fourcc)));
6094           ret = GST_FLOW_ERROR;
6095           break;
6096         }
6097         if (fourcc == FOURCC_mdat) {
6098           gint next_entry = next_entry_size (demux);
6099           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6100             /* we have the headers, start playback */
6101             demux->state = QTDEMUX_STATE_MOVIE;
6102             demux->neededbytes = next_entry;
6103             demux->mdatleft = size;
6104           } else {
6105             /* no headers yet, try to get them */
6106             guint bs;
6107             gboolean res;
6108             guint64 old, target;
6109
6110           buffer_data:
6111             old = demux->offset;
6112             target = old + size;
6113
6114             /* try to jump over the atom with a seek */
6115             /* only bother if it seems worth doing so,
6116              * and avoids possible upstream/server problems */
6117             if (demux->upstream_seekable &&
6118                 demux->upstream_size > 4 * (1 << 20)) {
6119               res = qtdemux_seek_offset (demux, target);
6120             } else {
6121               GST_DEBUG_OBJECT (demux, "skipping seek");
6122               res = FALSE;
6123             }
6124
6125             if (res) {
6126               GST_DEBUG_OBJECT (demux, "seek success");
6127               /* remember the offset fo the first mdat so we can seek back to it
6128                * after we have the headers */
6129               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6130                 demux->first_mdat = old;
6131                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6132                     demux->first_mdat);
6133               }
6134               /* seek worked, continue reading */
6135               demux->offset = target;
6136               demux->neededbytes = 16;
6137               demux->state = QTDEMUX_STATE_INITIAL;
6138             } else {
6139               /* seek failed, need to buffer */
6140               demux->offset = old;
6141               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6142               /* there may be multiple mdat (or alike) buffers */
6143               /* sanity check */
6144               if (demux->mdatbuffer)
6145                 bs = gst_buffer_get_size (demux->mdatbuffer);
6146               else
6147                 bs = 0;
6148               if (size + bs > 10 * (1 << 20))
6149                 goto no_moov;
6150               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6151               demux->neededbytes = size;
6152               if (!demux->mdatbuffer)
6153                 demux->mdatoffset = demux->offset;
6154             }
6155           }
6156         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6157           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6158               (_("This file is invalid and cannot be played.")),
6159               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6160                   GST_FOURCC_ARGS (fourcc), size));
6161           ret = GST_FLOW_ERROR;
6162           break;
6163         } else {
6164           /* this means we already started buffering and still no moov header,
6165            * let's continue buffering everything till we get moov */
6166           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6167                   || fourcc == FOURCC_moof))
6168             goto buffer_data;
6169           demux->neededbytes = size;
6170           demux->state = QTDEMUX_STATE_HEADER;
6171         }
6172         break;
6173       }
6174       case QTDEMUX_STATE_HEADER:{
6175         const guint8 *data;
6176         guint32 fourcc;
6177
6178         GST_DEBUG_OBJECT (demux, "In header");
6179
6180         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6181
6182         /* parse the header */
6183         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6184             &fourcc);
6185         if (fourcc == FOURCC_moov) {
6186           gint n;
6187
6188           /* in usual fragmented setup we could try to scan for more
6189            * and end up at the the moov (after mdat) again */
6190           if (demux->got_moov && demux->n_streams > 0 &&
6191               (!demux->fragmented
6192                   || demux->last_moov_offset == demux->offset)) {
6193             GST_DEBUG_OBJECT (demux,
6194                 "Skipping moov atom as we have (this) one already");
6195           } else {
6196             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6197
6198             if (demux->got_moov && demux->fragmented) {
6199               GST_DEBUG_OBJECT (demux,
6200                   "Got a second moov, clean up data from old one");
6201               if (demux->moov_node)
6202                 g_node_destroy (demux->moov_node);
6203               demux->moov_node = NULL;
6204               demux->moov_node_compressed = NULL;
6205             } else {
6206               /* prepare newsegment to send when streaming actually starts */
6207               if (!demux->pending_newsegment) {
6208                 demux->pending_newsegment =
6209                     gst_event_new_segment (&demux->segment);
6210                 if (demux->segment_seqnum)
6211                   gst_event_set_seqnum (demux->pending_newsegment,
6212                       demux->segment_seqnum);
6213               }
6214             }
6215
6216             demux->last_moov_offset = demux->offset;
6217
6218             qtdemux_parse_moov (demux, data, demux->neededbytes);
6219             qtdemux_node_dump (demux, demux->moov_node);
6220             qtdemux_parse_tree (demux);
6221             qtdemux_prepare_streams (demux);
6222             if (!demux->got_moov)
6223               qtdemux_expose_streams (demux);
6224             else {
6225
6226               for (n = 0; n < demux->n_streams; n++) {
6227                 QtDemuxStream *stream = demux->streams[n];
6228
6229                 gst_qtdemux_configure_stream (demux, stream);
6230               }
6231             }
6232
6233             demux->got_moov = TRUE;
6234             gst_qtdemux_check_send_pending_segment (demux);
6235
6236             /* fragmented streams headers shouldn't contain edts atoms */
6237             if (!demux->fragmented) {
6238               for (n = 0; n < demux->n_streams; n++) {
6239                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6240                     demux->streams[n]);
6241               }
6242             }
6243
6244             g_node_destroy (demux->moov_node);
6245             demux->moov_node = NULL;
6246             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6247           }
6248         } else if (fourcc == FOURCC_moof) {
6249           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6250             guint64 dist = 0;
6251             GstClockTime prev_pts;
6252             guint64 prev_offset;
6253
6254             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6255
6256             /*
6257              * The timestamp of the moof buffer is relevant as some scenarios
6258              * won't have the initial timestamp in the atoms. Whenever a new
6259              * buffer has started, we get that buffer's PTS and use it as a base
6260              * timestamp for the trun entries.
6261              *
6262              * To keep track of the current buffer timestamp and starting point
6263              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6264              * from the beggining of the buffer, with the distance and demux->offset
6265              * we know if it is still the same buffer or not.
6266              */
6267             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6268             prev_offset = demux->offset - dist;
6269             if (demux->fragment_start_offset == -1
6270                 || prev_offset > demux->fragment_start_offset) {
6271               demux->fragment_start_offset = prev_offset;
6272               demux->fragment_start = prev_pts;
6273               GST_DEBUG_OBJECT (demux,
6274                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6275                   GST_TIME_FORMAT, demux->fragment_start_offset,
6276                   GST_TIME_ARGS (demux->fragment_start));
6277             }
6278
6279             demux->moof_offset = demux->offset;
6280             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6281                     demux->offset, NULL)) {
6282               gst_adapter_unmap (demux->adapter);
6283               ret = GST_FLOW_ERROR;
6284               goto done;
6285             }
6286             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6287             if (demux->mss_mode && !demux->exposed) {
6288               if (!demux->pending_newsegment) {
6289                 GstSegment segment;
6290                 gst_segment_init (&segment, GST_FORMAT_TIME);
6291                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6292                 demux->pending_newsegment = gst_event_new_segment (&segment);
6293                 if (demux->segment_seqnum)
6294                   gst_event_set_seqnum (demux->pending_newsegment,
6295                       demux->segment_seqnum);
6296               }
6297               qtdemux_expose_streams (demux);
6298             }
6299           } else {
6300             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6301           }
6302         } else if (fourcc == FOURCC_ftyp) {
6303           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6304           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6305         } else if (fourcc == FOURCC_uuid) {
6306           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6307           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6308         } else if (fourcc == FOURCC_sidx) {
6309           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6310           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6311         } else {
6312           GST_WARNING_OBJECT (demux,
6313               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6314               GST_FOURCC_ARGS (fourcc));
6315           /* Let's jump that one and go back to initial state */
6316         }
6317         gst_adapter_unmap (demux->adapter);
6318         data = NULL;
6319
6320         if (demux->mdatbuffer && demux->n_streams) {
6321           gsize remaining_data_size = 0;
6322
6323           /* the mdat was before the header */
6324           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6325               demux->n_streams, demux->mdatbuffer);
6326           /* restore our adapter/offset view of things with upstream;
6327            * put preceding buffered data ahead of current moov data.
6328            * This should also handle evil mdat, moov, mdat cases and alike */
6329           gst_adapter_flush (demux->adapter, demux->neededbytes);
6330
6331           /* Store any remaining data after the mdat for later usage */
6332           remaining_data_size = gst_adapter_available (demux->adapter);
6333           if (remaining_data_size > 0) {
6334             g_assert (demux->restoredata_buffer == NULL);
6335             demux->restoredata_buffer =
6336                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6337             demux->restoredata_offset = demux->offset + demux->neededbytes;
6338             GST_DEBUG_OBJECT (demux,
6339                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6340                 G_GUINT64_FORMAT, remaining_data_size,
6341                 demux->restoredata_offset);
6342           }
6343
6344           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6345           demux->mdatbuffer = NULL;
6346           demux->offset = demux->mdatoffset;
6347           demux->neededbytes = next_entry_size (demux);
6348           demux->state = QTDEMUX_STATE_MOVIE;
6349           demux->mdatleft = gst_adapter_available (demux->adapter);
6350         } else {
6351           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6352           gst_adapter_flush (demux->adapter, demux->neededbytes);
6353
6354           /* only go back to the mdat if there are samples to play */
6355           if (demux->got_moov && demux->first_mdat != -1
6356               && has_next_entry (demux)) {
6357             gboolean res;
6358
6359             /* we need to seek back */
6360             res = qtdemux_seek_offset (demux, demux->first_mdat);
6361             if (res) {
6362               demux->offset = demux->first_mdat;
6363             } else {
6364               GST_DEBUG_OBJECT (demux, "Seek back failed");
6365             }
6366           } else {
6367             demux->offset += demux->neededbytes;
6368           }
6369           demux->neededbytes = 16;
6370           demux->state = QTDEMUX_STATE_INITIAL;
6371         }
6372
6373         break;
6374       }
6375       case QTDEMUX_STATE_BUFFER_MDAT:{
6376         GstBuffer *buf;
6377         guint8 fourcc[4];
6378
6379         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6380             demux->offset);
6381         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6382         gst_buffer_extract (buf, 0, fourcc, 4);
6383         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6384             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6385         if (demux->mdatbuffer)
6386           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6387         else
6388           demux->mdatbuffer = buf;
6389         demux->offset += demux->neededbytes;
6390         demux->neededbytes = 16;
6391         demux->state = QTDEMUX_STATE_INITIAL;
6392         gst_qtdemux_post_progress (demux, 1, 1);
6393
6394         break;
6395       }
6396       case QTDEMUX_STATE_MOVIE:{
6397         QtDemuxStream *stream = NULL;
6398         QtDemuxSample *sample;
6399         int i = -1;
6400         GstClockTime dts, pts, duration;
6401         gboolean keyframe;
6402
6403         GST_DEBUG_OBJECT (demux,
6404             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6405
6406         if (demux->fragmented) {
6407           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6408               demux->mdatleft);
6409           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6410             /* if needed data starts within this atom,
6411              * then it should not exceed this atom */
6412             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6413               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6414                   (_("This file is invalid and cannot be played.")),
6415                   ("sample data crosses atom boundary"));
6416               ret = GST_FLOW_ERROR;
6417               break;
6418             }
6419             demux->mdatleft -= demux->neededbytes;
6420           } else {
6421             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6422             /* so we are dropping more than left in this atom */
6423             gst_qtdemux_drop_data (demux, demux->mdatleft);
6424             demux->mdatleft = 0;
6425
6426             /* need to resume atom parsing so we do not miss any other pieces */
6427             demux->state = QTDEMUX_STATE_INITIAL;
6428             demux->neededbytes = 16;
6429
6430             /* check if there was any stored post mdat data from previous buffers */
6431             if (demux->restoredata_buffer) {
6432               g_assert (gst_adapter_available (demux->adapter) == 0);
6433
6434               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6435               demux->restoredata_buffer = NULL;
6436               demux->offset = demux->restoredata_offset;
6437             }
6438
6439             break;
6440           }
6441         }
6442
6443         if (demux->todrop) {
6444           if (demux->cenc_aux_info_offset > 0) {
6445             GstByteReader br;
6446             const guint8 *data;
6447
6448             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6449             data = gst_adapter_map (demux->adapter, demux->todrop);
6450             gst_byte_reader_init (&br, data + 8, demux->todrop);
6451             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6452                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6453               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6454               ret = GST_FLOW_ERROR;
6455               gst_adapter_unmap (demux->adapter);
6456               g_free (demux->cenc_aux_info_sizes);
6457               demux->cenc_aux_info_sizes = NULL;
6458               goto done;
6459             }
6460             demux->cenc_aux_info_offset = 0;
6461             g_free (demux->cenc_aux_info_sizes);
6462             demux->cenc_aux_info_sizes = NULL;
6463             gst_adapter_unmap (demux->adapter);
6464           }
6465           gst_qtdemux_drop_data (demux, demux->todrop);
6466         }
6467
6468         /* first buffer? */
6469         /* initial newsegment sent here after having added pads,
6470          * possible others in sink_event */
6471         gst_qtdemux_check_send_pending_segment (demux);
6472
6473         /* Figure out which stream this packet belongs to */
6474         for (i = 0; i < demux->n_streams; i++) {
6475           stream = demux->streams[i];
6476           if (stream->sample_index >= stream->n_samples)
6477             continue;
6478           GST_LOG_OBJECT (demux,
6479               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6480               " / size:%d)", i, stream->sample_index,
6481               stream->samples[stream->sample_index].offset,
6482               stream->samples[stream->sample_index].size);
6483
6484           if (stream->samples[stream->sample_index].offset == demux->offset)
6485             break;
6486         }
6487
6488         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6489           goto unknown_stream;
6490
6491         if (stream->new_caps) {
6492           gst_qtdemux_configure_stream (demux, stream);
6493         }
6494
6495         /* Put data in a buffer, set timestamps, caps, ... */
6496         sample = &stream->samples[stream->sample_index];
6497
6498         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6499           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6500               GST_FOURCC_ARGS (stream->fourcc));
6501
6502           dts = QTSAMPLE_DTS (stream, sample);
6503           pts = QTSAMPLE_PTS (stream, sample);
6504           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6505           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6506
6507           /* check for segment end */
6508           if (G_UNLIKELY (demux->segment.stop != -1
6509                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6510             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6511             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6512
6513             /* skip this data, stream is EOS */
6514             gst_adapter_flush (demux->adapter, demux->neededbytes);
6515
6516             /* check if all streams are eos */
6517             ret = GST_FLOW_EOS;
6518             for (i = 0; i < demux->n_streams; i++) {
6519               if (!STREAM_IS_EOS (demux->streams[i])) {
6520                 ret = GST_FLOW_OK;
6521                 break;
6522               }
6523             }
6524
6525             if (ret == GST_FLOW_EOS) {
6526               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6527               goto eos;
6528             }
6529           } else {
6530             GstBuffer *outbuf;
6531
6532             outbuf =
6533                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6534
6535             /* FIXME: should either be an assert or a plain check */
6536             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6537
6538             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6539                 dts, pts, duration, keyframe, dts, demux->offset);
6540           }
6541
6542           /* combine flows */
6543           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6544           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6545             goto non_ok_unlinked_flow;
6546         } else {
6547           /* skip this data, stream is EOS */
6548           gst_adapter_flush (demux->adapter, demux->neededbytes);
6549         }
6550
6551         stream->sample_index++;
6552         stream->offset_in_sample = 0;
6553
6554         /* update current offset and figure out size of next buffer */
6555         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6556             demux->offset, demux->neededbytes);
6557         demux->offset += demux->neededbytes;
6558         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6559             demux->offset);
6560
6561         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6562           if (demux->fragmented) {
6563             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6564             /* there may be more to follow, only finish this atom */
6565             demux->todrop = demux->mdatleft;
6566             demux->neededbytes = demux->todrop;
6567             break;
6568           }
6569           goto eos;
6570         }
6571         break;
6572       }
6573       default:
6574         goto invalid_state;
6575     }
6576   }
6577
6578   /* when buffering movie data, at least show user something is happening */
6579   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6580       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6581     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6582         demux->neededbytes);
6583   }
6584 done:
6585
6586   return ret;
6587
6588   /* ERRORS */
6589 non_ok_unlinked_flow:
6590   {
6591     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6592         gst_flow_get_name (ret));
6593     return ret;
6594   }
6595 unknown_stream:
6596   {
6597     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6598     ret = GST_FLOW_ERROR;
6599     goto done;
6600   }
6601 eos:
6602   {
6603     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6604     ret = GST_FLOW_EOS;
6605     goto done;
6606   }
6607 invalid_state:
6608   {
6609     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6610         (NULL), ("qtdemuxer invalid state %d", demux->state));
6611     ret = GST_FLOW_ERROR;
6612     goto done;
6613   }
6614 no_moov:
6615   {
6616     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6617         (NULL), ("no 'moov' atom within the first 10 MB"));
6618     ret = GST_FLOW_ERROR;
6619     goto done;
6620   }
6621 }
6622
6623 static gboolean
6624 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6625 {
6626   GstQuery *query;
6627   gboolean pull_mode;
6628
6629   query = gst_query_new_scheduling ();
6630
6631   if (!gst_pad_peer_query (sinkpad, query)) {
6632     gst_query_unref (query);
6633     goto activate_push;
6634   }
6635
6636   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6637       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6638   gst_query_unref (query);
6639
6640   if (!pull_mode)
6641     goto activate_push;
6642
6643   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6644   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6645
6646 activate_push:
6647   {
6648     GST_DEBUG_OBJECT (sinkpad, "activating push");
6649     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6650   }
6651 }
6652
6653 static gboolean
6654 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6655     GstPadMode mode, gboolean active)
6656 {
6657   gboolean res;
6658   GstQTDemux *demux = GST_QTDEMUX (parent);
6659
6660   switch (mode) {
6661     case GST_PAD_MODE_PUSH:
6662       demux->pullbased = FALSE;
6663       res = TRUE;
6664       break;
6665     case GST_PAD_MODE_PULL:
6666       if (active) {
6667         demux->pullbased = TRUE;
6668         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6669             sinkpad, NULL);
6670       } else {
6671         res = gst_pad_stop_task (sinkpad);
6672       }
6673       break;
6674     default:
6675       res = FALSE;
6676       break;
6677   }
6678   return res;
6679 }
6680
6681 #ifdef HAVE_ZLIB
6682 static void *
6683 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6684 {
6685   return g_malloc (items * size);
6686 }
6687
6688 static void
6689 qtdemux_zfree (void *opaque, void *addr)
6690 {
6691   g_free (addr);
6692 }
6693
6694 static void *
6695 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6696 {
6697   guint8 *buffer;
6698   z_stream *z;
6699   int ret;
6700
6701   z = g_new0 (z_stream, 1);
6702   z->zalloc = qtdemux_zalloc;
6703   z->zfree = qtdemux_zfree;
6704   z->opaque = NULL;
6705
6706   z->next_in = z_buffer;
6707   z->avail_in = z_length;
6708
6709   buffer = (guint8 *) g_malloc (length);
6710   ret = inflateInit (z);
6711   while (z->avail_in > 0) {
6712     if (z->avail_out == 0) {
6713       length += 1024;
6714       buffer = (guint8 *) g_realloc (buffer, length);
6715       z->next_out = buffer + z->total_out;
6716       z->avail_out = 1024;
6717     }
6718     ret = inflate (z, Z_SYNC_FLUSH);
6719     if (ret != Z_OK)
6720       break;
6721   }
6722   if (ret != Z_STREAM_END) {
6723     g_warning ("inflate() returned %d", ret);
6724   }
6725
6726   g_free (z);
6727   return buffer;
6728 }
6729 #endif /* HAVE_ZLIB */
6730
6731 static gboolean
6732 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6733 {
6734   GNode *cmov;
6735
6736   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6737
6738   /* counts as header data */
6739   qtdemux->header_size += length;
6740
6741   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6742   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6743
6744   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6745   if (cmov) {
6746     guint32 method;
6747     GNode *dcom;
6748     GNode *cmvd;
6749
6750     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6751     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6752     if (dcom == NULL || cmvd == NULL)
6753       goto invalid_compression;
6754
6755     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6756     switch (method) {
6757 #ifdef HAVE_ZLIB
6758       case FOURCC_zlib:{
6759         guint uncompressed_length;
6760         guint compressed_length;
6761         guint8 *buf;
6762
6763         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6764         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6765         GST_LOG ("length = %u", uncompressed_length);
6766
6767         buf =
6768             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6769             compressed_length, uncompressed_length);
6770
6771         qtdemux->moov_node_compressed = qtdemux->moov_node;
6772         qtdemux->moov_node = g_node_new (buf);
6773
6774         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6775             uncompressed_length);
6776         break;
6777       }
6778 #endif /* HAVE_ZLIB */
6779       default:
6780         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6781             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6782         break;
6783     }
6784   }
6785   return TRUE;
6786
6787   /* ERRORS */
6788 invalid_compression:
6789   {
6790     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6791     return FALSE;
6792   }
6793 }
6794
6795 static gboolean
6796 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6797     const guint8 * end)
6798 {
6799   while (G_UNLIKELY (buf < end)) {
6800     GNode *child;
6801     guint32 len;
6802
6803     if (G_UNLIKELY (buf + 4 > end)) {
6804       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6805       break;
6806     }
6807     len = QT_UINT32 (buf);
6808     if (G_UNLIKELY (len == 0)) {
6809       GST_LOG_OBJECT (qtdemux, "empty container");
6810       break;
6811     }
6812     if (G_UNLIKELY (len < 8)) {
6813       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6814       break;
6815     }
6816     if (G_UNLIKELY (len > (end - buf))) {
6817       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6818           (gint) (end - buf));
6819       break;
6820     }
6821
6822     child = g_node_new ((guint8 *) buf);
6823     g_node_append (node, child);
6824     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6825     qtdemux_parse_node (qtdemux, child, buf, len);
6826
6827     buf += len;
6828   }
6829   return TRUE;
6830 }
6831
6832 static gboolean
6833 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6834     GNode * xdxt)
6835 {
6836   int len = QT_UINT32 (xdxt->data);
6837   guint8 *buf = xdxt->data;
6838   guint8 *end = buf + len;
6839   GstBuffer *buffer;
6840
6841   /* skip size and type */
6842   buf += 8;
6843   end -= 8;
6844
6845   while (buf < end) {
6846     gint size;
6847     guint32 type;
6848
6849     size = QT_UINT32 (buf);
6850     type = QT_FOURCC (buf + 4);
6851
6852     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6853
6854     if (buf + size > end || size <= 0)
6855       break;
6856
6857     buf += 8;
6858     size -= 8;
6859
6860     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6861         GST_FOURCC_ARGS (type));
6862
6863     switch (type) {
6864       case FOURCC_tCtH:
6865         buffer = gst_buffer_new_and_alloc (size);
6866         gst_buffer_fill (buffer, 0, buf, size);
6867         stream->buffers = g_slist_append (stream->buffers, buffer);
6868         GST_LOG_OBJECT (qtdemux, "parsing theora header");
6869         break;
6870       case FOURCC_tCt_:
6871         buffer = gst_buffer_new_and_alloc (size);
6872         gst_buffer_fill (buffer, 0, buf, size);
6873         stream->buffers = g_slist_append (stream->buffers, buffer);
6874         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6875         break;
6876       case FOURCC_tCtC:
6877         buffer = gst_buffer_new_and_alloc (size);
6878         gst_buffer_fill (buffer, 0, buf, size);
6879         stream->buffers = g_slist_append (stream->buffers, buffer);
6880         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6881         break;
6882       default:
6883         GST_WARNING_OBJECT (qtdemux,
6884             "unknown theora cookie %" GST_FOURCC_FORMAT,
6885             GST_FOURCC_ARGS (type));
6886         break;
6887     }
6888     buf += size;
6889   }
6890   return TRUE;
6891 }
6892
6893 static gboolean
6894 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
6895     guint length)
6896 {
6897   guint32 fourcc = 0;
6898   guint32 node_length = 0;
6899   const QtNodeType *type;
6900   const guint8 *end;
6901
6902   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
6903
6904   if (G_UNLIKELY (length < 8))
6905     goto not_enough_data;
6906
6907   node_length = QT_UINT32 (buffer);
6908   fourcc = QT_FOURCC (buffer + 4);
6909
6910   /* ignore empty nodes */
6911   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
6912     return TRUE;
6913
6914   type = qtdemux_type_get (fourcc);
6915
6916   end = buffer + length;
6917
6918   GST_LOG_OBJECT (qtdemux,
6919       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
6920       GST_FOURCC_ARGS (fourcc), node_length, type->name);
6921
6922   if (node_length > length)
6923     goto broken_atom_size;
6924
6925   if (type->flags & QT_FLAG_CONTAINER) {
6926     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
6927   } else {
6928     switch (fourcc) {
6929       case FOURCC_stsd:
6930       {
6931         if (node_length < 20) {
6932           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
6933           break;
6934         }
6935         GST_DEBUG_OBJECT (qtdemux,
6936             "parsing stsd (sample table, sample description) atom");
6937         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
6938         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6939         break;
6940       }
6941       case FOURCC_mp4a:
6942       case FOURCC_alac:
6943       {
6944         guint32 version;
6945         guint32 offset;
6946         guint min_size;
6947
6948         /* also read alac (or whatever) in stead of mp4a in the following,
6949          * since a similar layout is used in other cases as well */
6950         if (fourcc == FOURCC_mp4a)
6951           min_size = 20;
6952         else
6953           min_size = 40;
6954
6955         /* There are two things we might encounter here: a true mp4a atom, and
6956            an mp4a entry in an stsd atom. The latter is what we're interested
6957            in, and it looks like an atom, but isn't really one. The true mp4a
6958            atom is short, so we detect it based on length here. */
6959         if (length < min_size) {
6960           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
6961               GST_FOURCC_ARGS (fourcc));
6962           break;
6963         }
6964
6965         /* 'version' here is the sound sample description version. Types 0 and
6966            1 are documented in the QTFF reference, but type 2 is not: it's
6967            described in Apple header files instead (struct SoundDescriptionV2
6968            in Movies.h) */
6969         version = QT_UINT16 (buffer + 16);
6970
6971         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
6972             GST_FOURCC_ARGS (fourcc), version);
6973
6974         /* parse any esds descriptors */
6975         switch (version) {
6976           case 0:
6977             offset = 0x24;
6978             break;
6979           case 1:
6980             offset = 0x34;
6981             break;
6982           case 2:
6983             offset = 0x48;
6984             break;
6985           default:
6986             GST_WARNING_OBJECT (qtdemux,
6987                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
6988                 GST_FOURCC_ARGS (fourcc), version);
6989             offset = 0;
6990             break;
6991         }
6992         if (offset)
6993           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6994         break;
6995       }
6996       case FOURCC_mp4v:
6997       case FOURCC_MP4V:
6998       case FOURCC_fmp4:
6999       case FOURCC_FMP4:
7000       case FOURCC_apcs:
7001       case FOURCC_apch:
7002       case FOURCC_apcn:
7003       case FOURCC_apco:
7004       case FOURCC_ap4h:
7005       {
7006         const guint8 *buf;
7007         guint32 version;
7008         int tlen;
7009
7010         /* codec_data is contained inside these atoms, which all have
7011          * the same format. */
7012
7013         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7014             GST_FOURCC_ARGS (fourcc));
7015         version = QT_UINT32 (buffer + 16);
7016         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7017         if (1 || version == 0x00000000) {
7018           buf = buffer + 0x32;
7019
7020           /* FIXME Quicktime uses PASCAL string while
7021            * the iso format uses C strings. Check the file
7022            * type before attempting to parse the string here. */
7023           tlen = QT_UINT8 (buf);
7024           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
7025           buf++;
7026           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
7027           /* the string has a reserved space of 32 bytes so skip
7028            * the remaining 31 */
7029           buf += 31;
7030           buf += 4;             /* and 4 bytes reserved */
7031
7032           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
7033
7034           qtdemux_parse_container (qtdemux, node, buf, end);
7035         }
7036         break;
7037       }
7038       case FOURCC_H264:
7039       {
7040         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
7041         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7042         break;
7043       }
7044       case FOURCC_avc1:
7045       {
7046         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
7047         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7048         break;
7049       }
7050       case FOURCC_avc3:
7051       {
7052         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
7053         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7054         break;
7055       }
7056       case FOURCC_H265:
7057       {
7058         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
7059         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7060         break;
7061       }
7062       case FOURCC_hvc1:
7063       {
7064         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
7065         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7066         break;
7067       }
7068       case FOURCC_hev1:
7069       {
7070         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
7071         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7072         break;
7073       }
7074       case FOURCC_mjp2:
7075       {
7076         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7077         break;
7078       }
7079       case FOURCC_meta:
7080       {
7081         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7082         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7083         break;
7084       }
7085       case FOURCC_mp4s:
7086       {
7087         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7088         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7089         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7090         break;
7091       }
7092       case FOURCC_XiTh:
7093       {
7094         guint32 version;
7095         guint32 offset;
7096
7097         version = QT_UINT32 (buffer + 12);
7098         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7099
7100         switch (version) {
7101           case 0x00000001:
7102             offset = 0x62;
7103             break;
7104           default:
7105             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7106             offset = 0;
7107             break;
7108         }
7109         if (offset)
7110           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7111         break;
7112       }
7113       case FOURCC_in24:
7114       {
7115         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7116         break;
7117       }
7118       case FOURCC_uuid:
7119       {
7120         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7121         break;
7122       }
7123       case FOURCC_encv:
7124       {
7125         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7126         break;
7127       }
7128       case FOURCC_enca:
7129       {
7130         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7131         break;
7132       }
7133       default:
7134         if (!strcmp (type->name, "unknown"))
7135           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7136         break;
7137     }
7138   }
7139   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7140       GST_FOURCC_ARGS (fourcc));
7141   return TRUE;
7142
7143 /* ERRORS */
7144 not_enough_data:
7145   {
7146     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7147         (_("This file is corrupt and cannot be played.")),
7148         ("Not enough data for an atom header, got only %u bytes", length));
7149     return FALSE;
7150   }
7151 broken_atom_size:
7152   {
7153     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7154         (_("This file is corrupt and cannot be played.")),
7155         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7156             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7157             length));
7158     return FALSE;
7159   }
7160 }
7161
7162 static GNode *
7163 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7164 {
7165   GNode *child;
7166   guint8 *buffer;
7167   guint32 child_fourcc;
7168
7169   for (child = g_node_first_child (node); child;
7170       child = g_node_next_sibling (child)) {
7171     buffer = (guint8 *) child->data;
7172
7173     child_fourcc = QT_FOURCC (buffer + 4);
7174
7175     if (G_UNLIKELY (child_fourcc == fourcc)) {
7176       return child;
7177     }
7178   }
7179   return NULL;
7180 }
7181
7182 static GNode *
7183 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7184     GstByteReader * parser)
7185 {
7186   GNode *child;
7187   guint8 *buffer;
7188   guint32 child_fourcc, child_len;
7189
7190   for (child = g_node_first_child (node); child;
7191       child = g_node_next_sibling (child)) {
7192     buffer = (guint8 *) child->data;
7193
7194     child_len = QT_UINT32 (buffer);
7195     child_fourcc = QT_FOURCC (buffer + 4);
7196
7197     if (G_UNLIKELY (child_fourcc == fourcc)) {
7198       if (G_UNLIKELY (child_len < (4 + 4)))
7199         return NULL;
7200       /* FIXME: must verify if atom length < parent atom length */
7201       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7202       return child;
7203     }
7204   }
7205   return NULL;
7206 }
7207
7208 static GNode *
7209 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7210     GstByteReader * parser)
7211 {
7212   GNode *child;
7213   guint8 *buffer;
7214   guint32 child_fourcc, child_len;
7215
7216   for (child = g_node_next_sibling (node); child;
7217       child = g_node_next_sibling (child)) {
7218     buffer = (guint8 *) child->data;
7219
7220     child_fourcc = QT_FOURCC (buffer + 4);
7221
7222     if (child_fourcc == fourcc) {
7223       if (parser) {
7224         child_len = QT_UINT32 (buffer);
7225         if (G_UNLIKELY (child_len < (4 + 4)))
7226           return NULL;
7227         /* FIXME: must verify if atom length < parent atom length */
7228         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7229       }
7230       return child;
7231     }
7232   }
7233   return NULL;
7234 }
7235
7236 static GNode *
7237 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7238 {
7239   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7240 }
7241
7242 static void
7243 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7244 {
7245 /* FIXME: This can only reliably work if demuxers have a
7246  * separate streaming thread per srcpad. This should be
7247  * done in a demuxer base class, which integrates parts
7248  * of multiqueue
7249  *
7250  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7251  */
7252 #if 0
7253   GstQuery *query;
7254
7255   query = gst_query_new_allocation (stream->caps, FALSE);
7256
7257   if (!gst_pad_peer_query (stream->pad, query)) {
7258     /* not a problem, just debug a little */
7259     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7260   }
7261
7262   if (stream->allocator)
7263     gst_object_unref (stream->allocator);
7264
7265   if (gst_query_get_n_allocation_params (query) > 0) {
7266     /* try the allocator */
7267     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7268         &stream->params);
7269     stream->use_allocator = TRUE;
7270   } else {
7271     stream->allocator = NULL;
7272     gst_allocation_params_init (&stream->params);
7273     stream->use_allocator = FALSE;
7274   }
7275   gst_query_unref (query);
7276 #endif
7277 }
7278
7279 static gboolean
7280 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7281     QtDemuxStream * stream)
7282 {
7283   GstStructure *s;
7284   const gchar *selected_system;
7285
7286   g_return_val_if_fail (qtdemux != NULL, FALSE);
7287   g_return_val_if_fail (stream != NULL, FALSE);
7288   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7289
7290   if (stream->protection_scheme_type != FOURCC_cenc) {
7291     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7292     return FALSE;
7293   }
7294   if (qtdemux->protection_system_ids == NULL) {
7295     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7296         "cenc protection system information has been found");
7297     return FALSE;
7298   }
7299   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7300   selected_system = gst_protection_select_system ((const gchar **)
7301       qtdemux->protection_system_ids->pdata);
7302   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7303       qtdemux->protection_system_ids->len - 1);
7304   if (!selected_system) {
7305     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7306         "suitable decryptor element has been found");
7307     return FALSE;
7308   }
7309
7310   s = gst_caps_get_structure (stream->caps, 0);
7311   if (!gst_structure_has_name (s, "application/x-cenc")) {
7312     gst_structure_set (s,
7313         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7314         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7315         NULL);
7316     gst_structure_set_name (s, "application/x-cenc");
7317   }
7318   return TRUE;
7319 }
7320
7321 static gboolean
7322 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7323 {
7324   if (stream->subtype == FOURCC_vide) {
7325     /* fps is calculated base on the duration of the average framerate since
7326      * qt does not have a fixed framerate. */
7327     gboolean fps_available = TRUE;
7328
7329     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7330       /* still frame */
7331       stream->fps_n = 0;
7332       stream->fps_d = 1;
7333     } else {
7334       if (stream->duration == 0 || stream->n_samples < 2) {
7335         stream->fps_n = stream->timescale;
7336         stream->fps_d = 1;
7337         fps_available = FALSE;
7338       } else {
7339         GstClockTime avg_duration;
7340         guint64 duration;
7341         guint32 n_samples;
7342
7343         /* duration and n_samples can be updated for fragmented format
7344          * so, framerate of fragmented format is calculated using data in a moof */
7345         if (qtdemux->fragmented && stream->n_samples_moof > 0
7346             && stream->duration_moof > 0) {
7347           n_samples = stream->n_samples_moof;
7348           duration = stream->duration_moof;
7349         } else {
7350           n_samples = stream->n_samples;
7351           duration = stream->duration;
7352         }
7353
7354         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7355         /* stream->duration is guint64, timescale, n_samples are guint32 */
7356         avg_duration =
7357             gst_util_uint64_scale_round (duration -
7358             stream->first_duration, GST_SECOND,
7359             (guint64) (stream->timescale) * (n_samples - 1));
7360
7361         GST_LOG_OBJECT (qtdemux,
7362             "Calculating avg sample duration based on stream (or moof) duration %"
7363             G_GUINT64_FORMAT
7364             " minus first sample %u, leaving %d samples gives %"
7365             GST_TIME_FORMAT, duration, stream->first_duration,
7366             n_samples - 1, GST_TIME_ARGS (avg_duration));
7367
7368         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7369             &stream->fps_d);
7370
7371         GST_DEBUG_OBJECT (qtdemux,
7372             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7373             stream->timescale, stream->fps_n, stream->fps_d);
7374       }
7375     }
7376
7377     if (stream->caps) {
7378       stream->caps = gst_caps_make_writable (stream->caps);
7379
7380       gst_caps_set_simple (stream->caps,
7381           "width", G_TYPE_INT, stream->width,
7382           "height", G_TYPE_INT, stream->height, NULL);
7383
7384       /* set framerate if calculated framerate is reliable */
7385       if (fps_available) {
7386         gst_caps_set_simple (stream->caps,
7387             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7388       }
7389
7390       /* calculate pixel-aspect-ratio using display width and height */
7391       GST_DEBUG_OBJECT (qtdemux,
7392           "video size %dx%d, target display size %dx%d", stream->width,
7393           stream->height, stream->display_width, stream->display_height);
7394       /* qt file might have pasp atom */
7395       if (stream->par_w > 0 && stream->par_h > 0) {
7396         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7397         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7398             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7399       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7400           stream->width > 0 && stream->height > 0) {
7401         gint n, d;
7402
7403         /* calculate the pixel aspect ratio using the display and pixel w/h */
7404         n = stream->display_width * stream->height;
7405         d = stream->display_height * stream->width;
7406         if (n == d)
7407           n = d = 1;
7408         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7409         stream->par_w = n;
7410         stream->par_h = d;
7411         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7412             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7413       }
7414
7415       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7416         guint par_w = 1, par_h = 1;
7417
7418         if (stream->par_w > 0 && stream->par_h > 0) {
7419           par_w = stream->par_w;
7420           par_h = stream->par_h;
7421         }
7422
7423         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7424                 stream->width, stream->height, par_w, par_h)) {
7425           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7426         }
7427
7428         gst_caps_set_simple (stream->caps,
7429             "multiview-mode", G_TYPE_STRING,
7430             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7431             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7432             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7433       }
7434     }
7435   }
7436
7437   else if (stream->subtype == FOURCC_soun) {
7438     if (stream->caps) {
7439       stream->caps = gst_caps_make_writable (stream->caps);
7440       if (stream->rate > 0)
7441         gst_caps_set_simple (stream->caps,
7442             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7443       if (stream->n_channels > 0)
7444         gst_caps_set_simple (stream->caps,
7445             "channels", G_TYPE_INT, stream->n_channels, NULL);
7446       if (stream->n_channels > 2) {
7447         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7448          * correctly; this is just the minimum we can do - assume
7449          * we don't actually have any channel positions. */
7450         gst_caps_set_simple (stream->caps,
7451             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7452       }
7453     }
7454   }
7455
7456   if (stream->pad) {
7457     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7458     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7459     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7460     gst_pad_set_active (stream->pad, TRUE);
7461
7462     gst_pad_use_fixed_caps (stream->pad);
7463
7464     if (stream->protected) {
7465       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7466         GST_ERROR_OBJECT (qtdemux,
7467             "Failed to configure protected stream caps.");
7468         return FALSE;
7469       }
7470     }
7471
7472     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7473     if (stream->new_stream) {
7474       gchar *stream_id;
7475       GstEvent *event;
7476       GstStreamFlags stream_flags;
7477
7478       event =
7479           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7480           0);
7481       if (event) {
7482         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7483           qtdemux->have_group_id = TRUE;
7484         else
7485           qtdemux->have_group_id = FALSE;
7486         gst_event_unref (event);
7487       } else if (!qtdemux->have_group_id) {
7488         qtdemux->have_group_id = TRUE;
7489         qtdemux->group_id = gst_util_group_id_next ();
7490       }
7491
7492       stream->new_stream = FALSE;
7493       stream_id =
7494           gst_pad_create_stream_id_printf (stream->pad,
7495           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7496       event = gst_event_new_stream_start (stream_id);
7497       if (qtdemux->have_group_id)
7498         gst_event_set_group_id (event, qtdemux->group_id);
7499       stream_flags = GST_STREAM_FLAG_NONE;
7500       if (stream->disabled)
7501         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7502       if (stream->sparse)
7503         stream_flags |= GST_STREAM_FLAG_SPARSE;
7504       gst_event_set_stream_flags (event, stream_flags);
7505       gst_pad_push_event (stream->pad, event);
7506       g_free (stream_id);
7507     }
7508     gst_pad_set_caps (stream->pad, stream->caps);
7509     stream->new_caps = FALSE;
7510   }
7511   return TRUE;
7512 }
7513
7514 static gboolean
7515 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7516     QtDemuxStream * stream, GstTagList * list)
7517 {
7518   gboolean ret = TRUE;
7519   /* consistent default for push based mode */
7520   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7521
7522   if (stream->subtype == FOURCC_vide) {
7523     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7524
7525     stream->pad =
7526         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7527     g_free (name);
7528
7529     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7530       gst_object_unref (stream->pad);
7531       stream->pad = NULL;
7532       ret = FALSE;
7533       goto done;
7534     }
7535
7536     qtdemux->n_video_streams++;
7537   } else if (stream->subtype == FOURCC_soun) {
7538     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7539
7540     stream->pad =
7541         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7542     g_free (name);
7543     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7544       gst_object_unref (stream->pad);
7545       stream->pad = NULL;
7546       ret = FALSE;
7547       goto done;
7548     }
7549     qtdemux->n_audio_streams++;
7550   } else if (stream->subtype == FOURCC_strm) {
7551     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7552   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7553       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7554     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7555
7556     stream->pad =
7557         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7558     g_free (name);
7559     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7560       gst_object_unref (stream->pad);
7561       stream->pad = NULL;
7562       ret = FALSE;
7563       goto done;
7564     }
7565     qtdemux->n_sub_streams++;
7566   } else if (stream->caps) {
7567     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7568
7569     stream->pad =
7570         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7571     g_free (name);
7572     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7573       gst_object_unref (stream->pad);
7574       stream->pad = NULL;
7575       ret = FALSE;
7576       goto done;
7577     }
7578     qtdemux->n_video_streams++;
7579   } else {
7580     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7581     goto done;
7582   }
7583
7584   if (stream->pad) {
7585     GList *l;
7586
7587     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7588         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7589     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7590     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7591
7592     if (stream->pending_tags)
7593       gst_tag_list_unref (stream->pending_tags);
7594     stream->pending_tags = list;
7595     list = NULL;
7596     /* global tags go on each pad anyway */
7597     stream->send_global_tags = TRUE;
7598     /* send upstream GST_EVENT_PROTECTION events that were received before
7599        this source pad was created */
7600     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7601       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7602   }
7603 done:
7604   if (list)
7605     gst_tag_list_unref (list);
7606   return ret;
7607 }
7608
7609 /* find next atom with @fourcc starting at @offset */
7610 static GstFlowReturn
7611 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7612     guint64 * length, guint32 fourcc)
7613 {
7614   GstFlowReturn ret;
7615   guint32 lfourcc;
7616   GstBuffer *buf;
7617
7618   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7619       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7620
7621   while (TRUE) {
7622     GstMapInfo map;
7623
7624     buf = NULL;
7625     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7626     if (G_UNLIKELY (ret != GST_FLOW_OK))
7627       goto locate_failed;
7628     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7629       /* likely EOF */
7630       ret = GST_FLOW_EOS;
7631       gst_buffer_unref (buf);
7632       goto locate_failed;
7633     }
7634     gst_buffer_map (buf, &map, GST_MAP_READ);
7635     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7636     gst_buffer_unmap (buf, &map);
7637     gst_buffer_unref (buf);
7638
7639     if (G_UNLIKELY (*length == 0)) {
7640       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7641       ret = GST_FLOW_ERROR;
7642       goto locate_failed;
7643     }
7644
7645     if (lfourcc == fourcc) {
7646       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7647           *offset);
7648       break;
7649     } else {
7650       GST_LOG_OBJECT (qtdemux,
7651           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7652           GST_FOURCC_ARGS (fourcc), *offset);
7653       *offset += *length;
7654     }
7655   }
7656
7657   return GST_FLOW_OK;
7658
7659 locate_failed:
7660   {
7661     /* might simply have had last one */
7662     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7663     return ret;
7664   }
7665 }
7666
7667 /* should only do something in pull mode */
7668 /* call with OBJECT lock */
7669 static GstFlowReturn
7670 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7671 {
7672   guint64 length, offset;
7673   GstBuffer *buf = NULL;
7674   GstFlowReturn ret = GST_FLOW_OK;
7675   GstFlowReturn res = GST_FLOW_OK;
7676   GstMapInfo map;
7677
7678   offset = qtdemux->moof_offset;
7679   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7680
7681   if (!offset) {
7682     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7683     return GST_FLOW_EOS;
7684   }
7685
7686   /* best not do pull etc with lock held */
7687   GST_OBJECT_UNLOCK (qtdemux);
7688
7689   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7690   if (ret != GST_FLOW_OK)
7691     goto flow_failed;
7692
7693   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7694   if (G_UNLIKELY (ret != GST_FLOW_OK))
7695     goto flow_failed;
7696   gst_buffer_map (buf, &map, GST_MAP_READ);
7697   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7698     gst_buffer_unmap (buf, &map);
7699     gst_buffer_unref (buf);
7700     buf = NULL;
7701     goto parse_failed;
7702   }
7703
7704   gst_buffer_unmap (buf, &map);
7705   gst_buffer_unref (buf);
7706   buf = NULL;
7707
7708   offset += length;
7709   /* look for next moof */
7710   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7711   if (G_UNLIKELY (ret != GST_FLOW_OK))
7712     goto flow_failed;
7713
7714 exit:
7715   GST_OBJECT_LOCK (qtdemux);
7716
7717   qtdemux->moof_offset = offset;
7718
7719   return res;
7720
7721 parse_failed:
7722   {
7723     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7724     offset = 0;
7725     res = GST_FLOW_ERROR;
7726     goto exit;
7727   }
7728 flow_failed:
7729   {
7730     /* maybe upstream temporarily flushing */
7731     if (ret != GST_FLOW_FLUSHING) {
7732       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7733       offset = 0;
7734     } else {
7735       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7736       /* resume at current position next time */
7737     }
7738     res = ret;
7739     goto exit;
7740   }
7741 }
7742
7743 /* initialise bytereaders for stbl sub-atoms */
7744 static gboolean
7745 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7746 {
7747   stream->stbl_index = -1;      /* no samples have yet been parsed */
7748   stream->sample_index = -1;
7749
7750   /* time-to-sample atom */
7751   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7752     goto corrupt_file;
7753
7754   /* copy atom data into a new buffer for later use */
7755   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7756
7757   /* skip version + flags */
7758   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7759       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7760     goto corrupt_file;
7761   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7762
7763   /* make sure there's enough data */
7764   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7765     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7766     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7767         stream->n_sample_times);
7768     if (!stream->n_sample_times)
7769       goto corrupt_file;
7770   }
7771
7772   /* sync sample atom */
7773   stream->stps_present = FALSE;
7774   if ((stream->stss_present =
7775           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7776               &stream->stss) ? TRUE : FALSE) == TRUE) {
7777     /* copy atom data into a new buffer for later use */
7778     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7779
7780     /* skip version + flags */
7781     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7782         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7783       goto corrupt_file;
7784
7785     if (stream->n_sample_syncs) {
7786       /* make sure there's enough data */
7787       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7788         goto corrupt_file;
7789     }
7790
7791     /* partial sync sample atom */
7792     if ((stream->stps_present =
7793             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7794                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7795       /* copy atom data into a new buffer for later use */
7796       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7797
7798       /* skip version + flags */
7799       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7800           !gst_byte_reader_get_uint32_be (&stream->stps,
7801               &stream->n_sample_partial_syncs))
7802         goto corrupt_file;
7803
7804       /* if there are no entries, the stss table contains the real
7805        * sync samples */
7806       if (stream->n_sample_partial_syncs) {
7807         /* make sure there's enough data */
7808         if (!qt_atom_parser_has_chunks (&stream->stps,
7809                 stream->n_sample_partial_syncs, 4))
7810           goto corrupt_file;
7811       }
7812     }
7813   }
7814
7815   /* sample size */
7816   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7817     goto no_samples;
7818
7819   /* copy atom data into a new buffer for later use */
7820   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7821
7822   /* skip version + flags */
7823   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7824       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7825     goto corrupt_file;
7826
7827   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7828     goto corrupt_file;
7829
7830   if (!stream->n_samples)
7831     goto no_samples;
7832
7833   /* sample-to-chunk atom */
7834   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7835     goto corrupt_file;
7836
7837   /* copy atom data into a new buffer for later use */
7838   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7839
7840   /* skip version + flags */
7841   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7842       !gst_byte_reader_get_uint32_be (&stream->stsc,
7843           &stream->n_samples_per_chunk))
7844     goto corrupt_file;
7845
7846   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7847       stream->n_samples_per_chunk);
7848
7849   /* make sure there's enough data */
7850   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7851           12))
7852     goto corrupt_file;
7853
7854
7855   /* chunk offset */
7856   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7857     stream->co_size = sizeof (guint32);
7858   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7859           &stream->stco))
7860     stream->co_size = sizeof (guint64);
7861   else
7862     goto corrupt_file;
7863
7864   /* copy atom data into a new buffer for later use */
7865   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7866
7867   /* skip version + flags */
7868   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7869     goto corrupt_file;
7870
7871   /* chunks_are_samples == TRUE means treat chunks as samples */
7872   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7873   if (stream->chunks_are_samples) {
7874     /* treat chunks as samples */
7875     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7876       goto corrupt_file;
7877   } else {
7878     /* skip number of entries */
7879     if (!gst_byte_reader_skip (&stream->stco, 4))
7880       goto corrupt_file;
7881
7882     /* make sure there are enough data in the stsz atom */
7883     if (!stream->sample_size) {
7884       /* different sizes for each sample */
7885       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7886         goto corrupt_file;
7887     }
7888   }
7889
7890   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7891       stream->n_samples, (guint) sizeof (QtDemuxSample),
7892       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7893
7894   if (stream->n_samples >=
7895       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7896     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7897         "be larger than %uMB (broken file?)", stream->n_samples,
7898         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7899     return FALSE;
7900   }
7901
7902   g_assert (stream->samples == NULL);
7903   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7904   if (!stream->samples) {
7905     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7906         stream->n_samples);
7907     return FALSE;
7908   }
7909
7910   /* composition time-to-sample */
7911   if ((stream->ctts_present =
7912           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7913               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7914     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7915
7916     /* copy atom data into a new buffer for later use */
7917     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7918
7919     /* skip version + flags */
7920     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7921         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7922             &stream->n_composition_times))
7923       goto corrupt_file;
7924
7925     /* make sure there's enough data */
7926     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7927             4 + 4))
7928       goto corrupt_file;
7929
7930     /* This is optional, if missing we iterate the ctts */
7931     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7932       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7933           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7934         g_free ((gpointer) cslg.data);
7935         goto corrupt_file;
7936       }
7937     } else {
7938       gint32 cslg_least = 0;
7939       guint num_entries, pos;
7940       gint i;
7941
7942       pos = gst_byte_reader_get_pos (&stream->ctts);
7943       num_entries = stream->n_composition_times;
7944
7945       stream->cslg_shift = 0;
7946
7947       for (i = 0; i < num_entries; i++) {
7948         gint32 offset;
7949
7950         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7951         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7952
7953         if (offset < cslg_least)
7954           cslg_least = offset;
7955       }
7956
7957       if (cslg_least < 0)
7958         stream->cslg_shift = ABS (cslg_least);
7959       else
7960         stream->cslg_shift = 0;
7961
7962       /* reset the reader so we can generate sample table */
7963       gst_byte_reader_set_pos (&stream->ctts, pos);
7964     }
7965   } else {
7966     /* Ensure the cslg_shift value is consistent so we can use it
7967      * unconditionnally to produce TS and Segment */
7968     stream->cslg_shift = 0;
7969   }
7970
7971   return TRUE;
7972
7973 corrupt_file:
7974   {
7975     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7976         (_("This file is corrupt and cannot be played.")), (NULL));
7977     return FALSE;
7978   }
7979 no_samples:
7980   {
7981     gst_qtdemux_stbl_free (stream);
7982     if (!qtdemux->fragmented) {
7983       /* not quite good */
7984       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
7985       return FALSE;
7986     } else {
7987       /* may pick up samples elsewhere */
7988       return TRUE;
7989     }
7990   }
7991 }
7992
7993 /* collect samples from the next sample to be parsed up to sample @n for @stream
7994  * by reading the info from @stbl
7995  *
7996  * This code can be executed from both the streaming thread and the seeking
7997  * thread so it takes the object lock to protect itself
7998  */
7999 static gboolean
8000 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8001 {
8002   gint i, j, k;
8003   QtDemuxSample *samples, *first, *cur, *last;
8004   guint32 n_samples_per_chunk;
8005   guint32 n_samples;
8006
8007   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8008       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8009       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8010
8011   n_samples = stream->n_samples;
8012
8013   if (n >= n_samples)
8014     goto out_of_samples;
8015
8016   GST_OBJECT_LOCK (qtdemux);
8017   if (n <= stream->stbl_index)
8018     goto already_parsed;
8019
8020   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8021
8022   if (!stream->stsz.data) {
8023     /* so we already parsed and passed all the moov samples;
8024      * onto fragmented ones */
8025     g_assert (qtdemux->fragmented);
8026     goto done;
8027   }
8028
8029   /* pointer to the sample table */
8030   samples = stream->samples;
8031
8032   /* starts from -1, moves to the next sample index to parse */
8033   stream->stbl_index++;
8034
8035   /* keep track of the first and last sample to fill */
8036   first = &samples[stream->stbl_index];
8037   last = &samples[n];
8038
8039   if (!stream->chunks_are_samples) {
8040     /* set the sample sizes */
8041     if (stream->sample_size == 0) {
8042       /* different sizes for each sample */
8043       for (cur = first; cur <= last; cur++) {
8044         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8045         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8046             (guint) (cur - samples), cur->size);
8047       }
8048     } else {
8049       /* samples have the same size */
8050       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8051       for (cur = first; cur <= last; cur++)
8052         cur->size = stream->sample_size;
8053     }
8054   }
8055
8056   n_samples_per_chunk = stream->n_samples_per_chunk;
8057   cur = first;
8058
8059   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8060     guint32 last_chunk;
8061
8062     if (stream->stsc_chunk_index >= stream->last_chunk
8063         || stream->stsc_chunk_index < stream->first_chunk) {
8064       stream->first_chunk =
8065           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8066       stream->samples_per_chunk =
8067           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8068       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8069
8070       /* chunk numbers are counted from 1 it seems */
8071       if (G_UNLIKELY (stream->first_chunk == 0))
8072         goto corrupt_file;
8073
8074       --stream->first_chunk;
8075
8076       /* the last chunk of each entry is calculated by taking the first chunk
8077        * of the next entry; except if there is no next, where we fake it with
8078        * INT_MAX */
8079       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8080         stream->last_chunk = G_MAXUINT32;
8081       } else {
8082         stream->last_chunk =
8083             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8084         if (G_UNLIKELY (stream->last_chunk == 0))
8085           goto corrupt_file;
8086
8087         --stream->last_chunk;
8088       }
8089
8090       GST_LOG_OBJECT (qtdemux,
8091           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8092           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8093
8094       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8095         goto corrupt_file;
8096
8097       if (stream->last_chunk != G_MAXUINT32) {
8098         if (!qt_atom_parser_peek_sub (&stream->stco,
8099                 stream->first_chunk * stream->co_size,
8100                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8101                 &stream->co_chunk))
8102           goto corrupt_file;
8103
8104       } else {
8105         stream->co_chunk = stream->stco;
8106         if (!gst_byte_reader_skip (&stream->co_chunk,
8107                 stream->first_chunk * stream->co_size))
8108           goto corrupt_file;
8109       }
8110
8111       stream->stsc_chunk_index = stream->first_chunk;
8112     }
8113
8114     last_chunk = stream->last_chunk;
8115
8116     if (stream->chunks_are_samples) {
8117       cur = &samples[stream->stsc_chunk_index];
8118
8119       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8120         if (j > n) {
8121           /* save state */
8122           stream->stsc_chunk_index = j;
8123           goto done;
8124         }
8125
8126         cur->offset =
8127             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8128             stream->co_size);
8129
8130         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8131             "%" G_GUINT64_FORMAT, j, cur->offset);
8132
8133         if (stream->samples_per_frame * stream->bytes_per_frame) {
8134           cur->size =
8135               (stream->samples_per_chunk * stream->n_channels) /
8136               stream->samples_per_frame * stream->bytes_per_frame;
8137         } else {
8138           cur->size = stream->samples_per_chunk;
8139         }
8140
8141         GST_DEBUG_OBJECT (qtdemux,
8142             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8143             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8144                     stream->stco_sample_index)), cur->size);
8145
8146         cur->timestamp = stream->stco_sample_index;
8147         cur->duration = stream->samples_per_chunk;
8148         cur->keyframe = TRUE;
8149         cur++;
8150
8151         stream->stco_sample_index += stream->samples_per_chunk;
8152       }
8153       stream->stsc_chunk_index = j;
8154     } else {
8155       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8156         guint32 samples_per_chunk;
8157         guint64 chunk_offset;
8158
8159         if (!stream->stsc_sample_index
8160             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8161                 &stream->chunk_offset))
8162           goto corrupt_file;
8163
8164         samples_per_chunk = stream->samples_per_chunk;
8165         chunk_offset = stream->chunk_offset;
8166
8167         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8168           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8169               G_GUINT64_FORMAT " and size %d",
8170               (guint) (cur - samples), chunk_offset, cur->size);
8171
8172           cur->offset = chunk_offset;
8173           chunk_offset += cur->size;
8174           cur++;
8175
8176           if (G_UNLIKELY (cur > last)) {
8177             /* save state */
8178             stream->stsc_sample_index = k + 1;
8179             stream->chunk_offset = chunk_offset;
8180             stream->stsc_chunk_index = j;
8181             goto done2;
8182           }
8183         }
8184         stream->stsc_sample_index = 0;
8185       }
8186       stream->stsc_chunk_index = j;
8187     }
8188     stream->stsc_index++;
8189   }
8190
8191   if (stream->chunks_are_samples)
8192     goto ctts;
8193 done2:
8194   {
8195     guint32 n_sample_times;
8196
8197     n_sample_times = stream->n_sample_times;
8198     cur = first;
8199
8200     for (i = stream->stts_index; i < n_sample_times; i++) {
8201       guint32 stts_samples;
8202       gint32 stts_duration;
8203       gint64 stts_time;
8204
8205       if (stream->stts_sample_index >= stream->stts_samples
8206           || !stream->stts_sample_index) {
8207
8208         stream->stts_samples =
8209             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8210         stream->stts_duration =
8211             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8212
8213         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8214             i, stream->stts_samples, stream->stts_duration);
8215
8216         stream->stts_sample_index = 0;
8217       }
8218
8219       stts_samples = stream->stts_samples;
8220       stts_duration = stream->stts_duration;
8221       stts_time = stream->stts_time;
8222
8223       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8224         GST_DEBUG_OBJECT (qtdemux,
8225             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8226             (guint) (cur - samples), j,
8227             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8228
8229         cur->timestamp = stts_time;
8230         cur->duration = stts_duration;
8231
8232         /* avoid 32-bit wrap-around,
8233          * but still mind possible 'negative' duration */
8234         stts_time += (gint64) stts_duration;
8235         cur++;
8236
8237         if (G_UNLIKELY (cur > last)) {
8238           /* save values */
8239           stream->stts_time = stts_time;
8240           stream->stts_sample_index = j + 1;
8241           goto done3;
8242         }
8243       }
8244       stream->stts_sample_index = 0;
8245       stream->stts_time = stts_time;
8246       stream->stts_index++;
8247     }
8248     /* fill up empty timestamps with the last timestamp, this can happen when
8249      * the last samples do not decode and so we don't have timestamps for them.
8250      * We however look at the last timestamp to estimate the track length so we
8251      * need something in here. */
8252     for (; cur < last; cur++) {
8253       GST_DEBUG_OBJECT (qtdemux,
8254           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8255           (guint) (cur - samples),
8256           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8257       cur->timestamp = stream->stts_time;
8258       cur->duration = -1;
8259     }
8260   }
8261 done3:
8262   {
8263     /* sample sync, can be NULL */
8264     if (stream->stss_present == TRUE) {
8265       guint32 n_sample_syncs;
8266
8267       n_sample_syncs = stream->n_sample_syncs;
8268
8269       if (!n_sample_syncs) {
8270         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8271         stream->all_keyframe = TRUE;
8272       } else {
8273         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8274           /* note that the first sample is index 1, not 0 */
8275           guint32 index;
8276
8277           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8278
8279           if (G_LIKELY (index > 0 && index <= n_samples)) {
8280             index -= 1;
8281             samples[index].keyframe = TRUE;
8282             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8283             /* and exit if we have enough samples */
8284             if (G_UNLIKELY (index >= n)) {
8285               i++;
8286               break;
8287             }
8288           }
8289         }
8290         /* save state */
8291         stream->stss_index = i;
8292       }
8293
8294       /* stps marks partial sync frames like open GOP I-Frames */
8295       if (stream->stps_present == TRUE) {
8296         guint32 n_sample_partial_syncs;
8297
8298         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8299
8300         /* if there are no entries, the stss table contains the real
8301          * sync samples */
8302         if (n_sample_partial_syncs) {
8303           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8304             /* note that the first sample is index 1, not 0 */
8305             guint32 index;
8306
8307             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8308
8309             if (G_LIKELY (index > 0 && index <= n_samples)) {
8310               index -= 1;
8311               samples[index].keyframe = TRUE;
8312               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8313               /* and exit if we have enough samples */
8314               if (G_UNLIKELY (index >= n)) {
8315                 i++;
8316                 break;
8317               }
8318             }
8319           }
8320           /* save state */
8321           stream->stps_index = i;
8322         }
8323       }
8324     } else {
8325       /* no stss, all samples are keyframes */
8326       stream->all_keyframe = TRUE;
8327       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8328     }
8329   }
8330
8331 ctts:
8332   /* composition time to sample */
8333   if (stream->ctts_present == TRUE) {
8334     guint32 n_composition_times;
8335     guint32 ctts_count;
8336     gint32 ctts_soffset;
8337
8338     /* Fill in the pts_offsets */
8339     cur = first;
8340     n_composition_times = stream->n_composition_times;
8341
8342     for (i = stream->ctts_index; i < n_composition_times; i++) {
8343       if (stream->ctts_sample_index >= stream->ctts_count
8344           || !stream->ctts_sample_index) {
8345         stream->ctts_count =
8346             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8347         stream->ctts_soffset =
8348             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8349         stream->ctts_sample_index = 0;
8350       }
8351
8352       ctts_count = stream->ctts_count;
8353       ctts_soffset = stream->ctts_soffset;
8354
8355       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8356         cur->pts_offset = ctts_soffset;
8357         cur++;
8358
8359         if (G_UNLIKELY (cur > last)) {
8360           /* save state */
8361           stream->ctts_sample_index = j + 1;
8362           goto done;
8363         }
8364       }
8365       stream->ctts_sample_index = 0;
8366       stream->ctts_index++;
8367     }
8368   }
8369 done:
8370   stream->stbl_index = n;
8371   /* if index has been completely parsed, free data that is no-longer needed */
8372   if (n + 1 == stream->n_samples) {
8373     gst_qtdemux_stbl_free (stream);
8374     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8375     if (qtdemux->pullbased) {
8376       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8377       while (n + 1 == stream->n_samples)
8378         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8379           break;
8380     }
8381   }
8382   GST_OBJECT_UNLOCK (qtdemux);
8383
8384   return TRUE;
8385
8386   /* SUCCESS */
8387 already_parsed:
8388   {
8389     GST_LOG_OBJECT (qtdemux,
8390         "Tried to parse up to sample %u but this sample has already been parsed",
8391         n);
8392     /* if fragmented, there may be more */
8393     if (qtdemux->fragmented && n == stream->stbl_index)
8394       goto done;
8395     GST_OBJECT_UNLOCK (qtdemux);
8396     return TRUE;
8397   }
8398   /* ERRORS */
8399 out_of_samples:
8400   {
8401     GST_LOG_OBJECT (qtdemux,
8402         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8403         stream->n_samples);
8404     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8405         (_("This file is corrupt and cannot be played.")), (NULL));
8406     return FALSE;
8407   }
8408 corrupt_file:
8409   {
8410     GST_OBJECT_UNLOCK (qtdemux);
8411     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8412         (_("This file is corrupt and cannot be played.")), (NULL));
8413     return FALSE;
8414   }
8415 }
8416
8417 /* collect all segment info for @stream.
8418  */
8419 static gboolean
8420 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8421     GNode * trak)
8422 {
8423   GNode *edts;
8424   /* accept edts if they contain gaps at start and there is only
8425    * one media segment */
8426   gboolean allow_pushbased_edts = TRUE;
8427   gint media_segments_count = 0;
8428
8429   /* parse and prepare segment info from the edit list */
8430   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8431   stream->n_segments = 0;
8432   stream->segments = NULL;
8433   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8434     GNode *elst;
8435     gint n_segments;
8436     gint i, count, entry_size;
8437     guint64 time;
8438     GstClockTime stime;
8439     guint8 *buffer;
8440     guint8 version;
8441
8442     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8443     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8444       goto done;
8445
8446     buffer = elst->data;
8447
8448     version = QT_UINT8 (buffer + 8);
8449     entry_size = (version == 1) ? 20 : 12;
8450
8451     n_segments = QT_UINT32 (buffer + 12);
8452
8453     /* we might allocate a bit too much, at least allocate 1 segment */
8454     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8455
8456     /* segments always start from 0 */
8457     time = 0;
8458     stime = 0;
8459     count = 0;
8460     for (i = 0; i < n_segments; i++) {
8461       guint64 duration;
8462       guint64 media_time;
8463       gboolean time_valid = TRUE;
8464       QtDemuxSegment *segment;
8465       guint32 rate_int;
8466       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8467
8468       if (version == 1) {
8469         media_time = QT_UINT64 (buffer + 24 + i * entry_size);
8470         duration = QT_UINT64 (buffer + 16 + i * entry_size);
8471         if (media_time == G_MAXUINT64)
8472           time_valid = FALSE;
8473       } else {
8474         media_time = QT_UINT32 (buffer + 20 + i * entry_size);
8475         duration = QT_UINT32 (buffer + 16 + i * entry_size);
8476         if (media_time == G_MAXUINT32)
8477           time_valid = FALSE;
8478       }
8479
8480       if (time_valid)
8481         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8482
8483       segment = &stream->segments[count++];
8484
8485       /* time and duration expressed in global timescale */
8486       segment->time = stime;
8487       /* add non scaled values so we don't cause roundoff errors */
8488       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8489         time += duration;
8490         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8491         segment->duration = stime - segment->time;
8492       } else {
8493         /* zero duration does not imply media_start == media_stop
8494          * but, only specify media_start.*/
8495         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8496         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8497             && stime >= media_start) {
8498           segment->duration = stime - media_start;
8499         } else {
8500           segment->duration = GST_CLOCK_TIME_NONE;
8501         }
8502       }
8503       segment->stop_time = stime;
8504
8505       segment->trak_media_start = media_time;
8506       /* media_time expressed in stream timescale */
8507       if (time_valid) {
8508         segment->media_start = media_start;
8509         segment->media_stop = segment->media_start + segment->duration;
8510         media_segments_count++;
8511       } else {
8512         segment->media_start = GST_CLOCK_TIME_NONE;
8513         segment->media_stop = GST_CLOCK_TIME_NONE;
8514       }
8515       rate_int =
8516           QT_UINT32 (buffer + ((version == 1) ? 32 : 24) + i * entry_size);
8517
8518       if (rate_int <= 1) {
8519         /* 0 is not allowed, some programs write 1 instead of the floating point
8520          * value */
8521         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8522             rate_int);
8523         segment->rate = 1;
8524       } else {
8525         segment->rate = rate_int / 65536.0;
8526       }
8527
8528       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8529           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8530           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8531           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8532           i, GST_TIME_ARGS (segment->time),
8533           GST_TIME_ARGS (segment->duration),
8534           GST_TIME_ARGS (segment->media_start), media_time,
8535           GST_TIME_ARGS (segment->media_stop),
8536           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8537           stream->timescale);
8538       if (segment->stop_time > qtdemux->segment.stop) {
8539         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8540             " extends to %" GST_TIME_FORMAT
8541             " past the end of the file duration %" GST_TIME_FORMAT
8542             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8543             GST_TIME_ARGS (qtdemux->segment.stop));
8544         qtdemux->segment.stop = segment->stop_time;
8545       }
8546     }
8547     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8548     stream->n_segments = count;
8549     if (media_segments_count != 1)
8550       allow_pushbased_edts = FALSE;
8551   }
8552 done:
8553
8554   /* push based does not handle segments, so act accordingly here,
8555    * and warn if applicable */
8556   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8557     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8558     /* remove and use default one below, we stream like it anyway */
8559     g_free (stream->segments);
8560     stream->segments = NULL;
8561     stream->n_segments = 0;
8562   }
8563
8564   /* no segments, create one to play the complete trak */
8565   if (stream->n_segments == 0) {
8566     GstClockTime stream_duration =
8567         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8568
8569     if (stream->segments == NULL)
8570       stream->segments = g_new (QtDemuxSegment, 1);
8571
8572     /* represent unknown our way */
8573     if (stream_duration == 0)
8574       stream_duration = GST_CLOCK_TIME_NONE;
8575
8576     stream->segments[0].time = 0;
8577     stream->segments[0].stop_time = stream_duration;
8578     stream->segments[0].duration = stream_duration;
8579     stream->segments[0].media_start = 0;
8580     stream->segments[0].media_stop = stream_duration;
8581     stream->segments[0].rate = 1.0;
8582     stream->segments[0].trak_media_start = 0;
8583
8584     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8585         GST_TIME_ARGS (stream_duration));
8586     stream->n_segments = 1;
8587     stream->dummy_segment = TRUE;
8588   }
8589   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8590
8591   return TRUE;
8592 }
8593
8594 /*
8595  * Parses the stsd atom of a svq3 trak looking for
8596  * the SMI and gama atoms.
8597  */
8598 static void
8599 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8600     guint8 ** gamma, GstBuffer ** seqh)
8601 {
8602   guint8 *_gamma = NULL;
8603   GstBuffer *_seqh = NULL;
8604   guint8 *stsd_data = stsd->data;
8605   guint32 length = QT_UINT32 (stsd_data);
8606   guint16 version;
8607
8608   if (length < 32) {
8609     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8610     goto end;
8611   }
8612
8613   stsd_data += 32;
8614   length -= 32;
8615   version = QT_UINT16 (stsd_data);
8616   if (version == 3) {
8617     if (length >= 70) {
8618       length -= 70;
8619       stsd_data += 70;
8620       while (length > 8) {
8621         guint32 fourcc, size;
8622         guint8 *data;
8623         size = QT_UINT32 (stsd_data);
8624         fourcc = QT_FOURCC (stsd_data + 4);
8625         data = stsd_data + 8;
8626
8627         if (size == 0) {
8628           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8629               "svq3 atom parsing");
8630           goto end;
8631         }
8632
8633         switch (fourcc) {
8634           case FOURCC_gama:{
8635             if (size == 12) {
8636               _gamma = data;
8637             } else {
8638               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8639                   " for gama atom, expected 12", size);
8640             }
8641             break;
8642           }
8643           case FOURCC_SMI_:{
8644             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8645               guint32 seqh_size;
8646               if (_seqh != NULL) {
8647                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8648                     " found, ignoring");
8649               } else {
8650                 seqh_size = QT_UINT32 (data + 4);
8651                 if (seqh_size > 0) {
8652                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8653                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8654                 }
8655               }
8656             }
8657             break;
8658           }
8659           default:{
8660             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8661                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8662           }
8663         }
8664
8665         if (size <= length) {
8666           length -= size;
8667           stsd_data += size;
8668         }
8669       }
8670     } else {
8671       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8672     }
8673   } else {
8674     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8675         G_GUINT16_FORMAT, version);
8676     goto end;
8677   }
8678
8679 end:
8680   if (gamma) {
8681     *gamma = _gamma;
8682   }
8683   if (seqh) {
8684     *seqh = _seqh;
8685   } else if (_seqh) {
8686     gst_buffer_unref (_seqh);
8687   }
8688 }
8689
8690 static gchar *
8691 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8692 {
8693   GNode *dinf;
8694   GstByteReader dref;
8695   gchar *uri = NULL;
8696
8697   /*
8698    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8699    * atom that might contain a 'data' atom with the rtsp uri.
8700    * This case was reported in bug #597497, some info about
8701    * the hndl atom can be found in TN1195
8702    */
8703   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8704   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8705
8706   if (dinf) {
8707     guint32 dref_num_entries = 0;
8708     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8709         gst_byte_reader_skip (&dref, 4) &&
8710         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8711       gint i;
8712
8713       /* search dref entries for hndl atom */
8714       for (i = 0; i < dref_num_entries; i++) {
8715         guint32 size = 0, type;
8716         guint8 string_len = 0;
8717         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8718             qt_atom_parser_get_fourcc (&dref, &type)) {
8719           if (type == FOURCC_hndl) {
8720             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8721
8722             /* skip data reference handle bytes and the
8723              * following pascal string and some extra 4
8724              * bytes I have no idea what are */
8725             if (!gst_byte_reader_skip (&dref, 4) ||
8726                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8727                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8728               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8729               break;
8730             }
8731
8732             /* iterate over the atoms to find the data atom */
8733             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8734               guint32 atom_size;
8735               guint32 atom_type;
8736
8737               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8738                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8739                 if (atom_type == FOURCC_data) {
8740                   const guint8 *uri_aux = NULL;
8741
8742                   /* found the data atom that might contain the rtsp uri */
8743                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8744                       "hndl atom, interpreting it as an URI");
8745                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8746                           &uri_aux)) {
8747                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8748                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8749                     else
8750                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8751                           "didn't contain a rtsp address");
8752                   } else {
8753                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8754                         "atom contents");
8755                   }
8756                   break;
8757                 }
8758                 /* skipping to the next entry */
8759                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8760                   break;
8761               } else {
8762                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8763                     "atom header");
8764                 break;
8765               }
8766             }
8767             break;
8768           }
8769           /* skip to the next entry */
8770           if (!gst_byte_reader_skip (&dref, size - 8))
8771             break;
8772         } else {
8773           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8774         }
8775       }
8776       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8777     }
8778   }
8779   return uri;
8780 }
8781
8782 #define AMR_NB_ALL_MODES        0x81ff
8783 #define AMR_WB_ALL_MODES        0x83ff
8784 static guint
8785 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8786 {
8787   /* The 'damr' atom is of the form:
8788    *
8789    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8790    *    32 b       8 b          16 b           8 b                 8 b
8791    *
8792    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8793    * represents the highest mode used in the stream (and thus the maximum
8794    * bitrate), with a couple of special cases as seen below.
8795    */
8796
8797   /* Map of frame type ID -> bitrate */
8798   static const guint nb_bitrates[] = {
8799     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8800   };
8801   static const guint wb_bitrates[] = {
8802     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8803   };
8804   GstMapInfo map;
8805   gsize max_mode;
8806   guint16 mode_set;
8807
8808   gst_buffer_map (buf, &map, GST_MAP_READ);
8809
8810   if (map.size != 0x11) {
8811     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8812     goto bad_data;
8813   }
8814
8815   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8816     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8817         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8818     goto bad_data;
8819   }
8820
8821   mode_set = QT_UINT16 (map.data + 13);
8822
8823   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8824     max_mode = 7 + (wb ? 1 : 0);
8825   else
8826     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8827     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8828
8829   if (max_mode == -1) {
8830     GST_DEBUG ("No mode indication was found (mode set) = %x",
8831         (guint) mode_set);
8832     goto bad_data;
8833   }
8834
8835   gst_buffer_unmap (buf, &map);
8836   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8837
8838 bad_data:
8839   gst_buffer_unmap (buf, &map);
8840   return 0;
8841 }
8842
8843 static gboolean
8844 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8845     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8846 {
8847   /*
8848    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8849    * [0 1 2]
8850    * [3 4 5]
8851    * [6 7 8]
8852    */
8853
8854   if (gst_byte_reader_get_remaining (reader) < 36)
8855     return FALSE;
8856
8857   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8858   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8859   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8860   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8861   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8862   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8863   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8864   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8865   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8866
8867   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8868   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8869       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8870       matrix[2] & 0xFF);
8871   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8872       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8873       matrix[5] & 0xFF);
8874   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8875       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8876       matrix[8] & 0xFF);
8877
8878   return TRUE;
8879 }
8880
8881 static void
8882 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8883     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8884 {
8885
8886 /* [a b c]
8887  * [d e f]
8888  * [g h i]
8889  *
8890  * This macro will only compare value abdegh, it expects cfi to have already
8891  * been checked
8892  */
8893 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8894                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8895
8896   /* only handle the cases where the last column has standard values */
8897   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8898     const gchar *rotation_tag = NULL;
8899
8900     /* no rotation needed */
8901     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8902       /* NOP */
8903     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8904       rotation_tag = "rotate-90";
8905     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8906       rotation_tag = "rotate-180";
8907     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8908       rotation_tag = "rotate-270";
8909     } else {
8910       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8911     }
8912
8913     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8914         rotation_tag);
8915     if (rotation_tag != NULL) {
8916       if (*taglist == NULL)
8917         *taglist = gst_tag_list_new_empty ();
8918       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8919           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8920     }
8921   } else {
8922     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8923   }
8924 }
8925
8926 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8927  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8928  * Common Encryption (cenc), the function will also parse the tenc box (defined
8929  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8930  * (typically an enc[v|a|t|s] sample entry); the function will set
8931  * @original_fmt to the fourcc of the original unencrypted stream format.
8932  * Returns TRUE if successful; FALSE otherwise. */
8933 static gboolean
8934 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8935     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8936 {
8937   GNode *sinf;
8938   GNode *frma;
8939   GNode *schm;
8940   GNode *schi;
8941
8942   g_return_val_if_fail (qtdemux != NULL, FALSE);
8943   g_return_val_if_fail (stream != NULL, FALSE);
8944   g_return_val_if_fail (container != NULL, FALSE);
8945   g_return_val_if_fail (original_fmt != NULL, FALSE);
8946
8947   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8948   if (G_UNLIKELY (!sinf)) {
8949     if (stream->protection_scheme_type == FOURCC_cenc) {
8950       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8951           "mandatory for Common Encryption");
8952       return FALSE;
8953     }
8954     return TRUE;
8955   }
8956
8957   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8958   if (G_UNLIKELY (!frma)) {
8959     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8960     return FALSE;
8961   }
8962
8963   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8964   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8965       GST_FOURCC_ARGS (*original_fmt));
8966
8967   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8968   if (!schm) {
8969     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8970     return FALSE;
8971   }
8972   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
8973   stream->protection_scheme_version =
8974       QT_UINT32 ((const guint8 *) schm->data + 16);
8975
8976   GST_DEBUG_OBJECT (qtdemux,
8977       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
8978       "protection_scheme_version: %#010x",
8979       GST_FOURCC_ARGS (stream->protection_scheme_type),
8980       stream->protection_scheme_version);
8981
8982   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
8983   if (!schi) {
8984     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
8985     return FALSE;
8986   }
8987   if (stream->protection_scheme_type == FOURCC_cenc) {
8988     QtDemuxCencSampleSetInfo *info;
8989     GNode *tenc;
8990     const guint8 *tenc_data;
8991     guint32 isEncrypted;
8992     guint8 iv_size;
8993     const guint8 *default_kid;
8994     GstBuffer *kid_buf;
8995
8996     if (G_UNLIKELY (!stream->protection_scheme_info))
8997       stream->protection_scheme_info =
8998           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
8999
9000     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9001
9002     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9003     if (!tenc) {
9004       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9005           "which is mandatory for Common Encryption");
9006       return FALSE;
9007     }
9008     tenc_data = (const guint8 *) tenc->data + 12;
9009     isEncrypted = QT_UINT24 (tenc_data);
9010     iv_size = QT_UINT8 (tenc_data + 3);
9011     default_kid = (tenc_data + 4);
9012     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9013     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9014     if (info->default_properties)
9015       gst_structure_free (info->default_properties);
9016     info->default_properties =
9017         gst_structure_new ("application/x-cenc",
9018         "iv_size", G_TYPE_UINT, iv_size,
9019         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9020         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9021     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9022         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9023     gst_buffer_unref (kid_buf);
9024   }
9025   return TRUE;
9026 }
9027
9028 /* parse the traks.
9029  * With each track we associate a new QtDemuxStream that contains all the info
9030  * about the trak.
9031  * traks that do not decode to something (like strm traks) will not have a pad.
9032  */
9033 static gboolean
9034 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9035 {
9036   GstByteReader tkhd;
9037   int offset;
9038   GNode *mdia;
9039   GNode *mdhd;
9040   GNode *hdlr;
9041   GNode *minf;
9042   GNode *stbl;
9043   GNode *stsd;
9044   GNode *mp4a;
9045   GNode *mp4v;
9046   GNode *wave;
9047   GNode *esds;
9048   GNode *pasp;
9049   GNode *tref;
9050   GNode *udta;
9051   GNode *svmi;
9052
9053   QtDemuxStream *stream = NULL;
9054   gboolean new_stream = FALSE;
9055   gchar *codec = NULL;
9056   const guint8 *stsd_data;
9057   guint16 lang_code;            /* quicktime lang code or packed iso code */
9058   guint32 version;
9059   guint32 tkhd_flags = 0;
9060   guint8 tkhd_version = 0;
9061   guint32 fourcc;
9062   guint value_size, stsd_len, len;
9063   guint32 track_id;
9064   guint32 dummy;
9065
9066   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9067
9068   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9069       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9070       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9071     goto corrupt_file;
9072
9073   /* pick between 64 or 32 bits */
9074   value_size = tkhd_version == 1 ? 8 : 4;
9075   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9076       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9077     goto corrupt_file;
9078
9079   if (!qtdemux->got_moov) {
9080     if (qtdemux_find_stream (qtdemux, track_id))
9081       goto existing_stream;
9082     stream = _create_stream ();
9083     stream->track_id = track_id;
9084     new_stream = TRUE;
9085   } else {
9086     stream = qtdemux_find_stream (qtdemux, track_id);
9087     if (!stream) {
9088       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9089       goto skip_track;
9090     }
9091
9092     /* flush samples data from this track from previous moov */
9093     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9094     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9095   }
9096   /* need defaults for fragments */
9097   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9098
9099   if (stream->pending_tags == NULL)
9100     stream->pending_tags = gst_tag_list_new_empty ();
9101
9102   if ((tkhd_flags & 1) == 0)
9103     stream->disabled = TRUE;
9104
9105   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9106       tkhd_version, tkhd_flags, stream->track_id);
9107
9108   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9109     goto corrupt_file;
9110
9111   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9112     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9113     if (qtdemux->major_brand != FOURCC_mjp2 ||
9114         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9115       goto corrupt_file;
9116   }
9117
9118   len = QT_UINT32 ((guint8 *) mdhd->data);
9119   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9120   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9121   if (version == 0x01000000) {
9122     if (len < 38)
9123       goto corrupt_file;
9124     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9125     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9126     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9127   } else {
9128     if (len < 30)
9129       goto corrupt_file;
9130     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9131     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9132     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9133   }
9134
9135   if (lang_code < 0x400) {
9136     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9137   } else if (lang_code == 0x7fff) {
9138     stream->lang_id[0] = 0;     /* unspecified */
9139   } else {
9140     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9141     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9142     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9143     stream->lang_id[3] = 0;
9144   }
9145
9146   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9147       stream->timescale);
9148   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9149       stream->duration);
9150   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9151       lang_code, stream->lang_id);
9152
9153   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9154     goto corrupt_file;
9155
9156   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9157     /* chapters track reference */
9158     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9159     if (chap) {
9160       gsize length = GST_READ_UINT32_BE (chap->data);
9161       if (qtdemux->chapters_track_id)
9162         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9163
9164       if (length >= 12) {
9165         qtdemux->chapters_track_id =
9166             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9167       }
9168     }
9169   }
9170
9171   /* fragmented files may have bogus duration in moov */
9172   if (!qtdemux->fragmented &&
9173       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9174     guint64 tdur1, tdur2;
9175
9176     /* don't overflow */
9177     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9178     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9179
9180     /* HACK:
9181      * some of those trailers, nowadays, have prologue images that are
9182      * themselves vide tracks as well. I haven't really found a way to
9183      * identify those yet, except for just looking at their duration. */
9184     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9185       GST_WARNING_OBJECT (qtdemux,
9186           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9187           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9188           "found, assuming preview image or something; skipping track",
9189           stream->duration, stream->timescale, qtdemux->duration,
9190           qtdemux->timescale);
9191       if (new_stream)
9192         gst_qtdemux_stream_free (qtdemux, stream);
9193       return TRUE;
9194     }
9195   }
9196
9197   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9198     goto corrupt_file;
9199
9200   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9201       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9202
9203   len = QT_UINT32 ((guint8 *) hdlr->data);
9204   if (len >= 20)
9205     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9206   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9207       GST_FOURCC_ARGS (stream->subtype));
9208
9209   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9210     goto corrupt_file;
9211
9212   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9213     goto corrupt_file;
9214
9215   /*parse svmi header if existing */
9216   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9217   if (svmi) {
9218     len = QT_UINT32 ((guint8 *) svmi->data);
9219     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9220     if (!version) {
9221       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9222       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9223       guint8 frame_type, frame_layout;
9224
9225       /* MPEG-A stereo video */
9226       if (qtdemux->major_brand == FOURCC_ss02)
9227         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9228
9229       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9230       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9231       switch (frame_type) {
9232         case 0:
9233           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9234           break;
9235         case 1:
9236           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9237           break;
9238         case 2:
9239           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9240           break;
9241         case 3:
9242           /* mode 3 is primary/secondary view sequence, ie
9243            * left/right views in separate tracks. See section 7.2
9244            * of ISO/IEC 23000-11:2009 */
9245           GST_FIXME_OBJECT (qtdemux,
9246               "Implement stereo video in separate streams");
9247       }
9248
9249       if ((frame_layout & 0x1) == 0)
9250         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9251
9252       GST_LOG_OBJECT (qtdemux,
9253           "StereoVideo: composition type: %u, is_left_first: %u",
9254           frame_type, frame_layout);
9255       stream->multiview_mode = mode;
9256       stream->multiview_flags = flags;
9257     }
9258   }
9259
9260   /* parse stsd */
9261   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9262     goto corrupt_file;
9263   stsd_data = (const guint8 *) stsd->data;
9264
9265   /* stsd should at least have one entry */
9266   stsd_len = QT_UINT32 (stsd_data);
9267   if (stsd_len < 24) {
9268     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9269     if (stream->subtype == FOURCC_vivo) {
9270       if (new_stream)
9271         gst_qtdemux_stream_free (qtdemux, stream);
9272       return TRUE;
9273     } else {
9274       goto corrupt_file;
9275     }
9276   }
9277
9278   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9279
9280   /* and that entry should fit within stsd */
9281   len = QT_UINT32 (stsd_data + 16);
9282   if (len > stsd_len + 16)
9283     goto corrupt_file;
9284
9285   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9286   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9287       GST_FOURCC_ARGS (stream->fourcc));
9288   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9289
9290   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9291     goto error_encrypted;
9292
9293   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9294     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9295     stream->protected = TRUE;
9296     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9297       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9298   }
9299
9300   if (stream->subtype == FOURCC_vide) {
9301     guint32 w = 0, h = 0;
9302     gboolean gray;
9303     gint depth, palette_size, palette_count;
9304     guint32 matrix[9];
9305     guint32 *palette_data = NULL;
9306
9307     stream->sampled = TRUE;
9308
9309     /* version 1 uses some 64-bit ints */
9310     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9311       goto corrupt_file;
9312
9313     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9314       goto corrupt_file;
9315
9316     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9317         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9318       goto corrupt_file;
9319
9320     stream->display_width = w >> 16;
9321     stream->display_height = h >> 16;
9322
9323     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9324         &stream->pending_tags);
9325
9326     offset = 16;
9327     if (len < 86)
9328       goto corrupt_file;
9329
9330     stream->width = QT_UINT16 (stsd_data + offset + 32);
9331     stream->height = QT_UINT16 (stsd_data + offset + 34);
9332     stream->fps_n = 0;          /* this is filled in later */
9333     stream->fps_d = 0;          /* this is filled in later */
9334     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9335     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9336
9337     /* if color_table_id is 0, ctab atom must follow; however some files
9338      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9339      * if color table is not present we'll correct the value */
9340     if (stream->color_table_id == 0 &&
9341         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9342       stream->color_table_id = -1;
9343     }
9344
9345     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9346         stream->width, stream->height, stream->bits_per_sample,
9347         stream->color_table_id);
9348
9349     depth = stream->bits_per_sample;
9350
9351     /* more than 32 bits means grayscale */
9352     gray = (depth > 32);
9353     /* low 32 bits specify the depth  */
9354     depth &= 0x1F;
9355
9356     /* different number of palette entries is determined by depth. */
9357     palette_count = 0;
9358     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9359       palette_count = (1 << depth);
9360     palette_size = palette_count * 4;
9361
9362     if (stream->color_table_id) {
9363       switch (palette_count) {
9364         case 0:
9365           break;
9366         case 2:
9367           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9368           break;
9369         case 4:
9370           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9371           break;
9372         case 16:
9373           if (gray)
9374             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9375           else
9376             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9377           break;
9378         case 256:
9379           if (gray)
9380             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9381           else
9382             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9383           break;
9384         default:
9385           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9386               (_("The video in this file might not play correctly.")),
9387               ("unsupported palette depth %d", depth));
9388           break;
9389       }
9390     } else {
9391       gint i, j, start, end;
9392
9393       if (len < 94)
9394         goto corrupt_file;
9395
9396       /* read table */
9397       start = QT_UINT32 (stsd_data + offset + 86);
9398       palette_count = QT_UINT16 (stsd_data + offset + 90);
9399       end = QT_UINT16 (stsd_data + offset + 92);
9400
9401       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9402           start, end, palette_count);
9403
9404       if (end > 255)
9405         end = 255;
9406       if (start > end)
9407         start = end;
9408
9409       if (len < 94 + (end - start) * 8)
9410         goto corrupt_file;
9411
9412       /* palette is always the same size */
9413       palette_data = g_malloc0 (256 * 4);
9414       palette_size = 256 * 4;
9415
9416       for (j = 0, i = start; i <= end; j++, i++) {
9417         guint32 a, r, g, b;
9418
9419         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9420         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9421         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9422         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9423
9424         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9425             (g & 0xff00) | (b >> 8);
9426       }
9427     }
9428
9429     if (stream->caps)
9430       gst_caps_unref (stream->caps);
9431
9432     stream->caps =
9433         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9434     if (G_UNLIKELY (!stream->caps)) {
9435       g_free (palette_data);
9436       goto unknown_stream;
9437     }
9438
9439     if (codec) {
9440       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9441           GST_TAG_VIDEO_CODEC, codec, NULL);
9442       g_free (codec);
9443       codec = NULL;
9444     }
9445
9446
9447     if (palette_data) {
9448       GstStructure *s;
9449
9450       if (stream->rgb8_palette)
9451         gst_memory_unref (stream->rgb8_palette);
9452       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9453           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9454
9455       s = gst_caps_get_structure (stream->caps, 0);
9456
9457       /* non-raw video has a palette_data property. raw video has the palette as
9458        * an extra plane that we append to the output buffers before we push
9459        * them*/
9460       if (!gst_structure_has_name (s, "video/x-raw")) {
9461         GstBuffer *palette;
9462
9463         palette = gst_buffer_new ();
9464         gst_buffer_append_memory (palette, stream->rgb8_palette);
9465         stream->rgb8_palette = NULL;
9466
9467         gst_caps_set_simple (stream->caps, "palette_data",
9468             GST_TYPE_BUFFER, palette, NULL);
9469         gst_buffer_unref (palette);
9470       }
9471     } else if (palette_count != 0) {
9472       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9473           (NULL), ("Unsupported palette depth %d", depth));
9474     }
9475
9476     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9477         QT_UINT16 (stsd_data + offset + 48));
9478
9479     esds = NULL;
9480     pasp = NULL;
9481     /* pick 'the' stsd child */
9482     if (!stream->protected)
9483       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9484     else
9485       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9486
9487     if (mp4v) {
9488       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9489       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9490     }
9491
9492     if (pasp) {
9493       const guint8 *pasp_data = (const guint8 *) pasp->data;
9494
9495       stream->par_w = QT_UINT32 (pasp_data + 8);
9496       stream->par_h = QT_UINT32 (pasp_data + 12);
9497     } else {
9498       stream->par_w = 0;
9499       stream->par_h = 0;
9500     }
9501
9502     if (esds) {
9503       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9504     } else {
9505       switch (fourcc) {
9506         case FOURCC_H264:
9507         case FOURCC_avc1:
9508         case FOURCC_avc3:
9509         {
9510           gint len = QT_UINT32 (stsd_data) - 0x66;
9511           const guint8 *avc_data = stsd_data + 0x66;
9512
9513           /* find avcC */
9514           while (len >= 0x8) {
9515             gint size;
9516
9517             if (QT_UINT32 (avc_data) <= len)
9518               size = QT_UINT32 (avc_data) - 0x8;
9519             else
9520               size = len - 0x8;
9521
9522             if (size < 1)
9523               /* No real data, so break out */
9524               break;
9525
9526             switch (QT_FOURCC (avc_data + 0x4)) {
9527               case FOURCC_avcC:
9528               {
9529                 /* parse, if found */
9530                 GstBuffer *buf;
9531
9532                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9533
9534                 /* First 4 bytes are the length of the atom, the next 4 bytes
9535                  * are the fourcc, the next 1 byte is the version, and the
9536                  * subsequent bytes are profile_tier_level structure like data. */
9537                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9538                     avc_data + 8 + 1, size - 1);
9539                 buf = gst_buffer_new_and_alloc (size);
9540                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9541                 gst_caps_set_simple (stream->caps,
9542                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9543                 gst_buffer_unref (buf);
9544
9545                 break;
9546               }
9547               case FOURCC_strf:
9548               {
9549                 GstBuffer *buf;
9550
9551                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9552
9553                 /* First 4 bytes are the length of the atom, the next 4 bytes
9554                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9555                  * next 1 byte is the version, and the
9556                  * subsequent bytes are sequence parameter set like data. */
9557
9558                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9559                 if (size > 1) {
9560                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9561                       avc_data + 8 + 40 + 1, size - 1);
9562
9563                   buf = gst_buffer_new_and_alloc (size);
9564                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9565                   gst_caps_set_simple (stream->caps,
9566                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9567                   gst_buffer_unref (buf);
9568                 }
9569                 break;
9570               }
9571               case FOURCC_btrt:
9572               {
9573                 guint avg_bitrate, max_bitrate;
9574
9575                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9576                 if (size < 12)
9577                   break;
9578
9579                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9580                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9581
9582                 if (!max_bitrate && !avg_bitrate)
9583                   break;
9584
9585                 /* Some muxers seem to swap the average and maximum bitrates
9586                  * (I'm looking at you, YouTube), so we swap for sanity. */
9587                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9588                   guint temp = avg_bitrate;
9589
9590                   avg_bitrate = max_bitrate;
9591                   max_bitrate = temp;
9592                 }
9593
9594                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9595                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9596                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9597                 }
9598                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9599                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9600                       GST_TAG_BITRATE, avg_bitrate, NULL);
9601                 }
9602
9603                 break;
9604               }
9605
9606               default:
9607                 break;
9608             }
9609
9610             len -= size + 8;
9611             avc_data += size + 8;
9612           }
9613
9614           break;
9615         }
9616         case FOURCC_H265:
9617         case FOURCC_hvc1:
9618         case FOURCC_hev1:
9619         {
9620           gint len = QT_UINT32 (stsd_data) - 0x66;
9621           const guint8 *hevc_data = stsd_data + 0x66;
9622
9623           /* find hevc */
9624           while (len >= 0x8) {
9625             gint size;
9626
9627             if (QT_UINT32 (hevc_data) <= len)
9628               size = QT_UINT32 (hevc_data) - 0x8;
9629             else
9630               size = len - 0x8;
9631
9632             if (size < 1)
9633               /* No real data, so break out */
9634               break;
9635
9636             switch (QT_FOURCC (hevc_data + 0x4)) {
9637               case FOURCC_hvcC:
9638               {
9639                 /* parse, if found */
9640                 GstBuffer *buf;
9641
9642                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9643
9644                 /* First 4 bytes are the length of the atom, the next 4 bytes
9645                  * are the fourcc, the next 1 byte is the version, and the
9646                  * subsequent bytes are sequence parameter set like data. */
9647                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9648                     (stream->caps, hevc_data + 8 + 1, size - 1);
9649
9650                 buf = gst_buffer_new_and_alloc (size);
9651                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9652                 gst_caps_set_simple (stream->caps,
9653                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9654                 gst_buffer_unref (buf);
9655                 break;
9656               }
9657               default:
9658                 break;
9659             }
9660             len -= size + 8;
9661             hevc_data += size + 8;
9662           }
9663           break;
9664         }
9665         case FOURCC_mp4v:
9666         case FOURCC_MP4V:
9667         case FOURCC_fmp4:
9668         case FOURCC_FMP4:
9669         {
9670           GNode *glbl;
9671
9672           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9673               GST_FOURCC_ARGS (fourcc));
9674
9675           /* codec data might be in glbl extension atom */
9676           glbl = mp4v ?
9677               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9678           if (glbl) {
9679             guint8 *data;
9680             GstBuffer *buf;
9681             gint len;
9682
9683             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9684             data = glbl->data;
9685             len = QT_UINT32 (data);
9686             if (len > 0x8) {
9687               len -= 0x8;
9688               buf = gst_buffer_new_and_alloc (len);
9689               gst_buffer_fill (buf, 0, data + 8, len);
9690               gst_caps_set_simple (stream->caps,
9691                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9692               gst_buffer_unref (buf);
9693             }
9694           }
9695           break;
9696         }
9697         case FOURCC_mjp2:
9698         {
9699           /* see annex I of the jpeg2000 spec */
9700           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9701           const guint8 *data;
9702           const gchar *colorspace = NULL;
9703           gint ncomp = 0;
9704           guint32 ncomp_map = 0;
9705           gint32 *comp_map = NULL;
9706           guint32 nchan_def = 0;
9707           gint32 *chan_def = NULL;
9708
9709           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9710           /* some required atoms */
9711           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9712           if (!mjp2)
9713             break;
9714           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9715           if (!jp2h)
9716             break;
9717
9718           /* number of components; redundant with info in codestream, but useful
9719              to a muxer */
9720           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9721           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9722             break;
9723           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9724
9725           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9726           if (!colr)
9727             break;
9728           GST_DEBUG_OBJECT (qtdemux, "found colr");
9729           /* extract colour space info */
9730           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9731             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9732               case 16:
9733                 colorspace = "sRGB";
9734                 break;
9735               case 17:
9736                 colorspace = "GRAY";
9737                 break;
9738               case 18:
9739                 colorspace = "sYUV";
9740                 break;
9741               default:
9742                 colorspace = NULL;
9743                 break;
9744             }
9745           }
9746           if (!colorspace)
9747             /* colr is required, and only values 16, 17, and 18 are specified,
9748                so error if we have no colorspace */
9749             break;
9750
9751           /* extract component mapping */
9752           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9753           if (cmap) {
9754             guint32 cmap_len = 0;
9755             int i;
9756             cmap_len = QT_UINT32 (cmap->data);
9757             if (cmap_len >= 8) {
9758               /* normal box, subtract off header */
9759               cmap_len -= 8;
9760               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9761               if (cmap_len % 4 == 0) {
9762                 ncomp_map = (cmap_len / 4);
9763                 comp_map = g_new0 (gint32, ncomp_map);
9764                 for (i = 0; i < ncomp_map; i++) {
9765                   guint16 cmp;
9766                   guint8 mtyp, pcol;
9767                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9768                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9769                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9770                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9771                 }
9772               }
9773             }
9774           }
9775           /* extract channel definitions */
9776           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9777           if (cdef) {
9778             guint32 cdef_len = 0;
9779             int i;
9780             cdef_len = QT_UINT32 (cdef->data);
9781             if (cdef_len >= 10) {
9782               /* normal box, subtract off header and len */
9783               cdef_len -= 10;
9784               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9785               if (cdef_len % 6 == 0) {
9786                 nchan_def = (cdef_len / 6);
9787                 chan_def = g_new0 (gint32, nchan_def);
9788                 for (i = 0; i < nchan_def; i++)
9789                   chan_def[i] = -1;
9790                 for (i = 0; i < nchan_def; i++) {
9791                   guint16 cn, typ, asoc;
9792                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9793                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9794                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9795                   if (cn < nchan_def) {
9796                     switch (typ) {
9797                       case 0:
9798                         chan_def[cn] = asoc;
9799                         break;
9800                       case 1:
9801                         chan_def[cn] = 0;       /* alpha */
9802                         break;
9803                       default:
9804                         chan_def[cn] = -typ;
9805                     }
9806                   }
9807                 }
9808               }
9809             }
9810           }
9811
9812           gst_caps_set_simple (stream->caps,
9813               "num-components", G_TYPE_INT, ncomp, NULL);
9814           gst_caps_set_simple (stream->caps,
9815               "colorspace", G_TYPE_STRING, colorspace, NULL);
9816
9817           if (comp_map) {
9818             GValue arr = { 0, };
9819             GValue elt = { 0, };
9820             int i;
9821             g_value_init (&arr, GST_TYPE_ARRAY);
9822             g_value_init (&elt, G_TYPE_INT);
9823             for (i = 0; i < ncomp_map; i++) {
9824               g_value_set_int (&elt, comp_map[i]);
9825               gst_value_array_append_value (&arr, &elt);
9826             }
9827             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9828                 "component-map", &arr);
9829             g_value_unset (&elt);
9830             g_value_unset (&arr);
9831             g_free (comp_map);
9832           }
9833
9834           if (chan_def) {
9835             GValue arr = { 0, };
9836             GValue elt = { 0, };
9837             int i;
9838             g_value_init (&arr, GST_TYPE_ARRAY);
9839             g_value_init (&elt, G_TYPE_INT);
9840             for (i = 0; i < nchan_def; i++) {
9841               g_value_set_int (&elt, chan_def[i]);
9842               gst_value_array_append_value (&arr, &elt);
9843             }
9844             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9845                 "channel-definitions", &arr);
9846             g_value_unset (&elt);
9847             g_value_unset (&arr);
9848             g_free (chan_def);
9849           }
9850
9851           /* some optional atoms */
9852           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9853           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9854
9855           /* indicate possible fields in caps */
9856           if (field) {
9857             data = (guint8 *) field->data + 8;
9858             if (*data != 1)
9859               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9860                   (gint) * data, NULL);
9861           }
9862           /* add codec_data if provided */
9863           if (prefix) {
9864             GstBuffer *buf;
9865             gint len;
9866
9867             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9868             data = prefix->data;
9869             len = QT_UINT32 (data);
9870             if (len > 0x8) {
9871               len -= 0x8;
9872               buf = gst_buffer_new_and_alloc (len);
9873               gst_buffer_fill (buf, 0, data + 8, len);
9874               gst_caps_set_simple (stream->caps,
9875                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9876               gst_buffer_unref (buf);
9877             }
9878           }
9879           break;
9880         }
9881         case FOURCC_SVQ3:
9882         case FOURCC_VP31:
9883         {
9884           GstBuffer *buf;
9885           GstBuffer *seqh = NULL;
9886           guint8 *gamma_data = NULL;
9887           gint len = QT_UINT32 (stsd_data);
9888
9889           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9890           if (gamma_data) {
9891             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9892                 QT_FP32 (gamma_data), NULL);
9893           }
9894           if (seqh) {
9895             /* sorry for the bad name, but we don't know what this is, other
9896              * than its own fourcc */
9897             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9898                 NULL);
9899           }
9900
9901           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9902           buf = gst_buffer_new_and_alloc (len);
9903           gst_buffer_fill (buf, 0, stsd_data, len);
9904           gst_caps_set_simple (stream->caps,
9905               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9906           gst_buffer_unref (buf);
9907           break;
9908         }
9909         case FOURCC_rle_:
9910         case FOURCC_WRLE:
9911         {
9912           gst_caps_set_simple (stream->caps,
9913               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9914           break;
9915         }
9916         case FOURCC_XiTh:
9917         {
9918           GNode *xith, *xdxt;
9919
9920           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9921           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9922           if (!xith)
9923             break;
9924
9925           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9926           if (!xdxt)
9927             break;
9928
9929           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9930           /* collect the headers and store them in a stream list so that we can
9931            * send them out first */
9932           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9933           break;
9934         }
9935         case FOURCC_ovc1:
9936         {
9937           GNode *ovc1;
9938           guint8 *ovc1_data;
9939           guint ovc1_len;
9940           GstBuffer *buf;
9941
9942           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9943           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9944           if (!ovc1)
9945             break;
9946           ovc1_data = ovc1->data;
9947           ovc1_len = QT_UINT32 (ovc1_data);
9948           if (ovc1_len <= 198) {
9949             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9950             break;
9951           }
9952           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9953           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9954           gst_caps_set_simple (stream->caps,
9955               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9956           gst_buffer_unref (buf);
9957           break;
9958         }
9959         case FOURCC_vc_1:
9960         {
9961           gint len = QT_UINT32 (stsd_data) - 0x66;
9962           const guint8 *vc1_data = stsd_data + 0x66;
9963
9964           /* find dvc1 */
9965           while (len >= 8) {
9966             gint size;
9967
9968             if (QT_UINT32 (vc1_data) <= len)
9969               size = QT_UINT32 (vc1_data) - 8;
9970             else
9971               size = len - 8;
9972
9973             if (size < 1)
9974               /* No real data, so break out */
9975               break;
9976
9977             switch (QT_FOURCC (vc1_data + 0x4)) {
9978               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
9979               {
9980                 GstBuffer *buf;
9981
9982                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
9983                 buf = gst_buffer_new_and_alloc (size);
9984                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
9985                 gst_caps_set_simple (stream->caps,
9986                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9987                 gst_buffer_unref (buf);
9988                 break;
9989               }
9990               default:
9991                 break;
9992             }
9993             len -= size + 8;
9994             vc1_data += size + 8;
9995           }
9996           break;
9997         }
9998         default:
9999           break;
10000       }
10001     }
10002
10003     GST_INFO_OBJECT (qtdemux,
10004         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10005         GST_FOURCC_ARGS (fourcc), stream->caps);
10006
10007   } else if (stream->subtype == FOURCC_soun) {
10008     int version, samplesize;
10009     guint16 compression_id;
10010     gboolean amrwb = FALSE;
10011
10012     offset = 32;
10013     /* sample description entry (16) + sound sample description v0 (20) */
10014     if (len < 36)
10015       goto corrupt_file;
10016
10017     version = QT_UINT32 (stsd_data + offset);
10018     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10019     samplesize = QT_UINT16 (stsd_data + offset + 10);
10020     compression_id = QT_UINT16 (stsd_data + offset + 12);
10021     stream->rate = QT_FP32 (stsd_data + offset + 16);
10022
10023     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10024     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10025         QT_UINT32 (stsd_data + offset + 4));
10026     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10027     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10028     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10029     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10030         QT_UINT16 (stsd_data + offset + 14));
10031     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10032
10033     if (compression_id == 0xfffe)
10034       stream->sampled = TRUE;
10035
10036     /* first assume uncompressed audio */
10037     stream->bytes_per_sample = samplesize / 8;
10038     stream->samples_per_frame = stream->n_channels;
10039     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10040     stream->samples_per_packet = stream->samples_per_frame;
10041     stream->bytes_per_packet = stream->bytes_per_sample;
10042
10043     offset = 52;
10044     switch (fourcc) {
10045         /* Yes, these have to be hard-coded */
10046       case FOURCC_MAC6:
10047       {
10048         stream->samples_per_packet = 6;
10049         stream->bytes_per_packet = 1;
10050         stream->bytes_per_frame = 1 * stream->n_channels;
10051         stream->bytes_per_sample = 1;
10052         stream->samples_per_frame = 6 * stream->n_channels;
10053         break;
10054       }
10055       case FOURCC_MAC3:
10056       {
10057         stream->samples_per_packet = 3;
10058         stream->bytes_per_packet = 1;
10059         stream->bytes_per_frame = 1 * stream->n_channels;
10060         stream->bytes_per_sample = 1;
10061         stream->samples_per_frame = 3 * stream->n_channels;
10062         break;
10063       }
10064       case FOURCC_ima4:
10065       {
10066         stream->samples_per_packet = 64;
10067         stream->bytes_per_packet = 34;
10068         stream->bytes_per_frame = 34 * stream->n_channels;
10069         stream->bytes_per_sample = 2;
10070         stream->samples_per_frame = 64 * stream->n_channels;
10071         break;
10072       }
10073       case FOURCC_ulaw:
10074       case FOURCC_alaw:
10075       {
10076         stream->samples_per_packet = 1;
10077         stream->bytes_per_packet = 1;
10078         stream->bytes_per_frame = 1 * stream->n_channels;
10079         stream->bytes_per_sample = 1;
10080         stream->samples_per_frame = 1 * stream->n_channels;
10081         break;
10082       }
10083       case FOURCC_agsm:
10084       {
10085         stream->samples_per_packet = 160;
10086         stream->bytes_per_packet = 33;
10087         stream->bytes_per_frame = 33 * stream->n_channels;
10088         stream->bytes_per_sample = 2;
10089         stream->samples_per_frame = 160 * stream->n_channels;
10090         break;
10091       }
10092       default:
10093         break;
10094     }
10095
10096     if (version == 0x00010000) {
10097       /* sample description entry (16) + sound sample description v1 (20+16) */
10098       if (len < 52)
10099         goto corrupt_file;
10100
10101       switch (fourcc) {
10102         case FOURCC_twos:
10103         case FOURCC_sowt:
10104         case FOURCC_raw_:
10105           break;
10106         default:
10107         {
10108           /* only parse extra decoding config for non-pcm audio */
10109           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10110           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10111           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10112           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10113
10114           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10115               stream->samples_per_packet);
10116           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10117               stream->bytes_per_packet);
10118           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10119               stream->bytes_per_frame);
10120           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10121               stream->bytes_per_sample);
10122
10123           if (!stream->sampled && stream->bytes_per_packet) {
10124             stream->samples_per_frame = (stream->bytes_per_frame /
10125                 stream->bytes_per_packet) * stream->samples_per_packet;
10126             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10127                 stream->samples_per_frame);
10128           }
10129           break;
10130         }
10131       }
10132     } else if (version == 0x00020000) {
10133       union
10134       {
10135         gdouble fp;
10136         guint64 val;
10137       } qtfp;
10138
10139       /* sample description entry (16) + sound sample description v2 (56) */
10140       if (len < 72)
10141         goto corrupt_file;
10142
10143       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10144       stream->rate = qtfp.fp;
10145       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10146
10147       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10148       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10149       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10150       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10151           QT_UINT32 (stsd_data + offset + 20));
10152       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10153           QT_UINT32 (stsd_data + offset + 24));
10154       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10155           QT_UINT32 (stsd_data + offset + 28));
10156       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10157           QT_UINT32 (stsd_data + offset + 32));
10158     } else if (version != 0x00000) {
10159       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10160     }
10161
10162     if (stream->caps)
10163       gst_caps_unref (stream->caps);
10164
10165     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10166         stsd_data + 32, len - 16, &codec);
10167
10168     switch (fourcc) {
10169       case FOURCC_in24:
10170       {
10171         GNode *enda;
10172         GNode *in24;
10173
10174         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10175
10176         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10177         if (!enda) {
10178           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10179           if (wave)
10180             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10181         }
10182         if (enda) {
10183           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10184           gst_caps_set_simple (stream->caps,
10185               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10186         }
10187         break;
10188       }
10189       case FOURCC_owma:
10190       {
10191         GNode *owma;
10192         const guint8 *owma_data;
10193         const gchar *codec_name = NULL;
10194         guint owma_len;
10195         GstBuffer *buf;
10196         gint version = 1;
10197         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10198         /* FIXME this should also be gst_riff_strf_auds,
10199          * but the latter one is actually missing bits-per-sample :( */
10200         typedef struct
10201         {
10202           gint16 wFormatTag;
10203           gint16 nChannels;
10204           gint32 nSamplesPerSec;
10205           gint32 nAvgBytesPerSec;
10206           gint16 nBlockAlign;
10207           gint16 wBitsPerSample;
10208           gint16 cbSize;
10209         } WAVEFORMATEX;
10210         WAVEFORMATEX *wfex;
10211
10212         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10213         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10214         if (!owma)
10215           break;
10216         owma_data = owma->data;
10217         owma_len = QT_UINT32 (owma_data);
10218         if (owma_len <= 54) {
10219           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10220           break;
10221         }
10222         wfex = (WAVEFORMATEX *) (owma_data + 36);
10223         buf = gst_buffer_new_and_alloc (owma_len - 54);
10224         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10225         if (wfex->wFormatTag == 0x0161) {
10226           codec_name = "Windows Media Audio";
10227           version = 2;
10228         } else if (wfex->wFormatTag == 0x0162) {
10229           codec_name = "Windows Media Audio 9 Pro";
10230           version = 3;
10231         } else if (wfex->wFormatTag == 0x0163) {
10232           codec_name = "Windows Media Audio 9 Lossless";
10233           /* is that correct? gstffmpegcodecmap.c is missing it, but
10234            * fluendo codec seems to support it */
10235           version = 4;
10236         }
10237
10238         gst_caps_set_simple (stream->caps,
10239             "codec_data", GST_TYPE_BUFFER, buf,
10240             "wmaversion", G_TYPE_INT, version,
10241             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10242             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10243             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10244             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10245             NULL);
10246         gst_buffer_unref (buf);
10247
10248         if (codec_name) {
10249           g_free (codec);
10250           codec = g_strdup (codec_name);
10251         }
10252         break;
10253       }
10254       case FOURCC_wma_:
10255       {
10256         gint len = QT_UINT32 (stsd_data) - offset;
10257         const guint8 *wfex_data = stsd_data + offset;
10258         const gchar *codec_name = NULL;
10259         gint version = 1;
10260         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10261         /* FIXME this should also be gst_riff_strf_auds,
10262          * but the latter one is actually missing bits-per-sample :( */
10263         typedef struct
10264         {
10265           gint16 wFormatTag;
10266           gint16 nChannels;
10267           gint32 nSamplesPerSec;
10268           gint32 nAvgBytesPerSec;
10269           gint16 nBlockAlign;
10270           gint16 wBitsPerSample;
10271           gint16 cbSize;
10272         } WAVEFORMATEX;
10273         WAVEFORMATEX wfex;
10274
10275         /* FIXME: unify with similar wavformatex parsing code above */
10276         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10277
10278         /* find wfex */
10279         while (len >= 8) {
10280           gint size;
10281
10282           if (QT_UINT32 (wfex_data) <= len)
10283             size = QT_UINT32 (wfex_data) - 8;
10284           else
10285             size = len - 8;
10286
10287           if (size < 1)
10288             /* No real data, so break out */
10289             break;
10290
10291           switch (QT_FOURCC (wfex_data + 4)) {
10292             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10293             {
10294               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10295
10296               if (size < 8 + 18)
10297                 break;
10298
10299               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10300               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10301               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10302               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10303               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10304               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10305               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10306
10307               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10308               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10309                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10310                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10311                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10312                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10313
10314               if (wfex.wFormatTag == 0x0161) {
10315                 codec_name = "Windows Media Audio";
10316                 version = 2;
10317               } else if (wfex.wFormatTag == 0x0162) {
10318                 codec_name = "Windows Media Audio 9 Pro";
10319                 version = 3;
10320               } else if (wfex.wFormatTag == 0x0163) {
10321                 codec_name = "Windows Media Audio 9 Lossless";
10322                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10323                  * fluendo codec seems to support it */
10324                 version = 4;
10325               }
10326
10327               gst_caps_set_simple (stream->caps,
10328                   "wmaversion", G_TYPE_INT, version,
10329                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10330                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10331                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10332                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10333
10334               if (size > wfex.cbSize) {
10335                 GstBuffer *buf;
10336
10337                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10338                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10339                     size - wfex.cbSize);
10340                 gst_caps_set_simple (stream->caps,
10341                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10342                 gst_buffer_unref (buf);
10343               } else {
10344                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10345               }
10346
10347               if (codec_name) {
10348                 g_free (codec);
10349                 codec = g_strdup (codec_name);
10350               }
10351               break;
10352             }
10353             default:
10354               break;
10355           }
10356           len -= size + 8;
10357           wfex_data += size + 8;
10358         }
10359         break;
10360       }
10361       case FOURCC_opus:
10362       {
10363         GNode *opus;
10364         const guint8 *opus_data;
10365         guint8 *channel_mapping = NULL;
10366         guint32 rate;
10367         guint8 channels;
10368         guint8 channel_mapping_family;
10369         guint8 stream_count;
10370         guint8 coupled_count;
10371         guint8 i;
10372
10373         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10374         opus_data = opus->data;
10375
10376         channels = GST_READ_UINT8 (opus_data + 45);
10377         rate = GST_READ_UINT32_LE (opus_data + 48);
10378         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10379         stream_count = GST_READ_UINT8 (opus_data + 55);
10380         coupled_count = GST_READ_UINT8 (opus_data + 56);
10381
10382         if (channels > 0) {
10383           channel_mapping = g_malloc (channels * sizeof (guint8));
10384           for (i = 0; i < channels; i++)
10385             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10386         }
10387
10388         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10389             channel_mapping_family, stream_count, coupled_count,
10390             channel_mapping);
10391         break;
10392       }
10393       default:
10394         break;
10395     }
10396
10397     if (codec) {
10398       GstStructure *s;
10399       gint bitrate = 0;
10400
10401       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10402           GST_TAG_AUDIO_CODEC, codec, NULL);
10403       g_free (codec);
10404       codec = NULL;
10405
10406       /* some bitrate info may have ended up in caps */
10407       s = gst_caps_get_structure (stream->caps, 0);
10408       gst_structure_get_int (s, "bitrate", &bitrate);
10409       if (bitrate > 0)
10410         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10411             GST_TAG_BITRATE, bitrate, NULL);
10412     }
10413
10414     if (stream->protected && fourcc == FOURCC_mp4a)
10415       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10416     else
10417       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10418
10419     wave = NULL;
10420     esds = NULL;
10421     if (mp4a) {
10422       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10423       if (wave)
10424         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10425       if (!esds)
10426         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10427     }
10428
10429
10430     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10431        16 bits is a byte-swapped wave-style codec identifier,
10432        and we can find a WAVE header internally to a 'wave' atom here.
10433        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10434        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10435        is big-endian).
10436      */
10437     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10438       if (len < offset + 20) {
10439         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10440       } else {
10441         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10442         const guint8 *data = stsd_data + offset + 16;
10443         GNode *wavenode;
10444         GNode *waveheadernode;
10445
10446         wavenode = g_node_new ((guint8 *) data);
10447         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10448           const guint8 *waveheader;
10449           guint32 headerlen;
10450
10451           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10452           if (waveheadernode) {
10453             waveheader = (const guint8 *) waveheadernode->data;
10454             headerlen = QT_UINT32 (waveheader);
10455
10456             if (headerlen > 8) {
10457               gst_riff_strf_auds *header = NULL;
10458               GstBuffer *headerbuf;
10459               GstBuffer *extra;
10460
10461               waveheader += 8;
10462               headerlen -= 8;
10463
10464               headerbuf = gst_buffer_new_and_alloc (headerlen);
10465               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10466
10467               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10468                       headerbuf, &header, &extra)) {
10469                 gst_caps_unref (stream->caps);
10470                 /* FIXME: Need to do something with the channel reorder map */
10471                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10472                     header, extra, NULL, NULL, NULL);
10473
10474                 if (extra)
10475                   gst_buffer_unref (extra);
10476                 g_free (header);
10477               }
10478             }
10479           } else
10480             GST_DEBUG ("Didn't find waveheadernode for this codec");
10481         }
10482         g_node_destroy (wavenode);
10483       }
10484     } else if (esds) {
10485       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10486     } else {
10487       switch (fourcc) {
10488 #if 0
10489           /* FIXME: what is in the chunk? */
10490         case FOURCC_QDMC:
10491         {
10492           gint len = QT_UINT32 (stsd_data);
10493
10494           /* seems to be always = 116 = 0x74 */
10495           break;
10496         }
10497 #endif
10498         case FOURCC_QDM2:
10499         {
10500           gint len = QT_UINT32 (stsd_data);
10501
10502           if (len > 0x4C) {
10503             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10504
10505             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10506             gst_caps_set_simple (stream->caps,
10507                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10508             gst_buffer_unref (buf);
10509           }
10510           gst_caps_set_simple (stream->caps,
10511               "samplesize", G_TYPE_INT, samplesize, NULL);
10512           break;
10513         }
10514         case FOURCC_alac:
10515         {
10516           GNode *alac, *wave = NULL;
10517
10518           /* apparently, m4a has this atom appended directly in the stsd entry,
10519            * while mov has it in a wave atom */
10520           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10521           if (alac) {
10522             /* alac now refers to stsd entry atom */
10523             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10524             if (wave)
10525               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10526             else
10527               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10528           }
10529           if (alac) {
10530             const guint8 *alac_data = alac->data;
10531             gint len = QT_UINT32 (alac->data);
10532             GstBuffer *buf;
10533
10534             if (len < 36) {
10535               GST_DEBUG_OBJECT (qtdemux,
10536                   "discarding alac atom with unexpected len %d", len);
10537             } else {
10538               /* codec-data contains alac atom size and prefix,
10539                * ffmpeg likes it that way, not quite gst-ish though ...*/
10540               buf = gst_buffer_new_and_alloc (len);
10541               gst_buffer_fill (buf, 0, alac->data, len);
10542               gst_caps_set_simple (stream->caps,
10543                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10544               gst_buffer_unref (buf);
10545
10546               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10547               stream->n_channels = QT_UINT8 (alac_data + 21);
10548               stream->rate = QT_UINT32 (alac_data + 32);
10549             }
10550           }
10551           gst_caps_set_simple (stream->caps,
10552               "samplesize", G_TYPE_INT, samplesize, NULL);
10553           break;
10554         }
10555         case FOURCC_sawb:
10556           /* Fallthrough! */
10557           amrwb = TRUE;
10558         case FOURCC_samr:
10559         {
10560           gint len = QT_UINT32 (stsd_data);
10561
10562           if (len > 0x34) {
10563             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10564             guint bitrate;
10565
10566             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10567
10568             /* If we have enough data, let's try to get the 'damr' atom. See
10569              * the 3GPP container spec (26.244) for more details. */
10570             if ((len - 0x34) > 8 &&
10571                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10572               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10573                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10574             }
10575
10576             gst_caps_set_simple (stream->caps,
10577                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10578             gst_buffer_unref (buf);
10579           }
10580           break;
10581         }
10582         case FOURCC_mp4a:
10583         {
10584           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10585           gint len = QT_UINT32 (stsd_data);
10586
10587           if (len >= 50) {
10588             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10589
10590             if (sound_version == 1) {
10591               guint16 channels = QT_UINT16 (stsd_data + 40);
10592               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10593               guint8 codec_data[2];
10594               GstBuffer *buf;
10595               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10596
10597               gint sample_rate_index =
10598                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10599
10600               /* build AAC codec data */
10601               codec_data[0] = profile << 3;
10602               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10603               codec_data[1] = (sample_rate_index & 0x01) << 7;
10604               codec_data[1] |= (channels & 0xF) << 3;
10605
10606               buf = gst_buffer_new_and_alloc (2);
10607               gst_buffer_fill (buf, 0, codec_data, 2);
10608               gst_caps_set_simple (stream->caps,
10609                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10610               gst_buffer_unref (buf);
10611             }
10612           }
10613           break;
10614         }
10615         default:
10616           GST_INFO_OBJECT (qtdemux,
10617               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10618           break;
10619       }
10620     }
10621     GST_INFO_OBJECT (qtdemux,
10622         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10623         GST_FOURCC_ARGS (fourcc), stream->caps);
10624
10625   } else if (stream->subtype == FOURCC_strm) {
10626     if (fourcc == FOURCC_rtsp) {
10627       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10628     } else {
10629       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10630           GST_FOURCC_ARGS (fourcc));
10631       goto unknown_stream;
10632     }
10633     stream->sampled = TRUE;
10634   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10635       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10636
10637     stream->sampled = TRUE;
10638     stream->sparse = TRUE;
10639
10640     stream->caps =
10641         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10642     if (codec) {
10643       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10644           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10645       g_free (codec);
10646       codec = NULL;
10647     }
10648
10649     /* hunt for sort-of codec data */
10650     switch (fourcc) {
10651       case FOURCC_mp4s:
10652       {
10653         GNode *mp4s = NULL;
10654         GNode *esds = NULL;
10655
10656         /* look for palette in a stsd->mp4s->esds sub-atom */
10657         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10658         if (mp4s)
10659           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10660         if (esds == NULL) {
10661           /* Invalid STSD */
10662           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10663           break;
10664         }
10665
10666         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10667         break;
10668       }
10669       default:
10670         GST_INFO_OBJECT (qtdemux,
10671             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10672         break;
10673     }
10674     GST_INFO_OBJECT (qtdemux,
10675         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10676         GST_FOURCC_ARGS (fourcc), stream->caps);
10677   } else {
10678     /* everything in 1 sample */
10679     stream->sampled = TRUE;
10680
10681     stream->caps =
10682         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10683
10684     if (stream->caps == NULL)
10685       goto unknown_stream;
10686
10687     if (codec) {
10688       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10689           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10690       g_free (codec);
10691       codec = NULL;
10692     }
10693   }
10694
10695   /* promote to sampled format */
10696   if (stream->fourcc == FOURCC_samr) {
10697     /* force mono 8000 Hz for AMR */
10698     stream->sampled = TRUE;
10699     stream->n_channels = 1;
10700     stream->rate = 8000;
10701   } else if (stream->fourcc == FOURCC_sawb) {
10702     /* force mono 16000 Hz for AMR-WB */
10703     stream->sampled = TRUE;
10704     stream->n_channels = 1;
10705     stream->rate = 16000;
10706   } else if (stream->fourcc == FOURCC_mp4a) {
10707     stream->sampled = TRUE;
10708   }
10709
10710   /* collect sample information */
10711   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10712     goto samples_failed;
10713
10714   if (qtdemux->fragmented) {
10715     guint64 offset;
10716
10717     /* need all moov samples as basis; probably not many if any at all */
10718     /* prevent moof parsing taking of at this time */
10719     offset = qtdemux->moof_offset;
10720     qtdemux->moof_offset = 0;
10721     if (stream->n_samples &&
10722         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10723       qtdemux->moof_offset = offset;
10724       goto samples_failed;
10725     }
10726     qtdemux->moof_offset = 0;
10727     /* movie duration more reliable in this case (e.g. mehd) */
10728     if (qtdemux->segment.duration &&
10729         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10730       stream->duration =
10731           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10732   }
10733
10734   /* configure segments */
10735   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10736     goto segments_failed;
10737
10738   /* add some language tag, if useful */
10739   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10740       strcmp (stream->lang_id, "und")) {
10741     const gchar *lang_code;
10742
10743     /* convert ISO 639-2 code to ISO 639-1 */
10744     lang_code = gst_tag_get_language_code (stream->lang_id);
10745     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10746         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10747   }
10748
10749   /* Check for UDTA tags */
10750   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10751     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10752   }
10753
10754   /* now we are ready to add the stream */
10755   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10756     goto too_many_streams;
10757
10758   if (!qtdemux->got_moov) {
10759     qtdemux->streams[qtdemux->n_streams] = stream;
10760     qtdemux->n_streams++;
10761     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10762   }
10763
10764   return TRUE;
10765
10766 /* ERRORS */
10767 skip_track:
10768   {
10769     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10770     if (new_stream)
10771       gst_qtdemux_stream_free (qtdemux, stream);
10772     return TRUE;
10773   }
10774 corrupt_file:
10775   {
10776     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10777         (_("This file is corrupt and cannot be played.")), (NULL));
10778     if (new_stream)
10779       gst_qtdemux_stream_free (qtdemux, stream);
10780     return FALSE;
10781   }
10782 error_encrypted:
10783   {
10784     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10785     if (new_stream)
10786       gst_qtdemux_stream_free (qtdemux, stream);
10787     return FALSE;
10788   }
10789 samples_failed:
10790 segments_failed:
10791   {
10792     /* we posted an error already */
10793     /* free stbl sub-atoms */
10794     gst_qtdemux_stbl_free (stream);
10795     if (new_stream)
10796       gst_qtdemux_stream_free (qtdemux, stream);
10797     return FALSE;
10798   }
10799 existing_stream:
10800   {
10801     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10802         track_id);
10803     if (new_stream)
10804       gst_qtdemux_stream_free (qtdemux, stream);
10805     return TRUE;
10806   }
10807 unknown_stream:
10808   {
10809     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10810         GST_FOURCC_ARGS (stream->subtype));
10811     if (new_stream)
10812       gst_qtdemux_stream_free (qtdemux, stream);
10813     return TRUE;
10814   }
10815 too_many_streams:
10816   {
10817     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10818         (_("This file contains too many streams. Only playing first %d"),
10819             GST_QTDEMUX_MAX_STREAMS), (NULL));
10820     return TRUE;
10821   }
10822 }
10823
10824 /* If we can estimate the overall bitrate, and don't have information about the
10825  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10826  * the overall bitrate minus the sum of the bitrates of all other streams. This
10827  * should be useful for the common case where we have one audio and one video
10828  * stream and can estimate the bitrate of one, but not the other. */
10829 static void
10830 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10831 {
10832   QtDemuxStream *stream = NULL;
10833   gint64 size, sys_bitrate, sum_bitrate = 0;
10834   GstClockTime duration;
10835   gint i;
10836   guint bitrate;
10837
10838   if (qtdemux->fragmented)
10839     return;
10840
10841   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10842
10843   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10844       || size <= 0) {
10845     GST_DEBUG_OBJECT (qtdemux,
10846         "Size in bytes of the stream not known - bailing");
10847     return;
10848   }
10849
10850   /* Subtract the header size */
10851   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10852       size, qtdemux->header_size);
10853
10854   if (size < qtdemux->header_size)
10855     return;
10856
10857   size = size - qtdemux->header_size;
10858
10859   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
10860     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10861     return;
10862   }
10863
10864   for (i = 0; i < qtdemux->n_streams; i++) {
10865     switch (qtdemux->streams[i]->subtype) {
10866       case FOURCC_soun:
10867       case FOURCC_vide:
10868         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10869             qtdemux->streams[i]->caps);
10870         /* retrieve bitrate, prefer avg then max */
10871         bitrate = 0;
10872         if (qtdemux->streams[i]->pending_tags) {
10873           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10874               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10875           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10876           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10877               GST_TAG_NOMINAL_BITRATE, &bitrate);
10878           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10879           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10880               GST_TAG_BITRATE, &bitrate);
10881           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10882         }
10883         if (bitrate)
10884           sum_bitrate += bitrate;
10885         else {
10886           if (stream) {
10887             GST_DEBUG_OBJECT (qtdemux,
10888                 ">1 stream with unknown bitrate - bailing");
10889             return;
10890           } else
10891             stream = qtdemux->streams[i];
10892         }
10893
10894       default:
10895         /* For other subtypes, we assume no significant impact on bitrate */
10896         break;
10897     }
10898   }
10899
10900   if (!stream) {
10901     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10902     return;
10903   }
10904
10905   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10906
10907   if (sys_bitrate < sum_bitrate) {
10908     /* This can happen, since sum_bitrate might be derived from maximum
10909      * bitrates and not average bitrates */
10910     GST_DEBUG_OBJECT (qtdemux,
10911         "System bitrate less than sum bitrate - bailing");
10912     return;
10913   }
10914
10915   bitrate = sys_bitrate - sum_bitrate;
10916   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10917       ", Stream bitrate = %u", sys_bitrate, bitrate);
10918
10919   if (!stream->pending_tags)
10920     stream->pending_tags = gst_tag_list_new_empty ();
10921
10922   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10923       GST_TAG_BITRATE, bitrate, NULL);
10924 }
10925
10926 static GstFlowReturn
10927 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10928 {
10929   gint i;
10930   GstFlowReturn ret = GST_FLOW_OK;
10931
10932   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10933
10934   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10935     QtDemuxStream *stream = qtdemux->streams[i];
10936     guint32 sample_num = 0;
10937
10938     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10939         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10940
10941     if (qtdemux->fragmented) {
10942       /* need all moov samples first */
10943       GST_OBJECT_LOCK (qtdemux);
10944       while (stream->n_samples == 0)
10945         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10946           break;
10947       GST_OBJECT_UNLOCK (qtdemux);
10948     } else {
10949       /* discard any stray moof */
10950       qtdemux->moof_offset = 0;
10951     }
10952
10953     /* prepare braking */
10954     if (ret != GST_FLOW_ERROR)
10955       ret = GST_FLOW_OK;
10956
10957     /* in pull mode, we should have parsed some sample info by now;
10958      * and quite some code will not handle no samples.
10959      * in push mode, we'll just have to deal with it */
10960     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10961       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10962       gst_qtdemux_remove_stream (qtdemux, i);
10963       i--;
10964       continue;
10965     }
10966
10967     /* parse the initial sample for use in setting the frame rate cap */
10968     while (sample_num == 0 && sample_num < stream->n_samples) {
10969       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10970         break;
10971       ++sample_num;
10972     }
10973     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
10974       stream->first_duration = stream->samples[0].duration;
10975       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
10976           stream->track_id, stream->first_duration);
10977     }
10978   }
10979
10980   return ret;
10981 }
10982
10983 static GstFlowReturn
10984 qtdemux_expose_streams (GstQTDemux * qtdemux)
10985 {
10986   gint i;
10987   GstFlowReturn ret = GST_FLOW_OK;
10988   GSList *oldpads = NULL;
10989   GSList *iter;
10990
10991   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
10992
10993   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10994     QtDemuxStream *stream = qtdemux->streams[i];
10995     GstPad *oldpad = stream->pad;
10996     GstTagList *list;
10997
10998     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10999         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11000
11001     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11002         stream->track_id == qtdemux->chapters_track_id) {
11003       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11004          so that it doesn't look like a subtitle track */
11005       gst_qtdemux_remove_stream (qtdemux, i);
11006       i--;
11007       continue;
11008     }
11009
11010     /* now we have all info and can expose */
11011     list = stream->pending_tags;
11012     stream->pending_tags = NULL;
11013     if (oldpad)
11014       oldpads = g_slist_prepend (oldpads, oldpad);
11015     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11016       return GST_FLOW_ERROR;
11017   }
11018
11019   gst_qtdemux_guess_bitrate (qtdemux);
11020
11021   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11022
11023   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11024     GstPad *oldpad = iter->data;
11025     GstEvent *event;
11026
11027     event = gst_event_new_eos ();
11028     if (qtdemux->segment_seqnum)
11029       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11030
11031     gst_pad_push_event (oldpad, event);
11032     gst_pad_set_active (oldpad, FALSE);
11033     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11034     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11035     gst_object_unref (oldpad);
11036   }
11037
11038   /* check if we should post a redirect in case there is a single trak
11039    * and it is a redirecting trak */
11040   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11041     GstMessage *m;
11042
11043     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11044         "an external content");
11045     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11046         gst_structure_new ("redirect",
11047             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11048             NULL));
11049     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11050     qtdemux->posted_redirect = TRUE;
11051   }
11052
11053   for (i = 0; i < qtdemux->n_streams; i++) {
11054     QtDemuxStream *stream = qtdemux->streams[i];
11055
11056     qtdemux_do_allocation (qtdemux, stream);
11057   }
11058
11059   qtdemux->exposed = TRUE;
11060   return ret;
11061 }
11062
11063 /* check if major or compatible brand is 3GP */
11064 static inline gboolean
11065 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11066 {
11067   if (major) {
11068     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11069         FOURCC_3g__);
11070   } else if (qtdemux->comp_brands != NULL) {
11071     GstMapInfo map;
11072     guint8 *data;
11073     gsize size;
11074     gboolean res = FALSE;
11075
11076     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11077     data = map.data;
11078     size = map.size;
11079     while (size >= 4) {
11080       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11081           FOURCC_3g__);
11082       data += 4;
11083       size -= 4;
11084     }
11085     gst_buffer_unmap (qtdemux->comp_brands, &map);
11086     return res;
11087   } else {
11088     return FALSE;
11089   }
11090 }
11091
11092 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11093 static inline gboolean
11094 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11095 {
11096   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11097       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11098       || fourcc == FOURCC_albm;
11099 }
11100
11101 static void
11102 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11103     const char *tag, const char *dummy, GNode * node)
11104 {
11105   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11106   int offset;
11107   char *name;
11108   gchar *data;
11109   gdouble longitude, latitude, altitude;
11110   gint len;
11111
11112   len = QT_UINT32 (node->data);
11113   if (len <= 14)
11114     goto short_read;
11115
11116   data = node->data;
11117   offset = 14;
11118
11119   /* TODO: language code skipped */
11120
11121   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11122
11123   if (!name) {
11124     /* do not alarm in trivial case, but bail out otherwise */
11125     if (*(data + offset) != 0) {
11126       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11127           "giving up", tag);
11128     }
11129   } else {
11130     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11131         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11132     offset += strlen (name);
11133     g_free (name);
11134   }
11135
11136   if (len < offset + 2 + 4 + 4 + 4)
11137     goto short_read;
11138
11139   /* +1 +1 = skip null-terminator and location role byte */
11140   offset += 1 + 1;
11141   /* table in spec says unsigned, semantics say negative has meaning ... */
11142   longitude = QT_SFP32 (data + offset);
11143
11144   offset += 4;
11145   latitude = QT_SFP32 (data + offset);
11146
11147   offset += 4;
11148   altitude = QT_SFP32 (data + offset);
11149
11150   /* one invalid means all are invalid */
11151   if (longitude >= -180.0 && longitude <= 180.0 &&
11152       latitude >= -90.0 && latitude <= 90.0) {
11153     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11154         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11155         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11156         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11157   }
11158
11159   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11160
11161   return;
11162
11163   /* ERRORS */
11164 short_read:
11165   {
11166     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11167     return;
11168   }
11169 }
11170
11171
11172 static void
11173 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11174     const char *tag, const char *dummy, GNode * node)
11175 {
11176   guint16 y;
11177   GDate *date;
11178   gint len;
11179
11180   len = QT_UINT32 (node->data);
11181   if (len < 14)
11182     return;
11183
11184   y = QT_UINT16 ((guint8 *) node->data + 12);
11185   if (y == 0) {
11186     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11187     return;
11188   }
11189   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11190
11191   date = g_date_new_dmy (1, 1, y);
11192   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11193   g_date_free (date);
11194 }
11195
11196 static void
11197 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11198     const char *tag, const char *dummy, GNode * node)
11199 {
11200   int offset;
11201   char *tag_str = NULL;
11202   guint8 *entity;
11203   guint16 table;
11204   gint len;
11205
11206   len = QT_UINT32 (node->data);
11207   if (len <= 20)
11208     goto short_read;
11209
11210   offset = 12;
11211   entity = (guint8 *) node->data + offset;
11212   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11213     GST_DEBUG_OBJECT (qtdemux,
11214         "classification info: %c%c%c%c invalid classification entity",
11215         entity[0], entity[1], entity[2], entity[3]);
11216     return;
11217   }
11218
11219   offset += 4;
11220   table = QT_UINT16 ((guint8 *) node->data + offset);
11221
11222   /* Language code skipped */
11223
11224   offset += 4;
11225
11226   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11227    * XXXX: classification entity, fixed length 4 chars.
11228    * Y[YYYY]: classification table, max 5 chars.
11229    */
11230   tag_str = g_strdup_printf ("----://%u/%s",
11231       table, (char *) node->data + offset);
11232
11233   /* memcpy To be sure we're preserving byte order */
11234   memcpy (tag_str, entity, 4);
11235   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11236
11237   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11238
11239   g_free (tag_str);
11240
11241   return;
11242
11243   /* ERRORS */
11244 short_read:
11245   {
11246     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11247     return;
11248   }
11249 }
11250
11251 static gboolean
11252 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11253     const char *tag, const char *dummy, GNode * node)
11254 {
11255   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11256   GNode *data;
11257   char *s;
11258   int len;
11259   guint32 type;
11260   int offset;
11261   gboolean ret = TRUE;
11262   const gchar *charset = NULL;
11263
11264   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11265   if (data) {
11266     len = QT_UINT32 (data->data);
11267     type = QT_UINT32 ((guint8 *) data->data + 8);
11268     if (type == 0x00000001 && len > 16) {
11269       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11270           env_vars);
11271       if (s) {
11272         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11273         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11274         g_free (s);
11275       } else {
11276         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11277       }
11278     }
11279   } else {
11280     len = QT_UINT32 (node->data);
11281     type = QT_UINT32 ((guint8 *) node->data + 4);
11282     if ((type >> 24) == 0xa9) {
11283       gint str_len;
11284       gint lang_code;
11285
11286       /* Type starts with the (C) symbol, so the next data is a list
11287        * of (string size(16), language code(16), string) */
11288
11289       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11290       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11291
11292       /* the string + fourcc + size + 2 16bit fields,
11293        * means that there are more tags in this atom */
11294       if (len > str_len + 8 + 4) {
11295         /* TODO how to represent the same tag in different languages? */
11296         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11297             "text alternatives, reading only first one");
11298       }
11299
11300       offset = 12;
11301       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
11302       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11303
11304       if (lang_code < 0x800) {  /* MAC encoded string */
11305         charset = "mac";
11306       }
11307     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11308             QT_FOURCC ((guint8 *) node->data + 4))) {
11309       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11310
11311       /* we go for 3GP style encoding if major brands claims so,
11312        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11313       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11314           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11315               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11316         offset = 14;
11317         /* 16-bit Language code is ignored here as well */
11318         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11319       } else {
11320         goto normal;
11321       }
11322     } else {
11323     normal:
11324       offset = 8;
11325       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11326       ret = FALSE;              /* may have to fallback */
11327     }
11328     if (charset) {
11329       GError *err = NULL;
11330
11331       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11332           charset, NULL, NULL, &err);
11333       if (err) {
11334         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11335             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11336             err->message);
11337         g_error_free (err);
11338       }
11339     } else {
11340       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11341           len - offset, env_vars);
11342     }
11343     if (s) {
11344       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11345       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11346       g_free (s);
11347       ret = TRUE;
11348     } else {
11349       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11350     }
11351   }
11352   return ret;
11353 }
11354
11355 static void
11356 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11357     const char *tag, const char *dummy, GNode * node)
11358 {
11359   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11360 }
11361
11362 static void
11363 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11364     const char *tag, const char *dummy, GNode * node)
11365 {
11366   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11367   guint8 *data;
11368   char *s, *t, *k = NULL;
11369   int len;
11370   int offset;
11371   int count;
11372
11373   /* first try normal string tag if major brand not 3GP */
11374   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11375     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11376       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11377        * let's try it 3gpp way after minor safety check */
11378       data = node->data;
11379       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11380         return;
11381     } else
11382       return;
11383   }
11384
11385   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11386
11387   data = node->data;
11388
11389   len = QT_UINT32 (data);
11390   if (len < 15)
11391     goto short_read;
11392
11393   count = QT_UINT8 (data + 14);
11394   offset = 15;
11395   for (; count; count--) {
11396     gint slen;
11397
11398     if (offset + 1 > len)
11399       goto short_read;
11400     slen = QT_UINT8 (data + offset);
11401     offset += 1;
11402     if (offset + slen > len)
11403       goto short_read;
11404     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11405         slen, env_vars);
11406     if (s) {
11407       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11408       if (k) {
11409         t = g_strjoin (",", k, s, NULL);
11410         g_free (s);
11411         g_free (k);
11412         k = t;
11413       } else {
11414         k = s;
11415       }
11416     } else {
11417       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11418     }
11419     offset += slen;
11420   }
11421
11422 done:
11423   if (k) {
11424     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11425     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11426   }
11427   g_free (k);
11428
11429   return;
11430
11431   /* ERRORS */
11432 short_read:
11433   {
11434     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11435     goto done;
11436   }
11437 }
11438
11439 static void
11440 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11441     const char *tag1, const char *tag2, GNode * node)
11442 {
11443   GNode *data;
11444   int len;
11445   int type;
11446   int n1, n2;
11447
11448   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11449   if (data) {
11450     len = QT_UINT32 (data->data);
11451     type = QT_UINT32 ((guint8 *) data->data + 8);
11452     if (type == 0x00000000 && len >= 22) {
11453       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11454       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11455       if (n1 > 0) {
11456         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11457         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11458       }
11459       if (n2 > 0) {
11460         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11461         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11462       }
11463     }
11464   }
11465 }
11466
11467 static void
11468 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11469     const char *tag1, const char *dummy, GNode * node)
11470 {
11471   GNode *data;
11472   int len;
11473   int type;
11474   int n1;
11475
11476   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11477   if (data) {
11478     len = QT_UINT32 (data->data);
11479     type = QT_UINT32 ((guint8 *) data->data + 8);
11480     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11481     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11482     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11483       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11484       if (n1) {
11485         /* do not add bpm=0 */
11486         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11487         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11488             NULL);
11489       }
11490     }
11491   }
11492 }
11493
11494 static void
11495 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11496     const char *tag1, const char *dummy, GNode * node)
11497 {
11498   GNode *data;
11499   int len;
11500   int type;
11501   guint32 num;
11502
11503   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11504   if (data) {
11505     len = QT_UINT32 (data->data);
11506     type = QT_UINT32 ((guint8 *) data->data + 8);
11507     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11508     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11509     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11510       num = QT_UINT32 ((guint8 *) data->data + 16);
11511       if (num) {
11512         /* do not add num=0 */
11513         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11514         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11515       }
11516     }
11517   }
11518 }
11519
11520 static void
11521 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11522     const char *tag1, const char *dummy, GNode * node)
11523 {
11524   GNode *data;
11525   int len;
11526   int type;
11527   GstSample *sample;
11528
11529   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11530   if (data) {
11531     len = QT_UINT32 (data->data);
11532     type = QT_UINT32 ((guint8 *) data->data + 8);
11533     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11534     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11535       if ((sample =
11536               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11537                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11538         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11539         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11540         gst_sample_unref (sample);
11541       }
11542     }
11543   }
11544 }
11545
11546 static void
11547 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11548     const char *tag, const char *dummy, GNode * node)
11549 {
11550   GNode *data;
11551   char *s;
11552   int len;
11553   int type;
11554
11555   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11556   if (data) {
11557     len = QT_UINT32 (data->data);
11558     type = QT_UINT32 ((guint8 *) data->data + 8);
11559     if (type == 0x00000001 && len > 16) {
11560       guint y, m = 1, d = 1;
11561       gint ret;
11562
11563       s = g_strndup ((char *) data->data + 16, len - 16);
11564       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11565       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11566       if (ret >= 1 && y > 1500 && y < 3000) {
11567         GDate *date;
11568
11569         date = g_date_new_dmy (d, m, y);
11570         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11571         g_date_free (date);
11572       } else {
11573         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11574       }
11575       g_free (s);
11576     }
11577   }
11578 }
11579
11580 static void
11581 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11582     const char *tag, const char *dummy, GNode * node)
11583 {
11584   GNode *data;
11585
11586   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11587
11588   /* re-route to normal string tag if major brand says so
11589    * or no data atom and compatible brand suggests so */
11590   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11591       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11592     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11593     return;
11594   }
11595
11596   if (data) {
11597     guint len, type, n;
11598
11599     len = QT_UINT32 (data->data);
11600     type = QT_UINT32 ((guint8 *) data->data + 8);
11601     if (type == 0x00000000 && len >= 18) {
11602       n = QT_UINT16 ((guint8 *) data->data + 16);
11603       if (n > 0) {
11604         const gchar *genre;
11605
11606         genre = gst_tag_id3_genre_get (n - 1);
11607         if (genre != NULL) {
11608           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11609           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11610         }
11611       }
11612     }
11613   }
11614 }
11615
11616 static void
11617 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11618     const gchar * tag, guint8 * data, guint32 datasize)
11619 {
11620   gdouble value;
11621   gchar *datacopy;
11622
11623   /* make a copy to have \0 at the end */
11624   datacopy = g_strndup ((gchar *) data, datasize);
11625
11626   /* convert the str to double */
11627   if (sscanf (datacopy, "%lf", &value) == 1) {
11628     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11629     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11630   } else {
11631     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11632         datacopy);
11633   }
11634   g_free (datacopy);
11635 }
11636
11637
11638 static void
11639 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11640     const char *tag, const char *tag_bis, GNode * node)
11641 {
11642   GNode *mean;
11643   GNode *name;
11644   GNode *data;
11645   guint32 meansize;
11646   guint32 namesize;
11647   guint32 datatype;
11648   guint32 datasize;
11649   const gchar *meanstr;
11650   const gchar *namestr;
11651
11652   /* checking the whole ---- atom size for consistency */
11653   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11654     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11655     return;
11656   }
11657
11658   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11659   if (!mean) {
11660     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11661     return;
11662   }
11663
11664   meansize = QT_UINT32 (mean->data);
11665   if (meansize <= 12) {
11666     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11667     return;
11668   }
11669   meanstr = ((gchar *) mean->data) + 12;
11670   meansize -= 12;
11671
11672   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11673   if (!name) {
11674     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11675     return;
11676   }
11677
11678   namesize = QT_UINT32 (name->data);
11679   if (namesize <= 12) {
11680     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11681     return;
11682   }
11683   namestr = ((gchar *) name->data) + 12;
11684   namesize -= 12;
11685
11686   /*
11687    * Data atom is:
11688    * uint32 - size
11689    * uint32 - name
11690    * uint8  - version
11691    * uint24 - data type
11692    * uint32 - all 0
11693    * rest   - the data
11694    */
11695   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11696   if (!data) {
11697     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11698     return;
11699   }
11700   datasize = QT_UINT32 (data->data);
11701   if (datasize <= 16) {
11702     GST_WARNING_OBJECT (demux, "Data atom too small");
11703     return;
11704   }
11705   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11706
11707   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11708       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11709     static const struct
11710     {
11711       const gchar name[28];
11712       const gchar tag[28];
11713     } tags[] = {
11714       {
11715       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11716       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11717       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11718       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11719       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11720       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11721       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11722       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11723     };
11724     int i;
11725
11726     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11727       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11728         switch (gst_tag_get_type (tags[i].tag)) {
11729           case G_TYPE_DOUBLE:
11730             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11731                 ((guint8 *) data->data) + 16, datasize - 16);
11732             break;
11733           case G_TYPE_STRING:
11734             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11735             break;
11736           default:
11737             /* not reached */
11738             break;
11739         }
11740         break;
11741       }
11742     }
11743     if (i == G_N_ELEMENTS (tags))
11744       goto unknown_tag;
11745   } else {
11746     goto unknown_tag;
11747   }
11748
11749   return;
11750
11751 /* errors */
11752 unknown_tag:
11753 #ifndef GST_DISABLE_GST_DEBUG
11754   {
11755     gchar *namestr_dbg;
11756     gchar *meanstr_dbg;
11757
11758     meanstr_dbg = g_strndup (meanstr, meansize);
11759     namestr_dbg = g_strndup (namestr, namesize);
11760
11761     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11762         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11763
11764     g_free (namestr_dbg);
11765     g_free (meanstr_dbg);
11766   }
11767 #endif
11768   return;
11769 }
11770
11771 static void
11772 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11773     const char *tag_bis, GNode * node)
11774 {
11775   guint8 *data;
11776   GstBuffer *buf;
11777   guint len;
11778   GstTagList *id32_taglist = NULL;
11779
11780   GST_LOG_OBJECT (demux, "parsing ID32");
11781
11782   data = node->data;
11783   len = GST_READ_UINT32_BE (data);
11784
11785   /* need at least full box and language tag */
11786   if (len < 12 + 2)
11787     return;
11788
11789   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11790   gst_buffer_fill (buf, 0, data + 14, len - 14);
11791
11792   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11793   if (id32_taglist) {
11794     GST_LOG_OBJECT (demux, "parsing ok");
11795     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11796     gst_tag_list_unref (id32_taglist);
11797   } else {
11798     GST_LOG_OBJECT (demux, "parsing failed");
11799   }
11800
11801   gst_buffer_unref (buf);
11802 }
11803
11804 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11805     const char *tag, const char *tag_bis, GNode * node);
11806
11807 /* unmapped tags
11808 FOURCC_pcst -> if media is a podcast -> bool
11809 FOURCC_cpil -> if media is part of a compilation -> bool
11810 FOURCC_pgap -> if media is part of a gapless context -> bool
11811 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11812 */
11813
11814 static const struct
11815 {
11816   guint32 fourcc;
11817   const gchar *gst_tag;
11818   const gchar *gst_tag_bis;
11819   const GstQTDemuxAddTagFunc func;
11820 } add_funcs[] = {
11821   {
11822   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11823   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11824   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11825   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11826   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11827   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11828   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11829   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11830   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11831   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11832   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11833   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11834   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11835   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11836   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11837   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11838   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11839   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11840   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11841   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11842   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11843   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11844   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11845         qtdemux_tag_add_num}, {
11846   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11847         qtdemux_tag_add_num}, {
11848   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11849   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11850   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11851   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11852   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11853   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11854   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11855   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11856   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11857   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11858   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11859   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11860   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11861   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11862   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11863   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11864   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11865   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11866         qtdemux_tag_add_classification}, {
11867   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11868   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11869   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11870
11871     /* This is a special case, some tags are stored in this
11872      * 'reverse dns naming', according to:
11873      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11874      * bug #614471
11875      */
11876   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11877     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11878   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11879 };
11880
11881 struct _GstQtDemuxTagList
11882 {
11883   GstQTDemux *demux;
11884   GstTagList *taglist;
11885 };
11886 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11887
11888 static void
11889 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11890 {
11891   gint len;
11892   guint8 *data;
11893   GstBuffer *buf;
11894   gchar *media_type;
11895   const gchar *style;
11896   GstSample *sample;
11897   GstStructure *s;
11898   guint i;
11899   guint8 ndata[4];
11900   GstQTDemux *demux = qtdemuxtaglist->demux;
11901   GstTagList *taglist = qtdemuxtaglist->taglist;
11902
11903   data = node->data;
11904   len = QT_UINT32 (data);
11905   buf = gst_buffer_new_and_alloc (len);
11906   gst_buffer_fill (buf, 0, data, len);
11907
11908   /* heuristic to determine style of tag */
11909   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11910       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11911     style = "itunes";
11912   else if (demux->major_brand == FOURCC_qt__)
11913     style = "quicktime";
11914   /* fall back to assuming iso/3gp tag style */
11915   else
11916     style = "iso";
11917
11918   /* santize the name for the caps. */
11919   for (i = 0; i < 4; i++) {
11920     guint8 d = data[4 + i];
11921     if (g_ascii_isalnum (d))
11922       ndata[i] = g_ascii_tolower (d);
11923     else
11924       ndata[i] = '_';
11925   }
11926
11927   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11928       ndata[0], ndata[1], ndata[2], ndata[3]);
11929   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11930
11931   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11932   sample = gst_sample_new (buf, NULL, NULL, s);
11933   gst_buffer_unref (buf);
11934   g_free (media_type);
11935
11936   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11937       len, s);
11938
11939   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11940       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11941
11942   gst_sample_unref (sample);
11943 }
11944
11945 static void
11946 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11947 {
11948   GNode *meta;
11949   GNode *ilst;
11950   GNode *xmp_;
11951   GNode *node;
11952   gint i;
11953   GstQtDemuxTagList demuxtaglist;
11954
11955   demuxtaglist.demux = qtdemux;
11956   demuxtaglist.taglist = taglist;
11957
11958   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11959   if (meta != NULL) {
11960     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11961     if (ilst == NULL) {
11962       GST_LOG_OBJECT (qtdemux, "no ilst");
11963       return;
11964     }
11965   } else {
11966     ilst = udta;
11967     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11968   }
11969
11970   i = 0;
11971   while (i < G_N_ELEMENTS (add_funcs)) {
11972     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
11973     if (node) {
11974       gint len;
11975
11976       len = QT_UINT32 (node->data);
11977       if (len < 12) {
11978         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
11979             GST_FOURCC_ARGS (add_funcs[i].fourcc));
11980       } else {
11981         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
11982             add_funcs[i].gst_tag_bis, node);
11983       }
11984       g_node_destroy (node);
11985     } else {
11986       i++;
11987     }
11988   }
11989
11990   /* parsed nodes have been removed, pass along remainder as blob */
11991   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
11992       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
11993
11994   /* parse up XMP_ node if existing */
11995   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
11996   if (xmp_ != NULL) {
11997     GstBuffer *buf;
11998     GstTagList *xmptaglist;
11999
12000     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12001         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12002     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12003     gst_buffer_unref (buf);
12004
12005     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12006   } else {
12007     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12008   }
12009 }
12010
12011 typedef struct
12012 {
12013   GstStructure *structure;      /* helper for sort function */
12014   gchar *location;
12015   guint min_req_bitrate;
12016   guint min_req_qt_version;
12017 } GstQtReference;
12018
12019 static gint
12020 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12021 {
12022   GstQtReference *ref_a = (GstQtReference *) a;
12023   GstQtReference *ref_b = (GstQtReference *) b;
12024
12025   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12026     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12027
12028   /* known bitrates go before unknown; higher bitrates go first */
12029   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12030 }
12031
12032 /* sort the redirects and post a message for the application.
12033  */
12034 static void
12035 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12036 {
12037   GstQtReference *best;
12038   GstStructure *s;
12039   GstMessage *msg;
12040   GValue list_val = { 0, };
12041   GList *l;
12042
12043   g_assert (references != NULL);
12044
12045   references = g_list_sort (references, qtdemux_redirects_sort_func);
12046
12047   best = (GstQtReference *) references->data;
12048
12049   g_value_init (&list_val, GST_TYPE_LIST);
12050
12051   for (l = references; l != NULL; l = l->next) {
12052     GstQtReference *ref = (GstQtReference *) l->data;
12053     GValue struct_val = { 0, };
12054
12055     ref->structure = gst_structure_new ("redirect",
12056         "new-location", G_TYPE_STRING, ref->location, NULL);
12057
12058     if (ref->min_req_bitrate > 0) {
12059       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12060           ref->min_req_bitrate, NULL);
12061     }
12062
12063     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12064     g_value_set_boxed (&struct_val, ref->structure);
12065     gst_value_list_append_value (&list_val, &struct_val);
12066     g_value_unset (&struct_val);
12067     /* don't free anything here yet, since we need best->structure below */
12068   }
12069
12070   g_assert (best != NULL);
12071   s = gst_structure_copy (best->structure);
12072
12073   if (g_list_length (references) > 1) {
12074     gst_structure_set_value (s, "locations", &list_val);
12075   }
12076
12077   g_value_unset (&list_val);
12078
12079   for (l = references; l != NULL; l = l->next) {
12080     GstQtReference *ref = (GstQtReference *) l->data;
12081
12082     gst_structure_free (ref->structure);
12083     g_free (ref->location);
12084     g_free (ref);
12085   }
12086   g_list_free (references);
12087
12088   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12089   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12090   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12091   qtdemux->posted_redirect = TRUE;
12092 }
12093
12094 /* look for redirect nodes, collect all redirect information and
12095  * process it.
12096  */
12097 static gboolean
12098 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12099 {
12100   GNode *rmra, *rmda, *rdrf;
12101
12102   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12103   if (rmra) {
12104     GList *redirects = NULL;
12105
12106     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12107     while (rmda) {
12108       GstQtReference ref = { NULL, NULL, 0, 0 };
12109       GNode *rmdr, *rmvc;
12110
12111       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12112         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12113         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12114             ref.min_req_bitrate);
12115       }
12116
12117       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12118         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12119         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12120
12121 #ifndef GST_DISABLE_GST_DEBUG
12122         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12123 #endif
12124         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12125
12126         GST_LOG_OBJECT (qtdemux,
12127             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12128             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12129             bitmask, check_type);
12130         if (package == FOURCC_qtim && check_type == 0) {
12131           ref.min_req_qt_version = version;
12132         }
12133       }
12134
12135       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12136       if (rdrf) {
12137         guint32 ref_type;
12138         guint8 *ref_data;
12139         guint ref_len;
12140
12141         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12142         if (ref_len > 20) {
12143           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12144           ref_data = (guint8 *) rdrf->data + 20;
12145           if (ref_type == FOURCC_alis) {
12146             guint record_len, record_version, fn_len;
12147
12148             if (ref_len > 70) {
12149               /* MacOSX alias record, google for alias-layout.txt */
12150               record_len = QT_UINT16 (ref_data + 4);
12151               record_version = QT_UINT16 (ref_data + 4 + 2);
12152               fn_len = QT_UINT8 (ref_data + 50);
12153               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12154                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12155               }
12156             } else {
12157               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12158                   ref_len);
12159             }
12160           } else if (ref_type == FOURCC_url_) {
12161             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12162           } else {
12163             GST_DEBUG_OBJECT (qtdemux,
12164                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12165                 GST_FOURCC_ARGS (ref_type));
12166           }
12167           if (ref.location != NULL) {
12168             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12169             redirects =
12170                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12171           } else {
12172             GST_WARNING_OBJECT (qtdemux,
12173                 "Failed to extract redirect location from rdrf atom");
12174           }
12175         } else {
12176           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12177         }
12178       }
12179
12180       /* look for others */
12181       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12182     }
12183
12184     if (redirects != NULL) {
12185       qtdemux_process_redirects (qtdemux, redirects);
12186     }
12187   }
12188   return TRUE;
12189 }
12190
12191 static GstTagList *
12192 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12193 {
12194   const gchar *fmt;
12195
12196   if (tags == NULL) {
12197     tags = gst_tag_list_new_empty ();
12198     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12199   }
12200
12201   if (qtdemux->major_brand == FOURCC_mjp2)
12202     fmt = "Motion JPEG 2000";
12203   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12204     fmt = "3GP";
12205   else if (qtdemux->major_brand == FOURCC_qt__)
12206     fmt = "Quicktime";
12207   else if (qtdemux->fragmented)
12208     fmt = "ISO fMP4";
12209   else
12210     fmt = "ISO MP4/M4A";
12211
12212   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12213       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12214
12215   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12216       fmt, NULL);
12217
12218   return tags;
12219 }
12220
12221 /* we have read th complete moov node now.
12222  * This function parses all of the relevant info, creates the traks and
12223  * prepares all data structures for playback
12224  */
12225 static gboolean
12226 qtdemux_parse_tree (GstQTDemux * qtdemux)
12227 {
12228   GNode *mvhd;
12229   GNode *trak;
12230   GNode *udta;
12231   GNode *mvex;
12232   GstClockTime duration;
12233   GNode *pssh;
12234   guint64 creation_time;
12235   GstDateTime *datetime = NULL;
12236   gint version;
12237
12238   /* make sure we have a usable taglist */
12239   if (!qtdemux->tag_list) {
12240     qtdemux->tag_list = gst_tag_list_new_empty ();
12241     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12242   } else {
12243     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12244   }
12245
12246   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12247   if (mvhd == NULL) {
12248     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12249     return qtdemux_parse_redirects (qtdemux);
12250   }
12251
12252   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12253   if (version == 1) {
12254     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12255     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12256     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12257   } else if (version == 0) {
12258     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12259     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12260     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12261   } else {
12262     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12263     return FALSE;
12264   }
12265
12266   /* Moving qt creation time (secs since 1904) to unix time */
12267   if (creation_time != 0) {
12268     /* Try to use epoch first as it should be faster and more commonly found */
12269     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12270       GTimeVal now;
12271
12272       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12273       /* some data cleansing sanity */
12274       g_get_current_time (&now);
12275       if (now.tv_sec + 24 * 3600 < creation_time) {
12276         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12277       } else {
12278         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12279       }
12280     } else {
12281       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12282       GDateTime *dt, *dt_local;
12283
12284       dt = g_date_time_add_seconds (base_dt, creation_time);
12285       dt_local = g_date_time_to_local (dt);
12286       datetime = gst_date_time_new_from_g_date_time (dt_local);
12287
12288       g_date_time_unref (base_dt);
12289       g_date_time_unref (dt);
12290     }
12291   }
12292   if (datetime) {
12293     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12294     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12295         datetime, NULL);
12296     gst_date_time_unref (datetime);
12297   }
12298
12299   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12300   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12301
12302   /* check for fragmented file and get some (default) data */
12303   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12304   if (mvex) {
12305     GNode *mehd;
12306     GstByteReader mehd_data;
12307
12308     /* let track parsing or anyone know weird stuff might happen ... */
12309     qtdemux->fragmented = TRUE;
12310
12311     /* compensate for total duration */
12312     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12313     if (mehd)
12314       qtdemux_parse_mehd (qtdemux, &mehd_data);
12315   }
12316
12317   /* set duration in the segment info */
12318   gst_qtdemux_get_duration (qtdemux, &duration);
12319   if (duration) {
12320     qtdemux->segment.duration = duration;
12321     /* also do not exceed duration; stop is set that way post seek anyway,
12322      * and segment activation falls back to duration,
12323      * whereas loop only checks stop, so let's align this here as well */
12324     qtdemux->segment.stop = duration;
12325   }
12326
12327   /* parse all traks */
12328   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12329   while (trak) {
12330     qtdemux_parse_trak (qtdemux, trak);
12331     /* iterate all siblings */
12332     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12333   }
12334
12335   if (!qtdemux->tag_list) {
12336     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12337     qtdemux->tag_list = gst_tag_list_new_empty ();
12338     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12339   } else {
12340     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12341   }
12342
12343   /* find tags */
12344   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12345   if (udta) {
12346     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12347   } else {
12348     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12349   }
12350
12351   /* maybe also some tags in meta box */
12352   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12353   if (udta) {
12354     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12355     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12356   } else {
12357     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12358   }
12359
12360   /* parse any protection system info */
12361   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12362   while (pssh) {
12363     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12364     qtdemux_parse_pssh (qtdemux, pssh);
12365     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12366   }
12367
12368   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12369
12370   return TRUE;
12371 }
12372
12373 /* taken from ffmpeg */
12374 static int
12375 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12376 {
12377   int count = 4;
12378   int len = 0;
12379
12380   while (count--) {
12381     int c;
12382
12383     if (ptr >= end)
12384       return -1;
12385
12386     c = *ptr++;
12387     len = (len << 7) | (c & 0x7f);
12388     if (!(c & 0x80))
12389       break;
12390   }
12391   *end_out = ptr;
12392   return len;
12393 }
12394
12395 /* this can change the codec originally present in @list */
12396 static void
12397 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12398     GNode * esds, GstTagList * list)
12399 {
12400   int len = QT_UINT32 (esds->data);
12401   guint8 *ptr = esds->data;
12402   guint8 *end = ptr + len;
12403   int tag;
12404   guint8 *data_ptr = NULL;
12405   int data_len = 0;
12406   guint8 object_type_id = 0;
12407   const char *codec_name = NULL;
12408   GstCaps *caps = NULL;
12409
12410   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12411   ptr += 8;
12412   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12413   ptr += 4;
12414   while (ptr + 1 < end) {
12415     tag = QT_UINT8 (ptr);
12416     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12417     ptr++;
12418     len = read_descr_size (ptr, end, &ptr);
12419     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12420
12421     /* Check the stated amount of data is available for reading */
12422     if (len < 0 || ptr + len > end)
12423       break;
12424
12425     switch (tag) {
12426       case ES_DESCRIPTOR_TAG:
12427         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12428         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12429         ptr += 3;
12430         break;
12431       case DECODER_CONFIG_DESC_TAG:{
12432         guint max_bitrate, avg_bitrate;
12433
12434         object_type_id = QT_UINT8 (ptr);
12435         max_bitrate = QT_UINT32 (ptr + 5);
12436         avg_bitrate = QT_UINT32 (ptr + 9);
12437         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12438         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12439         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12440         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12441         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12442         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12443           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12444               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12445         }
12446         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12447           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12448               avg_bitrate, NULL);
12449         }
12450         ptr += 13;
12451         break;
12452       }
12453       case DECODER_SPECIFIC_INFO_TAG:
12454         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12455         if (object_type_id == 0xe0 && len == 0x40) {
12456           guint8 *data;
12457           GstStructure *s;
12458           guint32 clut[16];
12459           gint i;
12460
12461           GST_DEBUG_OBJECT (qtdemux,
12462               "Have VOBSUB palette. Creating palette event");
12463           /* move to decConfigDescr data and read palette */
12464           data = ptr;
12465           for (i = 0; i < 16; i++) {
12466             clut[i] = QT_UINT32 (data);
12467             data += 4;
12468           }
12469
12470           s = gst_structure_new ("application/x-gst-dvd", "event",
12471               G_TYPE_STRING, "dvd-spu-clut-change",
12472               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12473               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12474               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12475               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12476               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12477               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12478               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12479               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12480               NULL);
12481
12482           /* store event and trigger custom processing */
12483           stream->pending_event =
12484               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12485         } else {
12486           /* Generic codec_data handler puts it on the caps */
12487           data_ptr = ptr;
12488           data_len = len;
12489         }
12490
12491         ptr += len;
12492         break;
12493       case SL_CONFIG_DESC_TAG:
12494         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12495         ptr += 1;
12496         break;
12497       default:
12498         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12499             tag);
12500         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12501         ptr += len;
12502         break;
12503     }
12504   }
12505
12506   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12507    * in use, and should also be used to override some other parameters for some
12508    * codecs. */
12509   switch (object_type_id) {
12510     case 0x20:                 /* MPEG-4 */
12511       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12512        * profile_and_level_indication */
12513       if (data_ptr != NULL && data_len >= 5 &&
12514           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12515         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12516             data_ptr + 4, data_len - 4);
12517       }
12518       break;                    /* Nothing special needed here */
12519     case 0x21:                 /* H.264 */
12520       codec_name = "H.264 / AVC";
12521       caps = gst_caps_new_simple ("video/x-h264",
12522           "stream-format", G_TYPE_STRING, "avc",
12523           "alignment", G_TYPE_STRING, "au", NULL);
12524       break;
12525     case 0x40:                 /* AAC (any) */
12526     case 0x66:                 /* AAC Main */
12527     case 0x67:                 /* AAC LC */
12528     case 0x68:                 /* AAC SSR */
12529       /* Override channels and rate based on the codec_data, as it's often
12530        * wrong. */
12531       /* Only do so for basic setup without HE-AAC extension */
12532       if (data_ptr && data_len == 2) {
12533         guint channels, rate;
12534
12535         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
12536         if (channels > 0)
12537           stream->n_channels = channels;
12538
12539         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
12540         if (rate > 0)
12541           stream->rate = rate;
12542       }
12543
12544       /* Set level and profile if possible */
12545       if (data_ptr != NULL && data_len >= 2) {
12546         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12547             data_ptr, data_len);
12548       }
12549       break;
12550     case 0x60:                 /* MPEG-2, various profiles */
12551     case 0x61:
12552     case 0x62:
12553     case 0x63:
12554     case 0x64:
12555     case 0x65:
12556       codec_name = "MPEG-2 video";
12557       caps = gst_caps_new_simple ("video/mpeg",
12558           "mpegversion", G_TYPE_INT, 2,
12559           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12560       break;
12561     case 0x69:                 /* MPEG-2 BC audio */
12562     case 0x6B:                 /* MPEG-1 audio */
12563       caps = gst_caps_new_simple ("audio/mpeg",
12564           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12565       codec_name = "MPEG-1 audio";
12566       break;
12567     case 0x6A:                 /* MPEG-1 */
12568       codec_name = "MPEG-1 video";
12569       caps = gst_caps_new_simple ("video/mpeg",
12570           "mpegversion", G_TYPE_INT, 1,
12571           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12572       break;
12573     case 0x6C:                 /* MJPEG */
12574       caps =
12575           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12576           NULL);
12577       codec_name = "Motion-JPEG";
12578       break;
12579     case 0x6D:                 /* PNG */
12580       caps =
12581           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12582           NULL);
12583       codec_name = "PNG still images";
12584       break;
12585     case 0x6E:                 /* JPEG2000 */
12586       codec_name = "JPEG-2000";
12587       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12588       break;
12589     case 0xA4:                 /* Dirac */
12590       codec_name = "Dirac";
12591       caps = gst_caps_new_empty_simple ("video/x-dirac");
12592       break;
12593     case 0xA5:                 /* AC3 */
12594       codec_name = "AC-3 audio";
12595       caps = gst_caps_new_simple ("audio/x-ac3",
12596           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12597       break;
12598     case 0xA9:                 /* AC3 */
12599       codec_name = "DTS audio";
12600       caps = gst_caps_new_simple ("audio/x-dts",
12601           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12602       break;
12603     case 0xE1:                 /* QCELP */
12604       /* QCELP, the codec_data is a riff tag (little endian) with
12605        * 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). */
12606       caps = gst_caps_new_empty_simple ("audio/qcelp");
12607       codec_name = "QCELP";
12608       break;
12609     default:
12610       break;
12611   }
12612
12613   /* If we have a replacement caps, then change our caps for this stream */
12614   if (caps) {
12615     gst_caps_unref (stream->caps);
12616     stream->caps = caps;
12617   }
12618
12619   if (codec_name && list)
12620     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12621         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12622
12623   /* Add the codec_data attribute to caps, if we have it */
12624   if (data_ptr) {
12625     GstBuffer *buffer;
12626
12627     buffer = gst_buffer_new_and_alloc (data_len);
12628     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12629
12630     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12631     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12632
12633     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12634         buffer, NULL);
12635     gst_buffer_unref (buffer);
12636   }
12637
12638 }
12639
12640 #define _codec(name) \
12641   do { \
12642     if (codec_name) { \
12643       *codec_name = g_strdup (name); \
12644     } \
12645   } while (0)
12646
12647 static GstCaps *
12648 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12649     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12650 {
12651   GstCaps *caps = NULL;
12652   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12653
12654   switch (fourcc) {
12655     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12656       _codec ("PNG still images");
12657       caps = gst_caps_new_empty_simple ("image/png");
12658       break;
12659     case FOURCC_jpeg:
12660       _codec ("JPEG still images");
12661       caps =
12662           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12663           NULL);
12664       break;
12665     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12666     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12667     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12668     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12669       _codec ("Motion-JPEG");
12670       caps =
12671           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12672           NULL);
12673       break;
12674     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12675       _codec ("Motion-JPEG format B");
12676       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12677       break;
12678     case FOURCC_mjp2:
12679       _codec ("JPEG-2000");
12680       /* override to what it should be according to spec, avoid palette_data */
12681       stream->bits_per_sample = 24;
12682       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12683       break;
12684     case FOURCC_SVQ3:
12685       _codec ("Sorensen video v.3");
12686       caps = gst_caps_new_simple ("video/x-svq",
12687           "svqversion", G_TYPE_INT, 3, NULL);
12688       break;
12689     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12690     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12691       _codec ("Sorensen video v.1");
12692       caps = gst_caps_new_simple ("video/x-svq",
12693           "svqversion", G_TYPE_INT, 1, NULL);
12694       break;
12695     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12696       caps = gst_caps_new_empty_simple ("video/x-raw");
12697       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12698       _codec ("Windows Raw RGB");
12699       break;
12700     case FOURCC_raw_:
12701     {
12702       guint16 bps;
12703
12704       bps = QT_UINT16 (stsd_data + 98);
12705       switch (bps) {
12706         case 15:
12707           format = GST_VIDEO_FORMAT_RGB15;
12708           break;
12709         case 16:
12710           format = GST_VIDEO_FORMAT_RGB16;
12711           break;
12712         case 24:
12713           format = GST_VIDEO_FORMAT_RGB;
12714           break;
12715         case 32:
12716           format = GST_VIDEO_FORMAT_ARGB;
12717           break;
12718         default:
12719           /* unknown */
12720           break;
12721       }
12722       break;
12723     }
12724     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12725       format = GST_VIDEO_FORMAT_I420;
12726       break;
12727     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12728     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12729       format = GST_VIDEO_FORMAT_I420;
12730       break;
12731     case FOURCC_2vuy:
12732     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12733       format = GST_VIDEO_FORMAT_UYVY;
12734       break;
12735     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12736       format = GST_VIDEO_FORMAT_v308;
12737       break;
12738     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12739       format = GST_VIDEO_FORMAT_v216;
12740       break;
12741     case FOURCC_v210:
12742       format = GST_VIDEO_FORMAT_v210;
12743       break;
12744     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12745       format = GST_VIDEO_FORMAT_r210;
12746       break;
12747       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12748          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12749          format = GST_VIDEO_FORMAT_v410;
12750          break;
12751        */
12752       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12753        * but different order than AYUV
12754        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12755        format = GST_VIDEO_FORMAT_v408;
12756        break;
12757        */
12758     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12759     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12760       _codec ("MPEG-1 video");
12761       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12762           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12763       break;
12764     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12765     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12766     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12767     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12768     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12769     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12770     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12771     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12772     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12773     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12774     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12775     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12776     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12777     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12778     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12779     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12780     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12781     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12782     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12783     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12784     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12785     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12786     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12787     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12788     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12789     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12790     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12791     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12792     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12793     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12794     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12795     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12796     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12797     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12798     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12799     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12800     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12801     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12802     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12803     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12804     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12805     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12806     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12807     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12808     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12809     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12810       _codec ("MPEG-2 video");
12811       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12812           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12813       break;
12814     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12815       _codec ("GIF still images");
12816       caps = gst_caps_new_empty_simple ("image/gif");
12817       break;
12818     case FOURCC_h263:
12819     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12820     case FOURCC_s263:
12821     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12822       _codec ("H.263");
12823       /* ffmpeg uses the height/width props, don't know why */
12824       caps = gst_caps_new_simple ("video/x-h263",
12825           "variant", G_TYPE_STRING, "itu", NULL);
12826       break;
12827     case FOURCC_mp4v:
12828     case FOURCC_MP4V:
12829       _codec ("MPEG-4 video");
12830       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12831           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12832       break;
12833     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12834     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12835       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12836       caps = gst_caps_new_simple ("video/x-msmpeg",
12837           "msmpegversion", G_TYPE_INT, 43, NULL);
12838       break;
12839     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12840       _codec ("DivX 3");
12841       caps = gst_caps_new_simple ("video/x-divx",
12842           "divxversion", G_TYPE_INT, 3, NULL);
12843       break;
12844     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12845     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12846       _codec ("DivX 4");
12847       caps = gst_caps_new_simple ("video/x-divx",
12848           "divxversion", G_TYPE_INT, 4, NULL);
12849       break;
12850     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12851       _codec ("DivX 5");
12852       caps = gst_caps_new_simple ("video/x-divx",
12853           "divxversion", G_TYPE_INT, 5, NULL);
12854       break;
12855
12856     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
12857       _codec ("FFV1");
12858       caps = gst_caps_new_simple ("video/x-ffv",
12859           "ffvversion", G_TYPE_INT, 1, NULL);
12860       break;
12861
12862     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12863     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12864     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12865     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12866     case FOURCC_FMP4:
12867     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12868       caps = gst_caps_new_simple ("video/mpeg",
12869           "mpegversion", G_TYPE_INT, 4, NULL);
12870       _codec ("MPEG-4");
12871       break;
12872
12873     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12874       _codec ("Cinepak");
12875       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12876       break;
12877     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12878       _codec ("Apple QuickDraw");
12879       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12880       break;
12881     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12882       _codec ("Apple video");
12883       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12884       break;
12885     case FOURCC_H264:
12886     case FOURCC_avc1:
12887       _codec ("H.264 / AVC");
12888       caps = gst_caps_new_simple ("video/x-h264",
12889           "stream-format", G_TYPE_STRING, "avc",
12890           "alignment", G_TYPE_STRING, "au", NULL);
12891       break;
12892     case FOURCC_avc3:
12893       _codec ("H.264 / AVC");
12894       caps = gst_caps_new_simple ("video/x-h264",
12895           "stream-format", G_TYPE_STRING, "avc3",
12896           "alignment", G_TYPE_STRING, "au", NULL);
12897       break;
12898     case FOURCC_H265:
12899     case FOURCC_hvc1:
12900       _codec ("H.265 / HEVC");
12901       caps = gst_caps_new_simple ("video/x-h265",
12902           "stream-format", G_TYPE_STRING, "hvc1",
12903           "alignment", G_TYPE_STRING, "au", NULL);
12904       break;
12905     case FOURCC_hev1:
12906       _codec ("H.265 / HEVC");
12907       caps = gst_caps_new_simple ("video/x-h265",
12908           "stream-format", G_TYPE_STRING, "hev1",
12909           "alignment", G_TYPE_STRING, "au", NULL);
12910       break;
12911     case FOURCC_rle_:
12912       _codec ("Run-length encoding");
12913       caps = gst_caps_new_simple ("video/x-rle",
12914           "layout", G_TYPE_STRING, "quicktime", NULL);
12915       break;
12916     case FOURCC_WRLE:
12917       _codec ("Run-length encoding");
12918       caps = gst_caps_new_simple ("video/x-rle",
12919           "layout", G_TYPE_STRING, "microsoft", NULL);
12920       break;
12921     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12922     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12923       _codec ("Indeo Video 3");
12924       caps = gst_caps_new_simple ("video/x-indeo",
12925           "indeoversion", G_TYPE_INT, 3, NULL);
12926       break;
12927     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12928     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12929       _codec ("Intel Video 4");
12930       caps = gst_caps_new_simple ("video/x-indeo",
12931           "indeoversion", G_TYPE_INT, 4, NULL);
12932       break;
12933     case FOURCC_dvcp:
12934     case FOURCC_dvc_:
12935     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12936     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12937     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12938     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12939     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12940     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12941       _codec ("DV Video");
12942       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12943           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12944       break;
12945     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
12946     case FOURCC_dv5p:          /* DVCPRO50 PAL */
12947       _codec ("DVCPro50 Video");
12948       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12949           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12950       break;
12951     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12952     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12953       _codec ("DVCProHD Video");
12954       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12955           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12956       break;
12957     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12958       _codec ("Apple Graphics (SMC)");
12959       caps = gst_caps_new_empty_simple ("video/x-smc");
12960       break;
12961     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12962       _codec ("VP3");
12963       caps = gst_caps_new_empty_simple ("video/x-vp3");
12964       break;
12965     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12966       _codec ("VP6 Flash");
12967       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12968       break;
12969     case FOURCC_XiTh:
12970       _codec ("Theora");
12971       caps = gst_caps_new_empty_simple ("video/x-theora");
12972       /* theora uses one byte of padding in the data stream because it does not
12973        * allow 0 sized packets while theora does */
12974       stream->padding = 1;
12975       break;
12976     case FOURCC_drac:
12977       _codec ("Dirac");
12978       caps = gst_caps_new_empty_simple ("video/x-dirac");
12979       break;
12980     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
12981       _codec ("TIFF still images");
12982       caps = gst_caps_new_empty_simple ("image/tiff");
12983       break;
12984     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
12985       _codec ("Apple Intermediate Codec");
12986       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
12987       break;
12988     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
12989       _codec ("AVID DNxHD");
12990       caps = gst_caps_from_string ("video/x-dnxhd");
12991       break;
12992     case FOURCC_VP80:
12993       _codec ("On2 VP8");
12994       caps = gst_caps_from_string ("video/x-vp8");
12995       break;
12996     case FOURCC_apcs:
12997       _codec ("Apple ProRes LT");
12998       caps =
12999           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13000           NULL);
13001       break;
13002     case FOURCC_apch:
13003       _codec ("Apple ProRes HQ");
13004       caps =
13005           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13006           NULL);
13007       break;
13008     case FOURCC_apcn:
13009       _codec ("Apple ProRes");
13010       caps =
13011           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13012           "standard", NULL);
13013       break;
13014     case FOURCC_apco:
13015       _codec ("Apple ProRes Proxy");
13016       caps =
13017           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13018           "proxy", NULL);
13019       break;
13020     case FOURCC_ap4h:
13021       _codec ("Apple ProRes 4444");
13022       caps =
13023           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13024           "4444", NULL);
13025       break;
13026     case FOURCC_vc_1:
13027     case FOURCC_ovc1:
13028       _codec ("VC-1");
13029       caps = gst_caps_new_simple ("video/x-wmv",
13030           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13031       break;
13032     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13033     default:
13034     {
13035       char *s, fourstr[5];
13036
13037       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13038       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
13039       caps = gst_caps_new_empty_simple (s);
13040       g_free (s);
13041       break;
13042     }
13043   }
13044
13045   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13046     GstVideoInfo info;
13047
13048     gst_video_info_init (&info);
13049     gst_video_info_set_format (&info, format, stream->width, stream->height);
13050
13051     caps = gst_video_info_to_caps (&info);
13052     *codec_name = gst_pb_utils_get_codec_description (caps);
13053
13054     /* enable clipping for raw video streams */
13055     stream->need_clip = TRUE;
13056   }
13057
13058   return caps;
13059 }
13060
13061 static GstCaps *
13062 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13063     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13064 {
13065   GstCaps *caps;
13066   const GstStructure *s;
13067   const gchar *name;
13068   gint endian = 0;
13069   GstAudioFormat format = 0;
13070   gint depth;
13071
13072   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13073
13074   depth = stream->bytes_per_packet * 8;
13075
13076   switch (fourcc) {
13077     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13078     case FOURCC_raw_:
13079       /* 8-bit audio is unsigned */
13080       if (depth == 8)
13081         format = GST_AUDIO_FORMAT_U8;
13082       /* otherwise it's signed and big-endian just like 'twos' */
13083     case FOURCC_twos:
13084       endian = G_BIG_ENDIAN;
13085       /* fall-through */
13086     case FOURCC_sowt:
13087     {
13088       gchar *str;
13089
13090       if (!endian)
13091         endian = G_LITTLE_ENDIAN;
13092
13093       if (!format)
13094         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13095
13096       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13097       _codec (str);
13098       g_free (str);
13099
13100       caps = gst_caps_new_simple ("audio/x-raw",
13101           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13102           "layout", G_TYPE_STRING, "interleaved", NULL);
13103       break;
13104     }
13105     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13106       _codec ("Raw 64-bit floating-point audio");
13107       caps = gst_caps_new_simple ("audio/x-raw",
13108           "format", G_TYPE_STRING, "F64BE",
13109           "layout", G_TYPE_STRING, "interleaved", NULL);
13110       break;
13111     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13112       _codec ("Raw 32-bit floating-point audio");
13113       caps = gst_caps_new_simple ("audio/x-raw",
13114           "format", G_TYPE_STRING, "F32BE",
13115           "layout", G_TYPE_STRING, "interleaved", NULL);
13116       break;
13117     case FOURCC_in24:
13118       _codec ("Raw 24-bit PCM audio");
13119       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13120        * endian later */
13121       caps = gst_caps_new_simple ("audio/x-raw",
13122           "format", G_TYPE_STRING, "S24BE",
13123           "layout", G_TYPE_STRING, "interleaved", NULL);
13124       break;
13125     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13126       _codec ("Raw 32-bit PCM audio");
13127       caps = gst_caps_new_simple ("audio/x-raw",
13128           "format", G_TYPE_STRING, "S32BE",
13129           "layout", G_TYPE_STRING, "interleaved", NULL);
13130       break;
13131     case FOURCC_ulaw:
13132       _codec ("Mu-law audio");
13133       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13134       break;
13135     case FOURCC_alaw:
13136       _codec ("A-law audio");
13137       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13138       break;
13139     case 0x0200736d:
13140     case 0x6d730002:
13141       _codec ("Microsoft ADPCM");
13142       /* Microsoft ADPCM-ACM code 2 */
13143       caps = gst_caps_new_simple ("audio/x-adpcm",
13144           "layout", G_TYPE_STRING, "microsoft", NULL);
13145       break;
13146     case 0x1100736d:
13147     case 0x6d730011:
13148       _codec ("DVI/IMA ADPCM");
13149       caps = gst_caps_new_simple ("audio/x-adpcm",
13150           "layout", G_TYPE_STRING, "dvi", NULL);
13151       break;
13152     case 0x1700736d:
13153     case 0x6d730017:
13154       _codec ("DVI/Intel IMA ADPCM");
13155       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13156       caps = gst_caps_new_simple ("audio/x-adpcm",
13157           "layout", G_TYPE_STRING, "quicktime", NULL);
13158       break;
13159     case 0x5500736d:
13160     case 0x6d730055:
13161       /* MPEG layer 3, CBR only (pre QT4.1) */
13162     case FOURCC__mp3:
13163       _codec ("MPEG-1 layer 3");
13164       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13165       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13166           "mpegversion", G_TYPE_INT, 1, NULL);
13167       break;
13168     case 0x20736d:
13169     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13170       _codec ("EAC-3 audio");
13171       caps = gst_caps_new_simple ("audio/x-eac3",
13172           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13173       stream->sampled = TRUE;
13174       break;
13175     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13176     case FOURCC_ac_3:
13177       _codec ("AC-3 audio");
13178       caps = gst_caps_new_simple ("audio/x-ac3",
13179           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13180       stream->sampled = TRUE;
13181       break;
13182     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13183     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13184       _codec ("DTS audio");
13185       caps = gst_caps_new_simple ("audio/x-dts",
13186           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13187       stream->sampled = TRUE;
13188       break;
13189     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13190     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13191       _codec ("DTS-HD audio");
13192       caps = gst_caps_new_simple ("audio/x-dts",
13193           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13194       stream->sampled = TRUE;
13195       break;
13196     case FOURCC_MAC3:
13197       _codec ("MACE-3");
13198       caps = gst_caps_new_simple ("audio/x-mace",
13199           "maceversion", G_TYPE_INT, 3, NULL);
13200       break;
13201     case FOURCC_MAC6:
13202       _codec ("MACE-6");
13203       caps = gst_caps_new_simple ("audio/x-mace",
13204           "maceversion", G_TYPE_INT, 6, NULL);
13205       break;
13206     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13207       /* ogg/vorbis */
13208       caps = gst_caps_new_empty_simple ("application/ogg");
13209       break;
13210     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13211       _codec ("DV audio");
13212       caps = gst_caps_new_empty_simple ("audio/x-dv");
13213       break;
13214     case FOURCC_mp4a:
13215       _codec ("MPEG-4 AAC audio");
13216       caps = gst_caps_new_simple ("audio/mpeg",
13217           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13218           "stream-format", G_TYPE_STRING, "raw", NULL);
13219       break;
13220     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13221       _codec ("QDesign Music");
13222       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13223       break;
13224     case FOURCC_QDM2:
13225       _codec ("QDesign Music v.2");
13226       /* FIXME: QDesign music version 2 (no constant) */
13227       if (FALSE && data) {
13228         caps = gst_caps_new_simple ("audio/x-qdm2",
13229             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13230             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13231             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13232       } else {
13233         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13234       }
13235       break;
13236     case FOURCC_agsm:
13237       _codec ("GSM audio");
13238       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13239       break;
13240     case FOURCC_samr:
13241       _codec ("AMR audio");
13242       caps = gst_caps_new_empty_simple ("audio/AMR");
13243       break;
13244     case FOURCC_sawb:
13245       _codec ("AMR-WB audio");
13246       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13247       break;
13248     case FOURCC_ima4:
13249       _codec ("Quicktime IMA ADPCM");
13250       caps = gst_caps_new_simple ("audio/x-adpcm",
13251           "layout", G_TYPE_STRING, "quicktime", NULL);
13252       break;
13253     case FOURCC_alac:
13254       _codec ("Apple lossless audio");
13255       caps = gst_caps_new_empty_simple ("audio/x-alac");
13256       break;
13257     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13258       _codec ("QualComm PureVoice");
13259       caps = gst_caps_from_string ("audio/qcelp");
13260       break;
13261     case FOURCC_wma_:
13262     case FOURCC_owma:
13263       _codec ("WMA");
13264       caps = gst_caps_new_empty_simple ("audio/x-wma");
13265       break;
13266     case FOURCC_opus:
13267       _codec ("Opus");
13268       caps = gst_caps_new_empty_simple ("audio/x-opus");
13269       break;
13270     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13271     {
13272       guint32 flags = 0;
13273       guint32 depth = 0;
13274       guint32 width = 0;
13275       GstAudioFormat format;
13276       enum
13277       {
13278         FLAG_IS_FLOAT = 0x1,
13279         FLAG_IS_BIG_ENDIAN = 0x2,
13280         FLAG_IS_SIGNED = 0x4,
13281         FLAG_IS_PACKED = 0x8,
13282         FLAG_IS_ALIGNED_HIGH = 0x10,
13283         FLAG_IS_NON_INTERLEAVED = 0x20
13284       };
13285       _codec ("Raw LPCM audio");
13286
13287       if (data && len >= 56) {
13288         depth = QT_UINT32 (data + 40);
13289         flags = QT_UINT32 (data + 44);
13290         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13291       }
13292       if ((flags & FLAG_IS_FLOAT) == 0) {
13293         if (depth == 0)
13294           depth = 16;
13295         if (width == 0)
13296           width = 16;
13297         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13298             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13299             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13300         caps = gst_caps_new_simple ("audio/x-raw",
13301             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13302             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13303             "non-interleaved" : "interleaved", NULL);
13304       } else {
13305         if (width == 0)
13306           width = 32;
13307         if (width == 64) {
13308           if (flags & FLAG_IS_BIG_ENDIAN)
13309             format = GST_AUDIO_FORMAT_F64BE;
13310           else
13311             format = GST_AUDIO_FORMAT_F64LE;
13312         } else {
13313           if (flags & FLAG_IS_BIG_ENDIAN)
13314             format = GST_AUDIO_FORMAT_F32BE;
13315           else
13316             format = GST_AUDIO_FORMAT_F32LE;
13317         }
13318         caps = gst_caps_new_simple ("audio/x-raw",
13319             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13320             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13321             "non-interleaved" : "interleaved", NULL);
13322       }
13323       break;
13324     }
13325     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
13326       /* ? */
13327     default:
13328     {
13329       char *s, fourstr[5];
13330
13331       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13332       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
13333       caps = gst_caps_new_empty_simple (s);
13334       g_free (s);
13335       break;
13336     }
13337   }
13338
13339   if (caps) {
13340     GstCaps *templ_caps =
13341         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
13342     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
13343     gst_caps_unref (caps);
13344     gst_caps_unref (templ_caps);
13345     caps = intersection;
13346   }
13347
13348   /* enable clipping for raw audio streams */
13349   s = gst_caps_get_structure (caps, 0);
13350   name = gst_structure_get_name (s);
13351   if (g_str_has_prefix (name, "audio/x-raw")) {
13352     stream->need_clip = TRUE;
13353     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
13354     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
13355   }
13356   return caps;
13357 }
13358
13359 static GstCaps *
13360 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13361     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13362 {
13363   GstCaps *caps;
13364
13365   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13366
13367   switch (fourcc) {
13368     case FOURCC_mp4s:
13369       _codec ("DVD subtitle");
13370       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
13371       stream->need_process = TRUE;
13372       break;
13373     case FOURCC_text:
13374       _codec ("Quicktime timed text");
13375       goto text;
13376     case FOURCC_tx3g:
13377       _codec ("3GPP timed text");
13378     text:
13379       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
13380           "utf8", NULL);
13381       /* actual text piece needs to be extracted */
13382       stream->need_process = TRUE;
13383       break;
13384     case FOURCC_stpp:
13385       _codec ("XML subtitles");
13386       caps = gst_caps_new_empty_simple ("application/ttml+xml");
13387       break;
13388     default:
13389     {
13390       char *s, fourstr[5];
13391
13392       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13393       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
13394       caps = gst_caps_new_empty_simple (s);
13395       g_free (s);
13396       break;
13397     }
13398   }
13399   return caps;
13400 }
13401
13402 static GstCaps *
13403 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13404     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13405 {
13406   GstCaps *caps;
13407
13408   switch (fourcc) {
13409     case FOURCC_m1v:
13410       _codec ("MPEG 1 video");
13411       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13412           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13413       break;
13414     default:
13415       caps = NULL;
13416       break;
13417   }
13418   return caps;
13419 }
13420
13421 static void
13422 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
13423     const gchar * system_id)
13424 {
13425   gint i;
13426
13427   if (!qtdemux->protection_system_ids)
13428     qtdemux->protection_system_ids =
13429         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13430   /* Check whether we already have an entry for this system ID. */
13431   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13432     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13433     if (g_ascii_strcasecmp (system_id, id) == 0) {
13434       return;
13435     }
13436   }
13437   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13438   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13439           -1));
13440 }