qtdemux: Add/Fix comments on the various structure variables
[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 _QtDemuxSegment QtDemuxSegment;
101 typedef struct _QtDemuxSample QtDemuxSample;
102
103 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
104
105 struct _QtDemuxSample
106 {
107   guint32 size;
108   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
109   guint64 offset;
110   guint64 timestamp;            /* DTS In mov time */
111   guint32 duration;             /* In mov time */
112   gboolean keyframe;            /* TRUE when this packet is a keyframe */
113 };
114
115 /* Macros for converting to/from timescale */
116 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
117 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
118
119 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
120 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
121
122 /* timestamp is the DTS */
123 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
124 /* timestamp + offset is the PTS */
125 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
126 /* timestamp + duration - dts is the duration */
127 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
128
129 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
130
131 /*
132  * Quicktime has tracks and segments. A track is a continuous piece of
133  * multimedia content. The track is not always played from start to finish but
134  * instead, pieces of the track are 'cut out' and played in sequence. This is
135  * what the segments do.
136  *
137  * Inside the track we have keyframes (K) and delta frames. The track has its
138  * own timing, which starts from 0 and extends to end. The position in the track
139  * is called the media_time.
140  *
141  * The segments now describe the pieces that should be played from this track
142  * and are basically tuples of media_time/duration/rate entries. We can have
143  * multiple segments and they are all played after one another. An example:
144  *
145  * segment 1: media_time: 1 second, duration: 1 second, rate 1
146  * segment 2: media_time: 3 second, duration: 2 second, rate 2
147  *
148  * To correctly play back this track, one must play: 1 second of media starting
149  * from media_time 1 followed by 2 seconds of media starting from media_time 3
150  * at a rate of 2.
151  *
152  * Each of the segments will be played at a specific time, the first segment at
153  * time 0, the second one after the duration of the first one, etc.. Note that
154  * the time in resulting playback is not identical to the media_time of the
155  * track anymore.
156  *
157  * Visually, assuming the track has 4 second of media_time:
158  *
159  *                (a)                   (b)          (c)              (d)
160  *         .-----------------------------------------------------------.
161  * track:  | K.....K.........K........K.......K.......K...........K... |
162  *         '-----------------------------------------------------------'
163  *         0              1              2              3              4
164  *           .------------^              ^   .----------^              ^
165  *          /              .-------------'  /       .------------------'
166  *         /              /          .-----'       /
167  *         .--------------.         .--------------.
168  *         | segment 1    |         | segment 2    |
169  *         '--------------'         '--------------'
170  *
171  * The challenge here is to cut out the right pieces of the track for each of
172  * the playback segments. This fortunately can easily be done with the SEGMENT
173  * events of GStreamer.
174  *
175  * For playback of segment 1, we need to provide the decoder with the keyframe
176  * (a), in the above figure, but we must instruct it only to output the decoded
177  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
178  * position set to the time of the segment: 0.
179  *
180  * We then proceed to push data from keyframe (a) to frame (b). The decoder
181  * decodes but clips all before media_time 1.
182  *
183  * After finishing a segment, we push out a new SEGMENT event with the clipping
184  * boundaries of the new data.
185  *
186  * This is a good usecase for the GStreamer accumulated SEGMENT events.
187  */
188
189 struct _QtDemuxSegment
190 {
191   /* global time and duration, all gst time */
192   GstClockTime time;
193   GstClockTime stop_time;
194   GstClockTime duration;
195   /* media time of trak, all gst time */
196   GstClockTime media_start;
197   GstClockTime media_stop;
198   gdouble rate;
199   /* Media start time in trak timescale units */
200   guint32 trak_media_start;
201 };
202
203 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
204
205 /* Used with fragmented MP4 files (mfra atom) */
206 typedef struct
207 {
208   GstClockTime ts;
209   guint64 moof_offset;
210 } QtDemuxRandomAccessEntry;
211
212 struct _QtDemuxStream
213 {
214   GstPad *pad;
215
216   /* stream type */
217   guint32 subtype;
218   GstCaps *caps;
219   guint32 fourcc;
220   gboolean sparse;
221
222   gboolean new_caps;            /* If TRUE, caps need to be generated (by
223                                  * calling _configure_stream()) This happens
224                                  * for MSS and fragmented streams */
225
226   gboolean new_stream;          /* signals that a stream_start is required */
227   gboolean on_keyframe;         /* if this stream last pushed buffer was a
228                                  * keyframe. This is important to identify
229                                  * where to stop pushing buffers after a
230                                  * segment stop time */
231
232   /* if the stream has a redirect URI in its headers, we store it here */
233   gchar *redirect_uri;
234
235   /* track id */
236   guint track_id;
237
238   /* duration/scale */
239   guint64 duration;             /* in timescale units */
240   guint32 timescale;
241
242   /* language */
243   gchar lang_id[4];             /* ISO 639-2T language code */
244
245   /* our samples */
246   guint32 n_samples;
247   QtDemuxSample *samples;
248   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
249   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
250                                    the framerate */
251   guint32 n_samples_moof;       /* sample count in a moof */
252   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
253                                  * the framerate of fragmented format stream */
254
255   guint32 offset_in_sample;     /* Offset in the current sample, used for
256                                  * streams which have got exceedingly big
257                                  * sample size (such as 24s of raw audio).
258                                  * Only used when max_buffer_size is non-NULL */
259   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
260                                  * Currently only set for raw audio streams*/
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
2084       /* some debug output */
2085       gst_event_copy_segment (event, &segment);
2086       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2087           &segment);
2088
2089       /* erase any previously set segment */
2090       gst_event_replace (&demux->pending_newsegment, NULL);
2091
2092       if (segment.format == GST_FORMAT_TIME) {
2093         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2094         gst_event_replace (&demux->pending_newsegment, event);
2095         demux->upstream_format_is_time = TRUE;
2096       } else {
2097         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2098             "not in time format");
2099
2100         /* chain will send initial newsegment after pads have been added */
2101         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2102           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2103           goto exit;
2104         }
2105       }
2106
2107       /* check if this matches a time seek we received previously
2108        * FIXME for backwards compatibility reasons we use the
2109        * seek_offset here to compare. In the future we might want to
2110        * change this to use the seqnum as it uniquely should identify
2111        * the segment that corresponds to the seek. */
2112       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2113           ", received segment offset %" G_GINT64_FORMAT,
2114           demux->seek_offset, segment.start);
2115       if (segment.format == GST_FORMAT_BYTES
2116           && demux->seek_offset == segment.start) {
2117         GST_OBJECT_LOCK (demux);
2118         offset = segment.start;
2119
2120         segment.format = GST_FORMAT_TIME;
2121         segment.start = demux->push_seek_start;
2122         segment.stop = demux->push_seek_stop;
2123         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2124             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2125             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2126         GST_OBJECT_UNLOCK (demux);
2127       }
2128
2129       /* we only expect a BYTE segment, e.g. following a seek */
2130       if (segment.format == GST_FORMAT_BYTES) {
2131         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2132           offset = segment.start;
2133
2134           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2135               NULL, (gint64 *) & segment.start);
2136           if ((gint64) segment.start < 0)
2137             segment.start = 0;
2138         }
2139         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2140           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2141               NULL, (gint64 *) & segment.stop);
2142           /* keyframe seeking should already arrange for start >= stop,
2143            * but make sure in other rare cases */
2144           segment.stop = MAX (segment.stop, segment.start);
2145         }
2146       } else if (segment.format == GST_FORMAT_TIME) {
2147         /* push all data on the adapter before starting this
2148          * new segment */
2149         gst_qtdemux_process_adapter (demux, TRUE);
2150       } else {
2151         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2152         goto exit;
2153       }
2154
2155       /* accept upstream's notion of segment and distribute along */
2156       segment.format = GST_FORMAT_TIME;
2157       segment.position = segment.time = segment.start;
2158       segment.duration = demux->segment.duration;
2159       segment.base = gst_segment_to_running_time (&demux->segment,
2160           GST_FORMAT_TIME, demux->segment.position);
2161
2162       gst_segment_copy_into (&segment, &demux->segment);
2163       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2164
2165       /* map segment to internal qt segments and push on each stream */
2166       if (demux->n_streams) {
2167         if (demux->fragmented) {
2168           GstEvent *segment_event = gst_event_new_segment (&segment);
2169
2170           gst_event_replace (&demux->pending_newsegment, NULL);
2171           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2172           gst_qtdemux_push_event (demux, segment_event);
2173         } else {
2174           gst_event_replace (&demux->pending_newsegment, NULL);
2175           gst_qtdemux_map_and_push_segments (demux, &segment);
2176         }
2177       }
2178
2179       /* clear leftover in current segment, if any */
2180       gst_adapter_clear (demux->adapter);
2181
2182       /* set up streaming thread */
2183       demux->offset = offset;
2184       if (demux->upstream_format_is_time) {
2185         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2186             "set values to restart reading from a new atom");
2187         demux->neededbytes = 16;
2188         demux->todrop = 0;
2189       } else {
2190         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2191             NULL);
2192         if (stream) {
2193           demux->todrop = stream->samples[idx].offset - offset;
2194           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2195         } else {
2196           /* set up for EOS */
2197           demux->neededbytes = -1;
2198           demux->todrop = 0;
2199         }
2200       }
2201     exit:
2202       gst_event_unref (event);
2203       res = TRUE;
2204       goto drop;
2205     }
2206     case GST_EVENT_FLUSH_START:
2207     {
2208       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2209         gst_event_unref (event);
2210         goto drop;
2211       }
2212       break;
2213     }
2214     case GST_EVENT_FLUSH_STOP:
2215     {
2216       guint64 dur;
2217
2218       dur = demux->segment.duration;
2219       gst_qtdemux_reset (demux, FALSE);
2220       demux->segment.duration = dur;
2221
2222       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2223         gst_event_unref (event);
2224         goto drop;
2225       }
2226       break;
2227     }
2228     case GST_EVENT_EOS:
2229       /* If we are in push mode, and get an EOS before we've seen any streams,
2230        * then error out - we have nowhere to send the EOS */
2231       if (!demux->pullbased) {
2232         gint i;
2233         gboolean has_valid_stream = FALSE;
2234         for (i = 0; i < demux->n_streams; i++) {
2235           if (demux->streams[i]->pad != NULL) {
2236             has_valid_stream = TRUE;
2237             break;
2238           }
2239         }
2240         if (!has_valid_stream)
2241           gst_qtdemux_post_no_playable_stream_error (demux);
2242         else {
2243           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2244               (guint) gst_adapter_available (demux->adapter));
2245           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2246             res = FALSE;
2247           }
2248         }
2249       }
2250       break;
2251     case GST_EVENT_CAPS:{
2252       GstCaps *caps = NULL;
2253
2254       gst_event_parse_caps (event, &caps);
2255       gst_qtdemux_setcaps (demux, caps);
2256       res = TRUE;
2257       gst_event_unref (event);
2258       goto drop;
2259     }
2260     case GST_EVENT_PROTECTION:
2261     {
2262       const gchar *system_id = NULL;
2263
2264       gst_event_parse_protection (event, &system_id, NULL, NULL);
2265       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2266           system_id);
2267       gst_qtdemux_append_protection_system_id (demux, system_id);
2268       /* save the event for later, for source pads that have not been created */
2269       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2270       /* send it to all pads that already exist */
2271       gst_qtdemux_push_event (demux, event);
2272       res = TRUE;
2273       goto drop;
2274     }
2275     default:
2276       break;
2277   }
2278
2279   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2280
2281 drop:
2282   return res;
2283 }
2284
2285 #if 0
2286 static void
2287 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2288 {
2289   GstQTDemux *demux = GST_QTDEMUX (element);
2290
2291   GST_OBJECT_LOCK (demux);
2292   if (demux->element_index)
2293     gst_object_unref (demux->element_index);
2294   if (index) {
2295     demux->element_index = gst_object_ref (index);
2296   } else {
2297     demux->element_index = NULL;
2298   }
2299   GST_OBJECT_UNLOCK (demux);
2300   /* object lock might be taken again */
2301   if (index)
2302     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2303   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2304       demux->element_index, demux->index_id);
2305 }
2306
2307 static GstIndex *
2308 gst_qtdemux_get_index (GstElement * element)
2309 {
2310   GstIndex *result = NULL;
2311   GstQTDemux *demux = GST_QTDEMUX (element);
2312
2313   GST_OBJECT_LOCK (demux);
2314   if (demux->element_index)
2315     result = gst_object_ref (demux->element_index);
2316   GST_OBJECT_UNLOCK (demux);
2317
2318   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2319
2320   return result;
2321 }
2322 #endif
2323
2324 static void
2325 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2326 {
2327   g_free ((gpointer) stream->stco.data);
2328   stream->stco.data = NULL;
2329   g_free ((gpointer) stream->stsz.data);
2330   stream->stsz.data = NULL;
2331   g_free ((gpointer) stream->stsc.data);
2332   stream->stsc.data = NULL;
2333   g_free ((gpointer) stream->stts.data);
2334   stream->stts.data = NULL;
2335   g_free ((gpointer) stream->stss.data);
2336   stream->stss.data = NULL;
2337   g_free ((gpointer) stream->stps.data);
2338   stream->stps.data = NULL;
2339   g_free ((gpointer) stream->ctts.data);
2340   stream->ctts.data = NULL;
2341 }
2342
2343 static void
2344 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2345     QtDemuxStream * stream)
2346 {
2347   g_free (stream->segments);
2348   stream->segments = NULL;
2349   stream->segment_index = -1;
2350   stream->accumulated_base = 0;
2351 }
2352
2353 static void
2354 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2355     QtDemuxStream * stream)
2356 {
2357   g_free (stream->samples);
2358   stream->samples = NULL;
2359   gst_qtdemux_stbl_free (stream);
2360
2361   /* fragments */
2362   g_free (stream->ra_entries);
2363   stream->ra_entries = NULL;
2364   stream->n_ra_entries = 0;
2365
2366   stream->sample_index = -1;
2367   stream->stbl_index = -1;
2368   stream->n_samples = 0;
2369   stream->time_position = 0;
2370
2371   stream->n_samples_moof = 0;
2372   stream->duration_moof = 0;
2373 }
2374
2375 static void
2376 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2377 {
2378   if (stream->allocator)
2379     gst_object_unref (stream->allocator);
2380   while (stream->buffers) {
2381     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2382     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2383   }
2384   if (stream->rgb8_palette) {
2385     gst_memory_unref (stream->rgb8_palette);
2386     stream->rgb8_palette = NULL;
2387   }
2388
2389   if (stream->pending_tags)
2390     gst_tag_list_unref (stream->pending_tags);
2391   stream->pending_tags = NULL;
2392   g_free (stream->redirect_uri);
2393   stream->redirect_uri = NULL;
2394   stream->sent_eos = FALSE;
2395   stream->sparse = FALSE;
2396   stream->protected = FALSE;
2397   if (stream->protection_scheme_info) {
2398     if (stream->protection_scheme_type == FOURCC_cenc) {
2399       QtDemuxCencSampleSetInfo *info =
2400           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2401       if (info->default_properties)
2402         gst_structure_free (info->default_properties);
2403       if (info->crypto_info)
2404         g_ptr_array_free (info->crypto_info, TRUE);
2405     }
2406     g_free (stream->protection_scheme_info);
2407     stream->protection_scheme_info = NULL;
2408   }
2409   stream->protection_scheme_type = 0;
2410   stream->protection_scheme_version = 0;
2411   g_queue_foreach (&stream->protection_scheme_event_queue,
2412       (GFunc) gst_event_unref, NULL);
2413   g_queue_clear (&stream->protection_scheme_event_queue);
2414   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2415   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2416 }
2417
2418 static void
2419 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2420 {
2421   gst_qtdemux_stream_clear (qtdemux, stream);
2422   if (stream->caps)
2423     gst_caps_unref (stream->caps);
2424   stream->caps = NULL;
2425   if (stream->pad) {
2426     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2427     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2428   }
2429   g_free (stream);
2430 }
2431
2432 static void
2433 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2434 {
2435   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2436
2437   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2438   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2439   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2440   qtdemux->n_streams--;
2441 }
2442
2443 static GstStateChangeReturn
2444 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2445 {
2446   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2447   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2448
2449   switch (transition) {
2450     case GST_STATE_CHANGE_PAUSED_TO_READY:
2451       break;
2452     default:
2453       break;
2454   }
2455
2456   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2457
2458   switch (transition) {
2459     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2460       gst_qtdemux_reset (qtdemux, TRUE);
2461       break;
2462     }
2463     default:
2464       break;
2465   }
2466
2467   return result;
2468 }
2469
2470 static void
2471 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2472 {
2473   /* counts as header data */
2474   qtdemux->header_size += length;
2475
2476   /* only consider at least a sufficiently complete ftyp atom */
2477   if (length >= 20) {
2478     GstBuffer *buf;
2479
2480     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2481     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2482         GST_FOURCC_ARGS (qtdemux->major_brand));
2483     if (qtdemux->comp_brands)
2484       gst_buffer_unref (qtdemux->comp_brands);
2485     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2486     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2487   }
2488 }
2489
2490 static void
2491 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2492     GstTagList * xmptaglist)
2493 {
2494   /* Strip out bogus fields */
2495   if (xmptaglist) {
2496     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2497       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2498       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2499     } else {
2500       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2501     }
2502
2503     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2504
2505     /* prioritize native tags using _KEEP mode */
2506     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2507     gst_tag_list_unref (xmptaglist);
2508   }
2509 }
2510
2511 static void
2512 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2513     guint offset)
2514 {
2515   GstByteReader br;
2516   guint8 version;
2517   guint32 flags = 0;
2518   guint i;
2519   guint8 iv_size = 8;
2520   QtDemuxStream *stream;
2521   GstStructure *structure;
2522   QtDemuxCencSampleSetInfo *ss_info = NULL;
2523   const gchar *system_id;
2524   gboolean uses_sub_sample_encryption = FALSE;
2525
2526   if (qtdemux->n_streams == 0)
2527     return;
2528
2529   stream = qtdemux->streams[0];
2530
2531   structure = gst_caps_get_structure (stream->caps, 0);
2532   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2533     GST_WARNING_OBJECT (qtdemux,
2534         "Attempting PIFF box parsing on an unencrypted stream.");
2535     return;
2536   }
2537
2538   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2539       G_TYPE_STRING, &system_id, NULL);
2540   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2541
2542   stream->protected = TRUE;
2543   stream->protection_scheme_type = FOURCC_cenc;
2544
2545   if (!stream->protection_scheme_info)
2546     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2547
2548   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2549
2550   if (ss_info->default_properties)
2551     gst_structure_free (ss_info->default_properties);
2552
2553   ss_info->default_properties =
2554       gst_structure_new ("application/x-cenc",
2555       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2556
2557   if (ss_info->crypto_info) {
2558     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2559     g_ptr_array_free (ss_info->crypto_info, TRUE);
2560     ss_info->crypto_info = NULL;
2561   }
2562
2563   /* skip UUID */
2564   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2565
2566   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2567     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2568     return;
2569   }
2570
2571   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2572     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2573     return;
2574   }
2575
2576   if ((flags & 0x000001)) {
2577     guint32 algorithm_id = 0;
2578     const guint8 *kid;
2579     GstBuffer *kid_buf;
2580     gboolean is_encrypted = TRUE;
2581
2582     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2583       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2584       return;
2585     }
2586
2587     algorithm_id >>= 8;
2588     if (algorithm_id == 0) {
2589       is_encrypted = FALSE;
2590     } else if (algorithm_id == 1) {
2591       /* FIXME: maybe store this in properties? */
2592       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2593     } else if (algorithm_id == 2) {
2594       /* FIXME: maybe store this in properties? */
2595       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2596     }
2597
2598     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2599       return;
2600
2601     if (!gst_byte_reader_get_data (&br, 16, &kid))
2602       return;
2603
2604     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2605     gst_buffer_fill (kid_buf, 0, kid, 16);
2606     if (ss_info->default_properties)
2607       gst_structure_free (ss_info->default_properties);
2608     ss_info->default_properties =
2609         gst_structure_new ("application/x-cenc",
2610         "iv_size", G_TYPE_UINT, iv_size,
2611         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2612         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2613     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2614         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2615     gst_buffer_unref (kid_buf);
2616   } else if ((flags & 0x000002)) {
2617     uses_sub_sample_encryption = TRUE;
2618   }
2619
2620   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2621     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2622     return;
2623   }
2624
2625   ss_info->crypto_info =
2626       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2627       (GDestroyNotify) qtdemux_gst_structure_free);
2628
2629   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2630     GstStructure *properties;
2631     guint8 *data;
2632     GstBuffer *buf;
2633
2634     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2635     if (properties == NULL) {
2636       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2637       return;
2638     }
2639
2640     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2641       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2642       gst_structure_free (properties);
2643       return;
2644     }
2645     buf = gst_buffer_new_wrapped (data, iv_size);
2646     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2647     gst_buffer_unref (buf);
2648
2649     if (uses_sub_sample_encryption) {
2650       guint16 n_subsamples;
2651
2652       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2653           || n_subsamples == 0) {
2654         GST_ERROR_OBJECT (qtdemux,
2655             "failed to get subsample count for sample %u", i);
2656         gst_structure_free (properties);
2657         return;
2658       }
2659       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2660       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2661         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2662             i);
2663         gst_structure_free (properties);
2664         return;
2665       }
2666       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2667       gst_structure_set (properties,
2668           "subsample_count", G_TYPE_UINT, n_subsamples,
2669           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2670       gst_buffer_unref (buf);
2671     } else {
2672       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2673     }
2674
2675     g_ptr_array_add (ss_info->crypto_info, properties);
2676   }
2677 }
2678
2679 static void
2680 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2681 {
2682   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2683     0x97, 0xA9, 0x42, 0xE8,
2684     0x9C, 0x71, 0x99, 0x94,
2685     0x91, 0xE3, 0xAF, 0xAC
2686   };
2687   static const guint8 playready_uuid[] = {
2688     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2689     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2690   };
2691
2692   static const guint8 piff_sample_encryption_uuid[] = {
2693     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2694     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2695   };
2696
2697   guint offset;
2698
2699   /* counts as header data */
2700   qtdemux->header_size += length;
2701
2702   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2703
2704   if (length <= offset + 16) {
2705     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2706     return;
2707   }
2708
2709   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2710     GstBuffer *buf;
2711     GstTagList *taglist;
2712
2713     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2714         length - offset - 16, NULL);
2715     taglist = gst_tag_list_from_xmp_buffer (buf);
2716     gst_buffer_unref (buf);
2717
2718     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2719
2720   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2721     int len;
2722     const gunichar2 *s_utf16;
2723     char *contents;
2724
2725     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2726     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2727     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2728     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2729
2730     g_free (contents);
2731
2732     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2733         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2734         (NULL));
2735   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2736     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2737   } else {
2738     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2739         GST_READ_UINT32_LE (buffer + offset),
2740         GST_READ_UINT32_LE (buffer + offset + 4),
2741         GST_READ_UINT32_LE (buffer + offset + 8),
2742         GST_READ_UINT32_LE (buffer + offset + 12));
2743   }
2744 }
2745
2746 static void
2747 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2748 {
2749   GstSidxParser sidx_parser;
2750   GstIsoffParserResult res;
2751   guint consumed;
2752
2753   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2754
2755   res =
2756       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2757       &consumed);
2758   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2759   if (res == GST_ISOFF_QT_PARSER_DONE) {
2760     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2761   }
2762   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2763 }
2764
2765 /* caller verifies at least 8 bytes in buf */
2766 static void
2767 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2768     guint64 * plength, guint32 * pfourcc)
2769 {
2770   guint64 length;
2771   guint32 fourcc;
2772
2773   length = QT_UINT32 (data);
2774   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2775   fourcc = QT_FOURCC (data + 4);
2776   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2777
2778   if (length == 0) {
2779     length = G_MAXUINT64;
2780   } else if (length == 1 && size >= 16) {
2781     /* this means we have an extended size, which is the 64 bit value of
2782      * the next 8 bytes */
2783     length = QT_UINT64 (data + 8);
2784     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2785   }
2786
2787   if (plength)
2788     *plength = length;
2789   if (pfourcc)
2790     *pfourcc = fourcc;
2791 }
2792
2793 static gboolean
2794 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2795 {
2796   guint32 version = 0;
2797   GstClockTime duration = 0;
2798
2799   if (!gst_byte_reader_get_uint32_be (br, &version))
2800     goto failed;
2801
2802   version >>= 24;
2803   if (version == 1) {
2804     if (!gst_byte_reader_get_uint64_be (br, &duration))
2805       goto failed;
2806   } else {
2807     guint32 dur = 0;
2808
2809     if (!gst_byte_reader_get_uint32_be (br, &dur))
2810       goto failed;
2811     duration = dur;
2812   }
2813
2814   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2815   qtdemux->duration = duration;
2816
2817   return TRUE;
2818
2819 failed:
2820   {
2821     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2822     return FALSE;
2823   }
2824 }
2825
2826 static gboolean
2827 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2828     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2829 {
2830   if (!stream->parsed_trex && qtdemux->moov_node) {
2831     GNode *mvex, *trex;
2832     GstByteReader trex_data;
2833
2834     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2835     if (mvex) {
2836       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2837           &trex_data);
2838       while (trex) {
2839         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2840
2841         /* skip version/flags */
2842         if (!gst_byte_reader_skip (&trex_data, 4))
2843           goto next;
2844         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2845           goto next;
2846         if (id != stream->track_id)
2847           goto next;
2848         /* sample description index; ignore */
2849         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2850           goto next;
2851         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2852           goto next;
2853         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2854           goto next;
2855         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2856           goto next;
2857
2858         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2859             "duration %d,  size %d, flags 0x%x", stream->track_id,
2860             dur, size, flags);
2861
2862         stream->parsed_trex = TRUE;
2863         stream->def_sample_duration = dur;
2864         stream->def_sample_size = size;
2865         stream->def_sample_flags = flags;
2866
2867       next:
2868         /* iterate all siblings */
2869         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2870             &trex_data);
2871       }
2872     }
2873   }
2874
2875   *ds_duration = stream->def_sample_duration;
2876   *ds_size = stream->def_sample_size;
2877   *ds_flags = stream->def_sample_flags;
2878
2879   /* even then, above values are better than random ... */
2880   if (G_UNLIKELY (!stream->parsed_trex)) {
2881     GST_WARNING_OBJECT (qtdemux,
2882         "failed to find fragment defaults for stream %d", stream->track_id);
2883     return FALSE;
2884   }
2885
2886   return TRUE;
2887 }
2888
2889 /* This method should be called whenever a more accurate duration might
2890  * have been found. It will update all relevant variables if/where needed
2891  */
2892 static void
2893 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2894 {
2895   guint i;
2896   guint64 movdur;
2897   GstClockTime prevdur;
2898
2899   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2900
2901   if (movdur > qtdemux->duration) {
2902     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2903     GST_DEBUG_OBJECT (qtdemux,
2904         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2905         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2906     qtdemux->duration = movdur;
2907     GST_DEBUG_OBJECT (qtdemux,
2908         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2909         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2910         GST_TIME_ARGS (qtdemux->segment.stop));
2911     if (qtdemux->segment.duration == prevdur) {
2912       /* If the current segment has duration/stop identical to previous duration
2913        * update them also (because they were set at that point in time with
2914        * the wrong duration */
2915       /* We convert the value *from* the timescale version to avoid rounding errors */
2916       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2917       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2918       qtdemux->segment.duration = fixeddur;
2919       qtdemux->segment.stop = fixeddur;
2920     }
2921   }
2922   for (i = 0; i < qtdemux->n_streams; i++) {
2923     QtDemuxStream *stream = qtdemux->streams[i];
2924     if (stream) {
2925       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2926       if (movdur > stream->duration) {
2927         GST_DEBUG_OBJECT (qtdemux,
2928             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2929             GST_TIME_ARGS (duration));
2930         stream->duration = movdur;
2931         if (stream->dummy_segment) {
2932           /* Update all dummy values to new duration */
2933           stream->segments[0].stop_time = duration;
2934           stream->segments[0].duration = duration;
2935           stream->segments[0].media_stop = duration;
2936
2937           /* let downstream know we possibly have a new stop time */
2938           if (stream->segment_index != -1) {
2939             GstClockTime pos;
2940
2941             if (qtdemux->segment.rate >= 0) {
2942               pos = stream->segment.start;
2943             } else {
2944               pos = stream->segment.stop;
2945             }
2946
2947             gst_qtdemux_stream_update_segment (qtdemux, stream,
2948                 stream->segment_index, pos, NULL, NULL);
2949           }
2950         }
2951       }
2952     }
2953   }
2954 }
2955
2956 static gboolean
2957 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2958     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2959     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2960     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2961 {
2962   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2963   guint64 timestamp;
2964   gint32 data_offset = 0;
2965   guint32 flags = 0, first_flags = 0, samples_count = 0;
2966   gint i;
2967   guint8 *data;
2968   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2969   QtDemuxSample *sample;
2970   gboolean ismv = FALSE;
2971
2972   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2973       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2974       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2975       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2976
2977   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2978     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2979     return TRUE;
2980   }
2981
2982   /* presence of stss or not can't really tell us much,
2983    * and flags and so on tend to be marginally reliable in these files */
2984   if (stream->subtype == FOURCC_soun) {
2985     GST_DEBUG_OBJECT (qtdemux,
2986         "sound track in fragmented file; marking all keyframes");
2987     stream->all_keyframe = TRUE;
2988   }
2989
2990   if (!gst_byte_reader_skip (trun, 1) ||
2991       !gst_byte_reader_get_uint24_be (trun, &flags))
2992     goto fail;
2993
2994   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
2995     goto fail;
2996
2997   if (flags & TR_DATA_OFFSET) {
2998     /* note this is really signed */
2999     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3000       goto fail;
3001     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3002     /* default base offset = first byte of moof */
3003     if (*base_offset == -1) {
3004       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3005       *base_offset = moof_offset;
3006     }
3007     *running_offset = *base_offset + data_offset;
3008   } else {
3009     /* if no offset at all, that would mean data starts at moof start,
3010      * which is a bit wrong and is ismv crappy way, so compensate
3011      * assuming data is in mdat following moof */
3012     if (*base_offset == -1) {
3013       *base_offset = moof_offset + moof_length + 8;
3014       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3015       ismv = TRUE;
3016     }
3017     if (*running_offset == -1)
3018       *running_offset = *base_offset;
3019   }
3020
3021   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3022       *running_offset);
3023   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3024       data_offset, flags, samples_count);
3025
3026   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3027     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3028       GST_DEBUG_OBJECT (qtdemux,
3029           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3030       flags ^= TR_FIRST_SAMPLE_FLAGS;
3031     } else {
3032       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3033         goto fail;
3034       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3035     }
3036   }
3037
3038   /* FIXME ? spec says other bits should also be checked to determine
3039    * entry size (and prefix size for that matter) */
3040   entry_size = 0;
3041   dur_offset = size_offset = 0;
3042   if (flags & TR_SAMPLE_DURATION) {
3043     GST_LOG_OBJECT (qtdemux, "entry duration present");
3044     dur_offset = entry_size;
3045     entry_size += 4;
3046   }
3047   if (flags & TR_SAMPLE_SIZE) {
3048     GST_LOG_OBJECT (qtdemux, "entry size present");
3049     size_offset = entry_size;
3050     entry_size += 4;
3051   }
3052   if (flags & TR_SAMPLE_FLAGS) {
3053     GST_LOG_OBJECT (qtdemux, "entry flags present");
3054     flags_offset = entry_size;
3055     entry_size += 4;
3056   }
3057   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3058     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3059     ct_offset = entry_size;
3060     entry_size += 4;
3061   }
3062
3063   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3064     goto fail;
3065   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3066
3067   if (stream->n_samples + samples_count >=
3068       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3069     goto index_too_big;
3070
3071   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3072       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3073       (stream->n_samples + samples_count) *
3074       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3075
3076   /* create a new array of samples if it's the first sample parsed */
3077   if (stream->n_samples == 0) {
3078     g_assert (stream->samples == NULL);
3079     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3080     /* or try to reallocate it with space enough to insert the new samples */
3081   } else
3082     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3083         stream->n_samples + samples_count);
3084   if (stream->samples == NULL)
3085     goto out_of_memory;
3086
3087   if (qtdemux->fragment_start != -1) {
3088     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3089     qtdemux->fragment_start = -1;
3090   } else {
3091     if (stream->n_samples == 0) {
3092       if (decode_ts > 0) {
3093         timestamp = decode_ts;
3094       } else if (stream->pending_seek != NULL) {
3095         /* if we don't have a timestamp from a tfdt box, we'll use the one
3096          * from the mfra seek table */
3097         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3098             GST_TIME_ARGS (stream->pending_seek->ts));
3099
3100         /* FIXME: this is not fully correct, the timestamp refers to the random
3101          * access sample refered to in the tfra entry, which may not necessarily
3102          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3103         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3104       } else {
3105         timestamp = 0;
3106       }
3107
3108       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3109       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3110           GST_TIME_ARGS (gst_ts));
3111     } else {
3112       /* subsequent fragments extend stream */
3113       timestamp =
3114           stream->samples[stream->n_samples - 1].timestamp +
3115           stream->samples[stream->n_samples - 1].duration;
3116
3117       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3118       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3119           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3120     }
3121   }
3122
3123   sample = stream->samples + stream->n_samples;
3124   for (i = 0; i < samples_count; i++) {
3125     guint32 dur, size, sflags, ct;
3126
3127     /* first read sample data */
3128     if (flags & TR_SAMPLE_DURATION) {
3129       dur = QT_UINT32 (data + dur_offset);
3130     } else {
3131       dur = d_sample_duration;
3132     }
3133     if (flags & TR_SAMPLE_SIZE) {
3134       size = QT_UINT32 (data + size_offset);
3135     } else {
3136       size = d_sample_size;
3137     }
3138     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3139       if (i == 0) {
3140         sflags = first_flags;
3141       } else {
3142         sflags = d_sample_flags;
3143       }
3144     } else if (flags & TR_SAMPLE_FLAGS) {
3145       sflags = QT_UINT32 (data + flags_offset);
3146     } else {
3147       sflags = d_sample_flags;
3148     }
3149     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3150       ct = QT_UINT32 (data + ct_offset);
3151     } else {
3152       ct = 0;
3153     }
3154     data += entry_size;
3155
3156     /* fill the sample information */
3157     sample->offset = *running_offset;
3158     sample->pts_offset = ct;
3159     sample->size = size;
3160     sample->timestamp = timestamp;
3161     sample->duration = dur;
3162     /* sample-is-difference-sample */
3163     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3164      * now idea how it relates to bitfield other than massive LE/BE confusion */
3165     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3166     *running_offset += size;
3167     timestamp += dur;
3168     stream->duration_moof += dur;
3169     sample++;
3170   }
3171
3172   /* Update total duration if needed */
3173   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3174
3175   stream->n_samples += samples_count;
3176   stream->n_samples_moof += samples_count;
3177
3178   if (stream->pending_seek != NULL)
3179     stream->pending_seek = NULL;
3180
3181   return TRUE;
3182
3183 fail:
3184   {
3185     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3186     return FALSE;
3187   }
3188 out_of_memory:
3189   {
3190     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3191         stream->n_samples);
3192     return FALSE;
3193   }
3194 index_too_big:
3195   {
3196     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3197         "be larger than %uMB (broken file?)", stream->n_samples,
3198         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3199     return FALSE;
3200   }
3201 }
3202
3203 /* find stream with @id */
3204 static inline QtDemuxStream *
3205 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3206 {
3207   QtDemuxStream *stream;
3208   gint i;
3209
3210   /* check */
3211   if (G_UNLIKELY (!id)) {
3212     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3213     return NULL;
3214   }
3215
3216   /* try to get it fast and simple */
3217   if (G_LIKELY (id <= qtdemux->n_streams)) {
3218     stream = qtdemux->streams[id - 1];
3219     if (G_LIKELY (stream->track_id == id))
3220       return stream;
3221   }
3222
3223   /* linear search otherwise */
3224   for (i = 0; i < qtdemux->n_streams; i++) {
3225     stream = qtdemux->streams[i];
3226     if (stream->track_id == id)
3227       return stream;
3228   }
3229   if (qtdemux->mss_mode) {
3230     /* mss should have only 1 stream anyway */
3231     return qtdemux->streams[0];
3232   }
3233
3234   return NULL;
3235 }
3236
3237 static gboolean
3238 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3239     guint32 * fragment_number)
3240 {
3241   if (!gst_byte_reader_skip (mfhd, 4))
3242     goto fail;
3243   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3244     goto fail;
3245   return TRUE;
3246 fail:
3247   {
3248     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3249     return FALSE;
3250   }
3251 }
3252
3253 static gboolean
3254 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3255     QtDemuxStream ** stream, guint32 * default_sample_duration,
3256     guint32 * default_sample_size, guint32 * default_sample_flags,
3257     gint64 * base_offset)
3258 {
3259   guint32 flags = 0;
3260   guint32 track_id = 0;
3261
3262   if (!gst_byte_reader_skip (tfhd, 1) ||
3263       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3264     goto invalid_track;
3265
3266   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3267     goto invalid_track;
3268
3269   *stream = qtdemux_find_stream (qtdemux, track_id);
3270   if (G_UNLIKELY (!*stream))
3271     goto unknown_stream;
3272
3273   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3274     *base_offset = qtdemux->moof_offset;
3275
3276   if (flags & TF_BASE_DATA_OFFSET)
3277     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3278       goto invalid_track;
3279
3280   /* obtain stream defaults */
3281   qtdemux_parse_trex (qtdemux, *stream,
3282       default_sample_duration, default_sample_size, default_sample_flags);
3283
3284   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3285   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3286     if (!gst_byte_reader_skip (tfhd, 4))
3287       goto invalid_track;
3288
3289   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3290     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3291       goto invalid_track;
3292
3293   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3294     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3295       goto invalid_track;
3296
3297   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3298     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3299       goto invalid_track;
3300
3301   return TRUE;
3302
3303 invalid_track:
3304   {
3305     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3306     return FALSE;
3307   }
3308 unknown_stream:
3309   {
3310     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3311     return TRUE;
3312   }
3313 }
3314
3315 static gboolean
3316 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3317     guint64 * decode_time)
3318 {
3319   guint32 version = 0;
3320
3321   if (!gst_byte_reader_get_uint32_be (br, &version))
3322     return FALSE;
3323
3324   version >>= 24;
3325   if (version == 1) {
3326     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3327       goto failed;
3328   } else {
3329     guint32 dec_time = 0;
3330     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3331       goto failed;
3332     *decode_time = dec_time;
3333   }
3334
3335   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3336       *decode_time);
3337
3338   return TRUE;
3339
3340 failed:
3341   {
3342     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3343     return FALSE;
3344   }
3345 }
3346
3347 /* Returns a pointer to a GstStructure containing the properties of
3348  * the stream sample identified by @sample_index. The caller must unref
3349  * the returned object after use. Returns NULL if unsuccessful. */
3350 static GstStructure *
3351 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3352     QtDemuxStream * stream, guint sample_index)
3353 {
3354   QtDemuxCencSampleSetInfo *info = NULL;
3355
3356   g_return_val_if_fail (stream != NULL, NULL);
3357   g_return_val_if_fail (stream->protected, NULL);
3358   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3359
3360   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3361
3362   /* Currently, cenc properties for groups of samples are not supported, so
3363    * simply return a copy of the default sample properties */
3364   return gst_structure_copy (info->default_properties);
3365 }
3366
3367 /* Parses the sizes of sample auxiliary information contained within a stream,
3368  * as given in a saiz box. Returns array of sample_count guint8 size values,
3369  * or NULL on failure */
3370 static guint8 *
3371 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3372     GstByteReader * br, guint32 * sample_count)
3373 {
3374   guint32 flags = 0;
3375   guint8 *info_sizes;
3376   guint8 default_info_size;
3377
3378   g_return_val_if_fail (qtdemux != NULL, NULL);
3379   g_return_val_if_fail (stream != NULL, NULL);
3380   g_return_val_if_fail (br != NULL, NULL);
3381   g_return_val_if_fail (sample_count != NULL, NULL);
3382
3383   if (!gst_byte_reader_get_uint32_be (br, &flags))
3384     return NULL;
3385
3386   if (flags & 0x1) {
3387     /* aux_info_type and aux_info_type_parameter are ignored */
3388     if (!gst_byte_reader_skip (br, 8))
3389       return NULL;
3390   }
3391
3392   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3393     return NULL;
3394   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3395
3396   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3397     return NULL;
3398   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3399
3400
3401   if (default_info_size == 0) {
3402     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3403       return NULL;
3404     }
3405   } else {
3406     info_sizes = g_new (guint8, *sample_count);
3407     memset (info_sizes, default_info_size, *sample_count);
3408   }
3409
3410   return info_sizes;
3411 }
3412
3413 /* Parses the offset of sample auxiliary information contained within a stream,
3414  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3415 static gboolean
3416 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3417     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3418     guint64 * offset)
3419 {
3420   guint8 version = 0;
3421   guint32 flags = 0;
3422   guint32 aux_info_type = 0;
3423   guint32 aux_info_type_parameter = 0;
3424   guint32 entry_count;
3425   guint32 off_32;
3426   guint64 off_64;
3427   const guint8 *aux_info_type_data = NULL;
3428
3429   g_return_val_if_fail (qtdemux != NULL, FALSE);
3430   g_return_val_if_fail (stream != NULL, FALSE);
3431   g_return_val_if_fail (br != NULL, FALSE);
3432   g_return_val_if_fail (offset != NULL, FALSE);
3433
3434   if (!gst_byte_reader_get_uint8 (br, &version))
3435     return FALSE;
3436
3437   if (!gst_byte_reader_get_uint24_be (br, &flags))
3438     return FALSE;
3439
3440   if (flags & 0x1) {
3441
3442     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3443       return FALSE;
3444     aux_info_type = QT_FOURCC (aux_info_type_data);
3445
3446     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3447       return FALSE;
3448   } else if (stream->protected) {
3449     aux_info_type = stream->protection_scheme_type;
3450   } else {
3451     aux_info_type = stream->fourcc;
3452   }
3453
3454   if (info_type)
3455     *info_type = aux_info_type;
3456   if (info_type_parameter)
3457     *info_type_parameter = aux_info_type_parameter;
3458
3459   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3460       "aux_info_type_parameter:  %#06x",
3461       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3462
3463   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3464     return FALSE;
3465
3466   if (entry_count != 1) {
3467     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3468     return FALSE;
3469   }
3470
3471   if (version == 0) {
3472     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3473       return FALSE;
3474     *offset = (guint64) off_32;
3475   } else {
3476     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3477       return FALSE;
3478     *offset = off_64;
3479   }
3480
3481   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3482   return TRUE;
3483 }
3484
3485 static void
3486 qtdemux_gst_structure_free (GstStructure * gststructure)
3487 {
3488   if (gststructure) {
3489     gst_structure_free (gststructure);
3490   }
3491 }
3492
3493 /* Parses auxiliary information relating to samples protected using Common
3494  * Encryption (cenc); the format of this information is defined in
3495  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3496 static gboolean
3497 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3498     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3499 {
3500   QtDemuxCencSampleSetInfo *ss_info = NULL;
3501   guint8 size;
3502   gint i;
3503
3504   g_return_val_if_fail (qtdemux != NULL, FALSE);
3505   g_return_val_if_fail (stream != NULL, FALSE);
3506   g_return_val_if_fail (br != NULL, FALSE);
3507   g_return_val_if_fail (stream->protected, FALSE);
3508   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3509
3510   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3511
3512   if (ss_info->crypto_info) {
3513     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3514     g_ptr_array_free (ss_info->crypto_info, TRUE);
3515   }
3516
3517   ss_info->crypto_info =
3518       g_ptr_array_new_full (sample_count,
3519       (GDestroyNotify) qtdemux_gst_structure_free);
3520
3521   for (i = 0; i < sample_count; ++i) {
3522     GstStructure *properties;
3523     guint16 n_subsamples = 0;
3524     guint8 *data;
3525     guint iv_size;
3526     GstBuffer *buf;
3527
3528     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3529     if (properties == NULL) {
3530       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3531       return FALSE;
3532     }
3533     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3534       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3535       gst_structure_free (properties);
3536       return FALSE;
3537     }
3538     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3539       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3540       gst_structure_free (properties);
3541       return FALSE;
3542     }
3543     buf = gst_buffer_new_wrapped (data, iv_size);
3544     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3545     gst_buffer_unref (buf);
3546     size = info_sizes[i];
3547     if (size > iv_size) {
3548       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3549           || !(n_subsamples > 0)) {
3550         gst_structure_free (properties);
3551         GST_ERROR_OBJECT (qtdemux,
3552             "failed to get subsample count for sample %u", i);
3553         return FALSE;
3554       }
3555       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3556       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3557         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3558             i);
3559         gst_structure_free (properties);
3560         return FALSE;
3561       }
3562       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3563       if (!buf) {
3564         gst_structure_free (properties);
3565         return FALSE;
3566       }
3567       gst_structure_set (properties,
3568           "subsample_count", G_TYPE_UINT, n_subsamples,
3569           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3570       gst_buffer_unref (buf);
3571     } else {
3572       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3573     }
3574     g_ptr_array_add (ss_info->crypto_info, properties);
3575   }
3576   return TRUE;
3577 }
3578
3579 /* Converts a UUID in raw byte form to a string representation, as defined in
3580  * RFC 4122. The caller takes ownership of the returned string and is
3581  * responsible for freeing it after use. */
3582 static gchar *
3583 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3584 {
3585   const guint8 *uuid = (const guint8 *) uuid_bytes;
3586
3587   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3588       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3589       uuid[0], uuid[1], uuid[2], uuid[3],
3590       uuid[4], uuid[5], uuid[6], uuid[7],
3591       uuid[8], uuid[9], uuid[10], uuid[11],
3592       uuid[12], uuid[13], uuid[14], uuid[15]);
3593 }
3594
3595 /* Parses a Protection System Specific Header box (pssh), as defined in the
3596  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3597  * information needed by a specific content protection system in order to
3598  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3599  * otherwise. */
3600 static gboolean
3601 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3602 {
3603   gchar *sysid_string;
3604   guint32 pssh_size = QT_UINT32 (node->data);
3605   GstBuffer *pssh = NULL;
3606   GstEvent *event = NULL;
3607   guint32 parent_box_type;
3608   gint i;
3609
3610   if (G_UNLIKELY (pssh_size < 32U)) {
3611     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3612     return FALSE;
3613   }
3614
3615   sysid_string =
3616       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3617
3618   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3619
3620   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3621   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3622       gst_buffer_get_size (pssh));
3623
3624   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3625
3626   /* Push an event containing the pssh box onto the queues of all streams. */
3627   event = gst_event_new_protection (sysid_string, pssh,
3628       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3629   for (i = 0; i < qtdemux->n_streams; ++i) {
3630     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3631         gst_event_ref (event));
3632   }
3633   g_free (sysid_string);
3634   gst_event_unref (event);
3635   gst_buffer_unref (pssh);
3636   return TRUE;
3637 }
3638
3639 static gboolean
3640 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3641     guint64 moof_offset, QtDemuxStream * stream)
3642 {
3643   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3644   GNode *uuid_node;
3645   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3646   GNode *saiz_node, *saio_node, *pssh_node;
3647   GstByteReader saiz_data, saio_data;
3648   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3649   gint64 base_offset, running_offset;
3650   guint32 frag_num;
3651
3652   /* NOTE @stream ignored */
3653
3654   moof_node = g_node_new ((guint8 *) buffer);
3655   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3656   qtdemux_node_dump (qtdemux, moof_node);
3657
3658   /* Get fragment number from mfhd and check it's valid */
3659   mfhd_node =
3660       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3661   if (mfhd_node == NULL)
3662     goto missing_mfhd;
3663   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3664     goto fail;
3665   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3666
3667   /* unknown base_offset to start with */
3668   base_offset = running_offset = -1;
3669   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3670   while (traf_node) {
3671     guint64 decode_time = 0;
3672
3673     /* Fragment Header node */
3674     tfhd_node =
3675         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3676         &tfhd_data);
3677     if (!tfhd_node)
3678       goto missing_tfhd;
3679     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3680             &ds_size, &ds_flags, &base_offset))
3681       goto missing_tfhd;
3682
3683     /* The following code assumes at most a single set of sample auxiliary
3684      * data in the fragment (consisting of a saiz box and a corresponding saio
3685      * box); in theory, however, there could be multiple sets of sample
3686      * auxiliary data in a fragment. */
3687     saiz_node =
3688         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3689         &saiz_data);
3690     if (saiz_node) {
3691       guint32 info_type = 0;
3692       guint64 offset = 0;
3693       guint32 info_type_parameter = 0;
3694
3695       g_free (qtdemux->cenc_aux_info_sizes);
3696
3697       qtdemux->cenc_aux_info_sizes =
3698           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3699           &qtdemux->cenc_aux_sample_count);
3700       if (qtdemux->cenc_aux_info_sizes == NULL) {
3701         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3702         goto fail;
3703       }
3704       saio_node =
3705           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3706           &saio_data);
3707       if (!saio_node) {
3708         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3709         g_free (qtdemux->cenc_aux_info_sizes);
3710         qtdemux->cenc_aux_info_sizes = NULL;
3711         goto fail;
3712       }
3713
3714       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3715                   &info_type, &info_type_parameter, &offset))) {
3716         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3717         g_free (qtdemux->cenc_aux_info_sizes);
3718         qtdemux->cenc_aux_info_sizes = NULL;
3719         goto fail;
3720       }
3721       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3722         offset += (guint64) (base_offset - qtdemux->moof_offset);
3723       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3724         GstByteReader br;
3725         if (offset > length) {
3726           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3727           qtdemux->cenc_aux_info_offset = offset;
3728         } else {
3729           gst_byte_reader_init (&br, buffer + offset, length - offset);
3730           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3731                   qtdemux->cenc_aux_info_sizes,
3732                   qtdemux->cenc_aux_sample_count)) {
3733             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3734             g_free (qtdemux->cenc_aux_info_sizes);
3735             qtdemux->cenc_aux_info_sizes = NULL;
3736             goto fail;
3737           }
3738         }
3739       }
3740     }
3741
3742     tfdt_node =
3743         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3744         &tfdt_data);
3745     if (tfdt_node) {
3746       GstClockTime decode_time_ts;
3747
3748       /* We'll use decode_time to interpolate timestamps
3749        * in case the input timestamps are missing */
3750       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3751
3752       decode_time_ts = QTSTREAMTIME_TO_GSTTIME (stream, decode_time);
3753
3754       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3755           " (%" GST_TIME_FORMAT ")", decode_time,
3756           GST_TIME_ARGS (decode_time_ts));
3757
3758       /* Discard the fragment buffer timestamp info to avoid using it.
3759        * Rely on tfdt instead as it is more accurate than the timestamp
3760        * that is fetched from a manifest/playlist and is usually
3761        * less accurate. */
3762       qtdemux->fragment_start = -1;
3763     }
3764
3765     if (G_UNLIKELY (!stream)) {
3766       /* we lost track of offset, we'll need to regain it,
3767        * but can delay complaining until later or avoid doing so altogether */
3768       base_offset = -2;
3769       goto next;
3770     }
3771     if (G_UNLIKELY (base_offset < -1))
3772       goto lost_offset;
3773
3774     if (qtdemux->upstream_format_is_time)
3775       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3776
3777     /* initialise moof sample data */
3778     stream->n_samples_moof = 0;
3779     stream->duration_moof = 0;
3780
3781     /* Track Run node */
3782     trun_node =
3783         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3784         &trun_data);
3785     while (trun_node) {
3786       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3787           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3788           &running_offset, decode_time);
3789       /* iterate all siblings */
3790       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3791           &trun_data);
3792     }
3793
3794     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3795     if (uuid_node) {
3796       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3797       guint32 box_length = QT_UINT32 (uuid_buffer);
3798
3799       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3800     }
3801
3802     /* if no new base_offset provided for next traf,
3803      * base is end of current traf */
3804     base_offset = running_offset;
3805     running_offset = -1;
3806
3807     if (stream->n_samples_moof && stream->duration_moof)
3808       stream->new_caps = TRUE;
3809
3810   next:
3811     /* iterate all siblings */
3812     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3813   }
3814
3815   /* parse any protection system info */
3816   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3817   while (pssh_node) {
3818     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3819     qtdemux_parse_pssh (qtdemux, pssh_node);
3820     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3821   }
3822
3823   g_node_destroy (moof_node);
3824   return TRUE;
3825
3826 missing_tfhd:
3827   {
3828     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3829     goto fail;
3830   }
3831 missing_mfhd:
3832   {
3833     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3834     goto fail;
3835   }
3836 lost_offset:
3837   {
3838     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3839     goto fail;
3840   }
3841 fail:
3842   {
3843     g_node_destroy (moof_node);
3844     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3845         (_("This file is corrupt and cannot be played.")), (NULL));
3846     return FALSE;
3847   }
3848 }
3849
3850 #if 0
3851 /* might be used if some day we actually use mfra & co
3852  * for random access to fragments,
3853  * but that will require quite some modifications and much less relying
3854  * on a sample array */
3855 #endif
3856
3857 static gboolean
3858 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3859 {
3860   QtDemuxStream *stream;
3861   guint32 ver_flags, track_id, len, num_entries, i;
3862   guint value_size, traf_size, trun_size, sample_size;
3863   guint64 time = 0, moof_offset = 0;
3864 #if 0
3865   GstBuffer *buf = NULL;
3866   GstFlowReturn ret;
3867 #endif
3868   GstByteReader tfra;
3869
3870   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3871
3872   if (!gst_byte_reader_skip (&tfra, 8))
3873     return FALSE;
3874
3875   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3876     return FALSE;
3877
3878   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3879       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3880       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3881     return FALSE;
3882
3883   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3884
3885   stream = qtdemux_find_stream (qtdemux, track_id);
3886   if (stream == NULL)
3887     goto unknown_trackid;
3888
3889   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3890   sample_size = (len & 3) + 1;
3891   trun_size = ((len & 12) >> 2) + 1;
3892   traf_size = ((len & 48) >> 4) + 1;
3893
3894   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3895       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3896
3897   if (num_entries == 0)
3898     goto no_samples;
3899
3900   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3901           value_size + value_size + traf_size + trun_size + sample_size))
3902     goto corrupt_file;
3903
3904   g_free (stream->ra_entries);
3905   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3906   stream->n_ra_entries = num_entries;
3907
3908   for (i = 0; i < num_entries; i++) {
3909     qt_atom_parser_get_offset (&tfra, value_size, &time);
3910     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3911     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3912     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3913     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3914
3915     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3916
3917     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3918         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3919
3920     stream->ra_entries[i].ts = time;
3921     stream->ra_entries[i].moof_offset = moof_offset;
3922
3923     /* don't want to go through the entire file and read all moofs at startup */
3924 #if 0
3925     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3926     if (ret != GST_FLOW_OK)
3927       goto corrupt_file;
3928     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3929         moof_offset, stream);
3930     gst_buffer_unref (buf);
3931 #endif
3932   }
3933
3934   check_update_duration (qtdemux, time);
3935
3936   return TRUE;
3937
3938 /* ERRORS */
3939 unknown_trackid:
3940   {
3941     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3942     return FALSE;
3943   }
3944 corrupt_file:
3945   {
3946     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3947     return FALSE;
3948   }
3949 no_samples:
3950   {
3951     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3952     return FALSE;
3953   }
3954 }
3955
3956 static gboolean
3957 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3958 {
3959   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3960   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3961   GstBuffer *mfro = NULL, *mfra = NULL;
3962   GstFlowReturn flow;
3963   gboolean ret = FALSE;
3964   GNode *mfra_node, *tfra_node;
3965   guint64 mfra_offset = 0;
3966   guint32 fourcc, mfra_size;
3967   gint64 len;
3968
3969   /* query upstream size in bytes */
3970   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3971     goto size_query_failed;
3972
3973   /* mfro box should be at the very end of the file */
3974   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3975   if (flow != GST_FLOW_OK)
3976     goto exit;
3977
3978   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3979
3980   fourcc = QT_FOURCC (mfro_map.data + 4);
3981   if (fourcc != FOURCC_mfro)
3982     goto exit;
3983
3984   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3985   if (mfro_map.size < 16)
3986     goto invalid_mfro_size;
3987
3988   mfra_size = QT_UINT32 (mfro_map.data + 12);
3989   if (mfra_size >= len)
3990     goto invalid_mfra_size;
3991
3992   mfra_offset = len - mfra_size;
3993
3994   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
3995       mfra_offset, mfra_size);
3996
3997   /* now get and parse mfra box */
3998   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
3999   if (flow != GST_FLOW_OK)
4000     goto broken_file;
4001
4002   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4003
4004   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4005   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4006
4007   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4008
4009   while (tfra_node) {
4010     qtdemux_parse_tfra (qtdemux, tfra_node);
4011     /* iterate all siblings */
4012     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4013   }
4014   g_node_destroy (mfra_node);
4015
4016   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4017   ret = TRUE;
4018
4019 exit:
4020
4021   if (mfro) {
4022     if (mfro_map.memory != NULL)
4023       gst_buffer_unmap (mfro, &mfro_map);
4024     gst_buffer_unref (mfro);
4025   }
4026   if (mfra) {
4027     if (mfra_map.memory != NULL)
4028       gst_buffer_unmap (mfra, &mfra_map);
4029     gst_buffer_unref (mfra);
4030   }
4031   return ret;
4032
4033 /* ERRORS */
4034 size_query_failed:
4035   {
4036     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4037     goto exit;
4038   }
4039 invalid_mfro_size:
4040   {
4041     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4042     goto exit;
4043   }
4044 invalid_mfra_size:
4045   {
4046     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4047     goto exit;
4048   }
4049 broken_file:
4050   {
4051     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4052     goto exit;
4053   }
4054 }
4055
4056 static guint64
4057 add_offset (guint64 offset, guint64 advance)
4058 {
4059   /* Avoid 64-bit overflow by clamping */
4060   if (offset > G_MAXUINT64 - advance)
4061     return G_MAXUINT64;
4062   return offset + advance;
4063 }
4064
4065 static GstFlowReturn
4066 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4067 {
4068   guint64 length = 0;
4069   guint32 fourcc = 0;
4070   GstBuffer *buf = NULL;
4071   GstFlowReturn ret = GST_FLOW_OK;
4072   guint64 cur_offset = qtdemux->offset;
4073   GstMapInfo map;
4074
4075   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4076   if (G_UNLIKELY (ret != GST_FLOW_OK))
4077     goto beach;
4078   gst_buffer_map (buf, &map, GST_MAP_READ);
4079   if (G_LIKELY (map.size >= 8))
4080     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4081   gst_buffer_unmap (buf, &map);
4082   gst_buffer_unref (buf);
4083
4084   /* maybe we already got most we needed, so only consider this eof */
4085   if (G_UNLIKELY (length == 0)) {
4086     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4087         (_("Invalid atom size.")),
4088         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4089             GST_FOURCC_ARGS (fourcc)));
4090     ret = GST_FLOW_EOS;
4091     goto beach;
4092   }
4093
4094   switch (fourcc) {
4095     case FOURCC_moof:
4096       /* record for later parsing when needed */
4097       if (!qtdemux->moof_offset) {
4098         qtdemux->moof_offset = qtdemux->offset;
4099       }
4100       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4101         /* FIXME */
4102       } else {
4103         qtdemux->offset += length;      /* skip moof and keep going */
4104       }
4105       if (qtdemux->got_moov) {
4106         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4107         ret = GST_FLOW_EOS;
4108         goto beach;
4109       }
4110       break;
4111     case FOURCC_mdat:
4112     case FOURCC_free:
4113     case FOURCC_wide:
4114     case FOURCC_PICT:
4115     case FOURCC_pnot:
4116     {
4117       GST_LOG_OBJECT (qtdemux,
4118           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4119           GST_FOURCC_ARGS (fourcc), cur_offset);
4120       qtdemux->offset = add_offset (qtdemux->offset, length);
4121       break;
4122     }
4123     case FOURCC_moov:
4124     {
4125       GstBuffer *moov = NULL;
4126
4127       if (qtdemux->got_moov) {
4128         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4129         qtdemux->offset = add_offset (qtdemux->offset, length);
4130         goto beach;
4131       }
4132
4133       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4134       if (ret != GST_FLOW_OK)
4135         goto beach;
4136       gst_buffer_map (moov, &map, GST_MAP_READ);
4137
4138       if (length != map.size) {
4139         /* Some files have a 'moov' atom at the end of the file which contains
4140          * a terminal 'free' atom where the body of the atom is missing.
4141          * Check for, and permit, this special case.
4142          */
4143         if (map.size >= 8) {
4144           guint8 *final_data = map.data + (map.size - 8);
4145           guint32 final_length = QT_UINT32 (final_data);
4146           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4147
4148           if (final_fourcc == FOURCC_free
4149               && map.size + final_length - 8 == length) {
4150             /* Ok, we've found that special case. Allocate a new buffer with
4151              * that free atom actually present. */
4152             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4153             gst_buffer_fill (newmoov, 0, map.data, map.size);
4154             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4155             gst_buffer_unmap (moov, &map);
4156             gst_buffer_unref (moov);
4157             moov = newmoov;
4158             gst_buffer_map (moov, &map, GST_MAP_READ);
4159           }
4160         }
4161       }
4162
4163       if (length != map.size) {
4164         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4165             (_("This file is incomplete and cannot be played.")),
4166             ("We got less than expected (received %" G_GSIZE_FORMAT
4167                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4168                 (guint) length, cur_offset));
4169         gst_buffer_unmap (moov, &map);
4170         gst_buffer_unref (moov);
4171         ret = GST_FLOW_ERROR;
4172         goto beach;
4173       }
4174       qtdemux->offset += length;
4175
4176       qtdemux_parse_moov (qtdemux, map.data, length);
4177       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4178
4179       qtdemux_parse_tree (qtdemux);
4180       g_node_destroy (qtdemux->moov_node);
4181       gst_buffer_unmap (moov, &map);
4182       gst_buffer_unref (moov);
4183       qtdemux->moov_node = NULL;
4184       qtdemux->got_moov = TRUE;
4185
4186       break;
4187     }
4188     case FOURCC_ftyp:
4189     {
4190       GstBuffer *ftyp = NULL;
4191
4192       /* extract major brand; might come in handy for ISO vs QT issues */
4193       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4194       if (ret != GST_FLOW_OK)
4195         goto beach;
4196       qtdemux->offset += length;
4197       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4198       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4199       gst_buffer_unmap (ftyp, &map);
4200       gst_buffer_unref (ftyp);
4201       break;
4202     }
4203     case FOURCC_uuid:
4204     {
4205       GstBuffer *uuid = NULL;
4206
4207       /* uuid are extension atoms */
4208       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4209       if (ret != GST_FLOW_OK)
4210         goto beach;
4211       qtdemux->offset += length;
4212       gst_buffer_map (uuid, &map, GST_MAP_READ);
4213       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4214       gst_buffer_unmap (uuid, &map);
4215       gst_buffer_unref (uuid);
4216       break;
4217     }
4218     case FOURCC_sidx:
4219     {
4220       GstBuffer *sidx = NULL;
4221       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4222       if (ret != GST_FLOW_OK)
4223         goto beach;
4224       qtdemux->offset += length;
4225       gst_buffer_map (sidx, &map, GST_MAP_READ);
4226       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4227       gst_buffer_unmap (sidx, &map);
4228       gst_buffer_unref (sidx);
4229       break;
4230     }
4231     default:
4232     {
4233       GstBuffer *unknown = NULL;
4234
4235       GST_LOG_OBJECT (qtdemux,
4236           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4237           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4238           cur_offset);
4239       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4240       if (ret != GST_FLOW_OK)
4241         goto beach;
4242       gst_buffer_map (unknown, &map, GST_MAP_READ);
4243       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4244       gst_buffer_unmap (unknown, &map);
4245       gst_buffer_unref (unknown);
4246       qtdemux->offset += length;
4247       break;
4248     }
4249   }
4250
4251 beach:
4252   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4253     /* digested all data, show what we have */
4254     qtdemux_prepare_streams (qtdemux);
4255     ret = qtdemux_expose_streams (qtdemux);
4256
4257     qtdemux->state = QTDEMUX_STATE_MOVIE;
4258     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4259         qtdemux->state);
4260     return ret;
4261   }
4262   return ret;
4263 }
4264
4265 /* Seeks to the previous keyframe of the indexed stream and
4266  * aligns other streams with respect to the keyframe timestamp
4267  * of indexed stream. Only called in case of Reverse Playback
4268  */
4269 static GstFlowReturn
4270 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4271 {
4272   guint8 n = 0;
4273   guint32 seg_idx = 0, k_index = 0;
4274   guint32 ref_seg_idx, ref_k_index;
4275   GstClockTime k_pos = 0, last_stop = 0;
4276   QtDemuxSegment *seg = NULL;
4277   QtDemuxStream *ref_str = NULL;
4278   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4279   guint64 target_ts;
4280
4281   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4282    * and finally align all the other streams on that timestamp with their
4283    * respective keyframes */
4284   for (n = 0; n < qtdemux->n_streams; n++) {
4285     QtDemuxStream *str = qtdemux->streams[n];
4286
4287     /* No candidate yet, take the first stream */
4288     if (!ref_str) {
4289       ref_str = str;
4290       continue;
4291     }
4292
4293     /* So that stream has a segment, we prefer video streams */
4294     if (str->subtype == FOURCC_vide) {
4295       ref_str = str;
4296       break;
4297     }
4298   }
4299
4300   if (G_UNLIKELY (!ref_str)) {
4301     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4302     goto eos;
4303   }
4304
4305   if (G_UNLIKELY (!ref_str->from_sample)) {
4306     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4307     goto eos;
4308   }
4309
4310   /* So that stream has been playing from from_sample to to_sample. We will
4311    * get the timestamp of the previous sample and search for a keyframe before
4312    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4313   if (ref_str->subtype == FOURCC_vide) {
4314     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4315         ref_str->from_sample - 1);
4316   } else {
4317     if (ref_str->from_sample >= 10)
4318       k_index = ref_str->from_sample - 10;
4319     else
4320       k_index = 0;
4321   }
4322
4323   target_ts =
4324       ref_str->samples[k_index].timestamp +
4325       ref_str->samples[k_index].pts_offset;
4326
4327   /* get current segment for that stream */
4328   seg = &ref_str->segments[ref_str->segment_index];
4329   /* Use segment start in original timescale for comparisons */
4330   seg_media_start_mov = seg->trak_media_start;
4331
4332   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4333       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4334       k_index, target_ts, seg_media_start_mov,
4335       GST_TIME_ARGS (seg->media_start));
4336
4337   /* Crawl back through segments to find the one containing this I frame */
4338   while (target_ts < seg_media_start_mov) {
4339     GST_DEBUG_OBJECT (qtdemux,
4340         "keyframe position (sample %u) is out of segment %u " " target %"
4341         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4342         ref_str->segment_index, target_ts, seg_media_start_mov);
4343
4344     if (G_UNLIKELY (!ref_str->segment_index)) {
4345       /* Reached first segment, let's consider it's EOS */
4346       goto eos;
4347     }
4348     ref_str->segment_index--;
4349     seg = &ref_str->segments[ref_str->segment_index];
4350     /* Use segment start in original timescale for comparisons */
4351     seg_media_start_mov = seg->trak_media_start;
4352   }
4353   /* Calculate time position of the keyframe and where we should stop */
4354   k_pos =
4355       QTSTREAMTIME_TO_GSTTIME (ref_str,
4356       target_ts - seg->trak_media_start) + seg->time;
4357   last_stop =
4358       QTSTREAMTIME_TO_GSTTIME (ref_str,
4359       ref_str->samples[ref_str->from_sample].timestamp -
4360       seg->trak_media_start) + seg->time;
4361
4362   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4363       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4364       k_index, GST_TIME_ARGS (k_pos));
4365
4366   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4367   qtdemux->segment.position = last_stop;
4368   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4369       GST_TIME_ARGS (last_stop));
4370
4371   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4372     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4373     goto eos;
4374   }
4375
4376   ref_seg_idx = ref_str->segment_index;
4377   ref_k_index = k_index;
4378
4379   /* Align them all on this */
4380   for (n = 0; n < qtdemux->n_streams; n++) {
4381     guint32 index = 0;
4382     GstClockTime seg_time = 0;
4383     QtDemuxStream *str = qtdemux->streams[n];
4384
4385     /* aligning reference stream again might lead to backing up to yet another
4386      * keyframe (due to timestamp rounding issues),
4387      * potentially putting more load on downstream; so let's try to avoid */
4388     if (str == ref_str) {
4389       seg_idx = ref_seg_idx;
4390       seg = &str->segments[seg_idx];
4391       k_index = ref_k_index;
4392       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4393           "sample at index %d", n, ref_str->segment_index, k_index);
4394     } else {
4395       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4396       GST_DEBUG_OBJECT (qtdemux,
4397           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4398           seg_idx, GST_TIME_ARGS (k_pos));
4399
4400       /* get segment and time in the segment */
4401       seg = &str->segments[seg_idx];
4402       seg_time = k_pos - seg->time;
4403
4404       /* get the media time in the segment.
4405        * No adjustment for empty "filler" segments */
4406       if (seg->media_start != GST_CLOCK_TIME_NONE)
4407         seg_time += seg->media_start;
4408
4409       /* get the index of the sample with media time */
4410       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4411       GST_DEBUG_OBJECT (qtdemux,
4412           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4413           GST_TIME_ARGS (seg_time), index);
4414
4415       /* find previous keyframe */
4416       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4417     }
4418
4419     /* Remember until where we want to go */
4420     str->to_sample = str->from_sample - 1;
4421     /* Define our time position */
4422     target_ts =
4423         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4424     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4425     if (seg->media_start != GST_CLOCK_TIME_NONE)
4426       str->time_position -= seg->media_start;
4427
4428     /* Now seek back in time */
4429     gst_qtdemux_move_stream (qtdemux, str, k_index);
4430     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4431         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4432         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4433   }
4434
4435   return GST_FLOW_OK;
4436
4437 eos:
4438   return GST_FLOW_EOS;
4439 }
4440
4441 /*
4442  * Gets the current qt segment start, stop and position for the
4443  * given time offset. This is used in update_segment()
4444  */
4445 static void
4446 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4447     QtDemuxStream * stream, GstClockTime offset,
4448     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4449 {
4450   GstClockTime seg_time;
4451   GstClockTime start, stop, time;
4452   QtDemuxSegment *segment;
4453
4454   segment = &stream->segments[stream->segment_index];
4455
4456   /* get time in this segment */
4457   seg_time = (offset - segment->time) * segment->rate;
4458
4459   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4460       GST_TIME_ARGS (seg_time));
4461
4462   if (G_UNLIKELY (seg_time > segment->duration)) {
4463     GST_LOG_OBJECT (stream->pad,
4464         "seg_time > segment->duration %" GST_TIME_FORMAT,
4465         GST_TIME_ARGS (segment->duration));
4466     seg_time = segment->duration;
4467   }
4468
4469   /* qtdemux->segment.stop is in outside-time-realm, whereas
4470    * segment->media_stop is in track-time-realm.
4471    *
4472    * In order to compare the two, we need to bring segment.stop
4473    * into the track-time-realm
4474    *
4475    * FIXME - does this comment still hold? Don't see any conversion here */
4476
4477   stop = qtdemux->segment.stop;
4478   if (stop == GST_CLOCK_TIME_NONE)
4479     stop = qtdemux->segment.duration;
4480   if (stop == GST_CLOCK_TIME_NONE)
4481     stop = segment->media_stop;
4482   else
4483     stop =
4484         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4485
4486   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4487     start = segment->time + seg_time;
4488     time = offset;
4489     stop = start - seg_time + segment->duration;
4490   } else if (qtdemux->segment.rate >= 0) {
4491     start = MIN (segment->media_start + seg_time, stop);
4492     time = offset;
4493   } else {
4494     if (segment->media_start >= qtdemux->segment.start) {
4495       time = segment->time;
4496     } else {
4497       time = segment->time + (qtdemux->segment.start - segment->media_start);
4498     }
4499
4500     start = MAX (segment->media_start, qtdemux->segment.start);
4501     stop = MIN (segment->media_start + seg_time, stop);
4502   }
4503
4504   *_start = start;
4505   *_stop = stop;
4506   *_time = time;
4507 }
4508
4509 /*
4510  * Updates the qt segment used for the stream and pushes a new segment event
4511  * downstream on this stream's pad.
4512  */
4513 static gboolean
4514 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4515     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4516     GstClockTime * _stop)
4517 {
4518   QtDemuxSegment *segment;
4519   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4520   gdouble rate;
4521   GstEvent *event;
4522
4523   /* update the current segment */
4524   stream->segment_index = seg_idx;
4525
4526   /* get the segment */
4527   segment = &stream->segments[seg_idx];
4528
4529   if (G_UNLIKELY (offset < segment->time)) {
4530     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4531         GST_TIME_ARGS (segment->time));
4532     return FALSE;
4533   }
4534
4535   /* segment lies beyond total indicated duration */
4536   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4537           segment->time > qtdemux->segment.duration)) {
4538     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4539         " < segment->time %" GST_TIME_FORMAT,
4540         GST_TIME_ARGS (qtdemux->segment.duration),
4541         GST_TIME_ARGS (segment->time));
4542     return FALSE;
4543   }
4544
4545   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4546       &start, &stop, &time);
4547
4548   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4549       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4550       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4551
4552   /* combine global rate with that of the segment */
4553   rate = segment->rate * qtdemux->segment.rate;
4554
4555   /* Copy flags from main segment */
4556   stream->segment.flags = qtdemux->segment.flags;
4557
4558   /* update the segment values used for clipping */
4559   stream->segment.offset = qtdemux->segment.offset;
4560   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4561   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4562   stream->segment.rate = rate;
4563   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4564       stream->cslg_shift);
4565   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4566       stream->cslg_shift);
4567   stream->segment.time = time;
4568   stream->segment.position = stream->segment.start;
4569
4570   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4571       &stream->segment);
4572
4573   /* now prepare and send the segment */
4574   if (stream->pad) {
4575     event = gst_event_new_segment (&stream->segment);
4576     if (qtdemux->segment_seqnum) {
4577       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4578     }
4579     gst_pad_push_event (stream->pad, event);
4580     /* assume we can send more data now */
4581     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4582     /* clear to send tags on this pad now */
4583     gst_qtdemux_push_tags (qtdemux, stream);
4584   }
4585
4586   if (_start)
4587     *_start = start;
4588   if (_stop)
4589     *_stop = stop;
4590
4591   return TRUE;
4592 }
4593
4594 /* activate the given segment number @seg_idx of @stream at time @offset.
4595  * @offset is an absolute global position over all the segments.
4596  *
4597  * This will push out a NEWSEGMENT event with the right values and
4598  * position the stream index to the first decodable sample before
4599  * @offset.
4600  */
4601 static gboolean
4602 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4603     guint32 seg_idx, GstClockTime offset)
4604 {
4605   QtDemuxSegment *segment;
4606   guint32 index, kf_index;
4607   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4608
4609   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4610       seg_idx, GST_TIME_ARGS (offset));
4611
4612   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4613           &start, &stop))
4614     return FALSE;
4615
4616   segment = &stream->segments[stream->segment_index];
4617
4618   /* in the fragmented case, we pick a fragment that starts before our
4619    * desired position and rely on downstream to wait for a keyframe
4620    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4621    * tfra entries tells us which trun/sample the key unit is in, but we don't
4622    * make use of this additional information at the moment) */
4623   if (qtdemux->fragmented) {
4624     stream->to_sample = G_MAXUINT32;
4625     return TRUE;
4626   }
4627
4628   /* We don't need to look for a sample in push-based */
4629   if (!qtdemux->pullbased)
4630     return TRUE;
4631
4632   /* and move to the keyframe before the indicated media time of the
4633    * segment */
4634   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4635     if (qtdemux->segment.rate >= 0) {
4636       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4637       stream->to_sample = G_MAXUINT32;
4638       GST_DEBUG_OBJECT (stream->pad,
4639           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4640           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4641           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4642     } else {
4643       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4644       stream->to_sample = index;
4645       GST_DEBUG_OBJECT (stream->pad,
4646           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4647           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4648           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4649     }
4650   } else {
4651     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4652         "this is an empty segment");
4653     return TRUE;
4654   }
4655
4656   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4657    * encountered an error and printed a message so we return appropriately */
4658   if (index == -1)
4659     return FALSE;
4660
4661   /* we're at the right spot */
4662   if (index == stream->sample_index) {
4663     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4664     return TRUE;
4665   }
4666
4667   /* find keyframe of the target index */
4668   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4669
4670 /* *INDENT-OFF* */
4671 /* indent does stupid stuff with stream->samples[].timestamp */
4672
4673   /* if we move forwards, we don't have to go back to the previous
4674    * keyframe since we already sent that. We can also just jump to
4675    * the keyframe right before the target index if there is one. */
4676   if (index > stream->sample_index) {
4677     /* moving forwards check if we move past a keyframe */
4678     if (kf_index > stream->sample_index) {
4679       GST_DEBUG_OBJECT (stream->pad,
4680            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4681            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4682            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4683       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4684     } else {
4685       GST_DEBUG_OBJECT (stream->pad,
4686           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4687           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4688           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4689     }
4690   } else {
4691     GST_DEBUG_OBJECT (stream->pad,
4692         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4693         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4694         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4695     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4696   }
4697
4698 /* *INDENT-ON* */
4699
4700   return TRUE;
4701 }
4702
4703 /* prepare to get the current sample of @stream, getting essential values.
4704  *
4705  * This function will also prepare and send the segment when needed.
4706  *
4707  * Return FALSE if the stream is EOS.
4708  *
4709  * PULL-BASED
4710  */
4711 static gboolean
4712 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4713     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4714     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4715     gboolean * keyframe)
4716 {
4717   QtDemuxSample *sample;
4718   GstClockTime time_position;
4719   guint32 seg_idx;
4720
4721   g_return_val_if_fail (stream != NULL, FALSE);
4722
4723   time_position = stream->time_position;
4724   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4725     goto eos;
4726
4727   seg_idx = stream->segment_index;
4728   if (G_UNLIKELY (seg_idx == -1)) {
4729     /* find segment corresponding to time_position if we are looking
4730      * for a segment. */
4731     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4732   }
4733
4734   /* different segment, activate it, sample_index will be set. */
4735   if (G_UNLIKELY (stream->segment_index != seg_idx))
4736     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4737
4738   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4739                   segment_index]))) {
4740     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4741
4742     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4743         " prepare empty sample");
4744
4745     *empty = TRUE;
4746     *pts = *dts = time_position;
4747     *duration = seg->duration - (time_position - seg->time);
4748
4749     return TRUE;
4750   }
4751
4752   *empty = FALSE;
4753
4754   if (stream->sample_index == -1)
4755     stream->sample_index = 0;
4756
4757   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4758       stream->sample_index, stream->n_samples);
4759
4760   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4761     if (!qtdemux->fragmented)
4762       goto eos;
4763
4764     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4765     do {
4766       GstFlowReturn flow;
4767
4768       GST_OBJECT_LOCK (qtdemux);
4769       flow = qtdemux_add_fragmented_samples (qtdemux);
4770       GST_OBJECT_UNLOCK (qtdemux);
4771
4772       if (flow != GST_FLOW_OK)
4773         goto eos;
4774     }
4775     while (stream->sample_index >= stream->n_samples);
4776   }
4777
4778   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4779     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4780         stream->sample_index);
4781     return FALSE;
4782   }
4783
4784   /* now get the info for the sample we're at */
4785   sample = &stream->samples[stream->sample_index];
4786
4787   *dts = QTSAMPLE_DTS (stream, sample);
4788   *pts = QTSAMPLE_PTS (stream, sample);
4789   *offset = sample->offset;
4790   *size = sample->size;
4791   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4792   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4793
4794   return TRUE;
4795
4796   /* special cases */
4797 eos:
4798   {
4799     stream->time_position = GST_CLOCK_TIME_NONE;
4800     return FALSE;
4801   }
4802 }
4803
4804 /* move to the next sample in @stream.
4805  *
4806  * Moves to the next segment when needed.
4807  */
4808 static void
4809 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4810 {
4811   QtDemuxSample *sample;
4812   QtDemuxSegment *segment;
4813
4814   /* get current segment */
4815   segment = &stream->segments[stream->segment_index];
4816
4817   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4818     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4819     goto next_segment;
4820   }
4821
4822   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4823     /* Mark the stream as EOS */
4824     GST_DEBUG_OBJECT (qtdemux,
4825         "reached max allowed sample %u, mark EOS", stream->to_sample);
4826     stream->time_position = GST_CLOCK_TIME_NONE;
4827     return;
4828   }
4829
4830   /* move to next sample */
4831   stream->sample_index++;
4832   stream->offset_in_sample = 0;
4833
4834   /* reached the last sample, we need the next segment */
4835   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4836     goto next_segment;
4837
4838   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4839     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4840         stream->sample_index);
4841     return;
4842   }
4843
4844   /* get next sample */
4845   sample = &stream->samples[stream->sample_index];
4846
4847   /* see if we are past the segment */
4848   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4849     goto next_segment;
4850
4851   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4852     /* inside the segment, update time_position, looks very familiar to
4853      * GStreamer segments, doesn't it? */
4854     stream->time_position =
4855         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4856   } else {
4857     /* not yet in segment, time does not yet increment. This means
4858      * that we are still prerolling keyframes to the decoder so it can
4859      * decode the first sample of the segment. */
4860     stream->time_position = segment->time;
4861   }
4862   return;
4863
4864   /* move to the next segment */
4865 next_segment:
4866   {
4867     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4868
4869     if (stream->segment_index == stream->n_segments - 1) {
4870       /* are we at the end of the last segment, we're EOS */
4871       stream->time_position = GST_CLOCK_TIME_NONE;
4872     } else {
4873       /* else we're only at the end of the current segment */
4874       stream->time_position = segment->stop_time;
4875     }
4876     /* make sure we select a new segment */
4877
4878     /* accumulate previous segments */
4879     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4880       stream->accumulated_base +=
4881           (stream->segment.stop -
4882           stream->segment.start) / ABS (stream->segment.rate);
4883
4884     stream->segment_index = -1;
4885   }
4886 }
4887
4888 static void
4889 gst_qtdemux_sync_streams (GstQTDemux * demux)
4890 {
4891   gint i;
4892
4893   if (demux->n_streams <= 1)
4894     return;
4895
4896   for (i = 0; i < demux->n_streams; i++) {
4897     QtDemuxStream *stream;
4898     GstClockTime end_time;
4899
4900     stream = demux->streams[i];
4901
4902     if (!stream->pad)
4903       continue;
4904
4905     /* TODO advance time on subtitle streams here, if any some day */
4906
4907     /* some clips/trailers may have unbalanced streams at the end,
4908      * so send EOS on shorter stream to prevent stalling others */
4909
4910     /* do not mess with EOS if SEGMENT seeking */
4911     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4912       continue;
4913
4914     if (demux->pullbased) {
4915       /* loop mode is sample time based */
4916       if (!STREAM_IS_EOS (stream))
4917         continue;
4918     } else {
4919       /* push mode is byte position based */
4920       if (stream->n_samples &&
4921           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4922         continue;
4923     }
4924
4925     if (stream->sent_eos)
4926       continue;
4927
4928     /* only act if some gap */
4929     end_time = stream->segments[stream->n_segments - 1].stop_time;
4930     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4931         ", stream end: %" GST_TIME_FORMAT,
4932         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4933     if (GST_CLOCK_TIME_IS_VALID (end_time)
4934         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4935       GstEvent *event;
4936
4937       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4938           GST_PAD_NAME (stream->pad));
4939       stream->sent_eos = TRUE;
4940       event = gst_event_new_eos ();
4941       if (demux->segment_seqnum)
4942         gst_event_set_seqnum (event, demux->segment_seqnum);
4943       gst_pad_push_event (stream->pad, event);
4944     }
4945   }
4946 }
4947
4948 /* EOS and NOT_LINKED need to be combined. This means that we return:
4949  *
4950  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4951  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4952  */
4953 static GstFlowReturn
4954 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4955     GstFlowReturn ret)
4956 {
4957   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4958
4959   if (stream->pad)
4960     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4961         ret);
4962   else
4963     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4964
4965   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4966   return ret;
4967 }
4968
4969 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4970  * completely clipped
4971  *
4972  * Should be used only with raw buffers */
4973 static GstBuffer *
4974 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4975     GstBuffer * buf)
4976 {
4977   guint64 start, stop, cstart, cstop, diff;
4978   GstClockTime pts, duration;
4979   gsize size, osize;
4980   gint num_rate, denom_rate;
4981   gint frame_size;
4982   gboolean clip_data;
4983   guint offset;
4984
4985   osize = size = gst_buffer_get_size (buf);
4986   offset = 0;
4987
4988   /* depending on the type, setup the clip parameters */
4989   if (stream->subtype == FOURCC_soun) {
4990     frame_size = stream->bytes_per_frame;
4991     num_rate = GST_SECOND;
4992     denom_rate = (gint) stream->rate;
4993     clip_data = TRUE;
4994   } else if (stream->subtype == FOURCC_vide) {
4995     frame_size = size;
4996     num_rate = stream->fps_n;
4997     denom_rate = stream->fps_d;
4998     clip_data = FALSE;
4999   } else
5000     goto wrong_type;
5001
5002   if (frame_size <= 0)
5003     goto bad_frame_size;
5004
5005   /* we can only clip if we have a valid pts */
5006   pts = GST_BUFFER_PTS (buf);
5007   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5008     goto no_pts;
5009
5010   duration = GST_BUFFER_DURATION (buf);
5011
5012   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5013     duration =
5014         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5015   }
5016
5017   start = pts;
5018   stop = start + duration;
5019
5020   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5021               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5022     goto clipped;
5023
5024   /* see if some clipping happened */
5025   diff = cstart - start;
5026   if (diff > 0) {
5027     pts += diff;
5028     duration -= diff;
5029
5030     if (clip_data) {
5031       /* bring clipped time to samples and to bytes */
5032       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5033       diff *= frame_size;
5034
5035       GST_DEBUG_OBJECT (qtdemux,
5036           "clipping start to %" GST_TIME_FORMAT " %"
5037           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5038
5039       offset = diff;
5040       size -= diff;
5041     }
5042   }
5043   diff = stop - cstop;
5044   if (diff > 0) {
5045     duration -= diff;
5046
5047     if (clip_data) {
5048       /* bring clipped time to samples and then to bytes */
5049       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5050       diff *= frame_size;
5051       GST_DEBUG_OBJECT (qtdemux,
5052           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5053           " bytes", GST_TIME_ARGS (cstop), diff);
5054       size -= diff;
5055     }
5056   }
5057
5058   if (offset != 0 || size != osize)
5059     gst_buffer_resize (buf, offset, size);
5060
5061   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5062   GST_BUFFER_PTS (buf) = pts;
5063   GST_BUFFER_DURATION (buf) = duration;
5064
5065   return buf;
5066
5067   /* dropped buffer */
5068 wrong_type:
5069   {
5070     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5071     return buf;
5072   }
5073 bad_frame_size:
5074   {
5075     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5076     return buf;
5077   }
5078 no_pts:
5079   {
5080     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5081     return buf;
5082   }
5083 clipped:
5084   {
5085     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5086     gst_buffer_unref (buf);
5087     return NULL;
5088   }
5089 }
5090
5091 /* the input buffer metadata must be writable,
5092  * but time/duration etc not yet set and need not be preserved */
5093 static GstBuffer *
5094 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5095     GstBuffer * buf)
5096 {
5097   GstMapInfo map;
5098   guint nsize = 0;
5099   gchar *str;
5100
5101   /* not many cases for now */
5102   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5103     /* send a one time dvd clut event */
5104     if (stream->pending_event && stream->pad)
5105       gst_pad_push_event (stream->pad, stream->pending_event);
5106     stream->pending_event = NULL;
5107   }
5108
5109   if (G_UNLIKELY (stream->subtype != FOURCC_text
5110           && stream->subtype != FOURCC_sbtl &&
5111           stream->subtype != FOURCC_subp)) {
5112     return buf;
5113   }
5114
5115   gst_buffer_map (buf, &map, GST_MAP_READ);
5116
5117   /* empty buffer is sent to terminate previous subtitle */
5118   if (map.size <= 2) {
5119     gst_buffer_unmap (buf, &map);
5120     gst_buffer_unref (buf);
5121     return NULL;
5122   }
5123   if (stream->subtype == FOURCC_subp) {
5124     /* That's all the processing needed for subpictures */
5125     gst_buffer_unmap (buf, &map);
5126     return buf;
5127   }
5128
5129   nsize = GST_READ_UINT16_BE (map.data);
5130   nsize = MIN (nsize, map.size - 2);
5131
5132   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5133       nsize, map.size);
5134
5135   /* takes care of UTF-8 validation or UTF-16 recognition,
5136    * no other encoding expected */
5137   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5138   gst_buffer_unmap (buf, &map);
5139   if (str) {
5140     gst_buffer_unref (buf);
5141     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5142   } else {
5143     /* this should not really happen unless the subtitle is corrupted */
5144     gst_buffer_unref (buf);
5145     buf = NULL;
5146   }
5147
5148   /* FIXME ? convert optional subsequent style info to markup */
5149
5150   return buf;
5151 }
5152
5153 /* Sets a buffer's attributes properly and pushes it downstream.
5154  * Also checks for additional actions and custom processing that may
5155  * need to be done first.
5156  */
5157 static GstFlowReturn
5158 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5159     QtDemuxStream * stream, GstBuffer * buf,
5160     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5161     gboolean keyframe, GstClockTime position, guint64 byte_position)
5162 {
5163   GstFlowReturn ret = GST_FLOW_OK;
5164
5165   /* offset the timestamps according to the edit list */
5166
5167   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5168     gchar *url;
5169     GstMapInfo map;
5170
5171     gst_buffer_map (buf, &map, GST_MAP_READ);
5172     url = g_strndup ((gchar *) map.data, map.size);
5173     gst_buffer_unmap (buf, &map);
5174     if (url != NULL && strlen (url) != 0) {
5175       /* we have RTSP redirect now */
5176       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5177           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5178               gst_structure_new ("redirect",
5179                   "new-location", G_TYPE_STRING, url, NULL)));
5180       qtdemux->posted_redirect = TRUE;
5181     } else {
5182       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5183           "posting");
5184     }
5185     g_free (url);
5186   }
5187
5188   /* position reporting */
5189   if (qtdemux->segment.rate >= 0) {
5190     qtdemux->segment.position = position;
5191     gst_qtdemux_sync_streams (qtdemux);
5192   }
5193
5194   if (G_UNLIKELY (!stream->pad)) {
5195     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5196     gst_buffer_unref (buf);
5197     goto exit;
5198   }
5199
5200   /* send out pending buffers */
5201   while (stream->buffers) {
5202     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5203
5204     if (G_UNLIKELY (stream->discont)) {
5205       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5206       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5207       stream->discont = FALSE;
5208     } else {
5209       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5210     }
5211
5212     gst_pad_push (stream->pad, buffer);
5213
5214     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5215   }
5216
5217   /* we're going to modify the metadata */
5218   buf = gst_buffer_make_writable (buf);
5219
5220   if (G_UNLIKELY (stream->need_process))
5221     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5222
5223   if (!buf) {
5224     goto exit;
5225   }
5226
5227   GST_BUFFER_DTS (buf) = dts;
5228   GST_BUFFER_PTS (buf) = pts;
5229   GST_BUFFER_DURATION (buf) = duration;
5230   GST_BUFFER_OFFSET (buf) = -1;
5231   GST_BUFFER_OFFSET_END (buf) = -1;
5232
5233   if (G_UNLIKELY (stream->rgb8_palette))
5234     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5235
5236   if (G_UNLIKELY (stream->padding)) {
5237     gst_buffer_resize (buf, stream->padding, -1);
5238   }
5239 #if 0
5240   if (G_UNLIKELY (qtdemux->element_index)) {
5241     GstClockTime stream_time;
5242
5243     stream_time =
5244         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5245         timestamp);
5246     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5247       GST_LOG_OBJECT (qtdemux,
5248           "adding association %" GST_TIME_FORMAT "-> %"
5249           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5250       gst_index_add_association (qtdemux->element_index,
5251           qtdemux->index_id,
5252           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5253           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5254           GST_FORMAT_BYTES, byte_position, NULL);
5255     }
5256   }
5257 #endif
5258
5259   if (stream->need_clip)
5260     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5261
5262   if (G_UNLIKELY (buf == NULL))
5263     goto exit;
5264
5265   if (G_UNLIKELY (stream->discont)) {
5266     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5267     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5268     stream->discont = FALSE;
5269   } else {
5270     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5271   }
5272
5273   if (!keyframe) {
5274     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5275     stream->on_keyframe = FALSE;
5276   } else {
5277     stream->on_keyframe = TRUE;
5278   }
5279
5280
5281   GST_LOG_OBJECT (qtdemux,
5282       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5283       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5284       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5285       GST_PAD_NAME (stream->pad));
5286
5287   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5288     GstStructure *crypto_info;
5289     QtDemuxCencSampleSetInfo *info =
5290         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5291     gint index;
5292     GstEvent *event;
5293
5294     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5295       gst_pad_push_event (stream->pad, event);
5296     }
5297
5298     if (qtdemux->cenc_aux_info_offset > 0 && info->crypto_info == NULL) {
5299       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5300       gst_buffer_unref (buf);
5301       goto exit;
5302     }
5303
5304     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
5305     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5306       /* steal structure from array */
5307       crypto_info = g_ptr_array_index (info->crypto_info, index);
5308       g_ptr_array_index (info->crypto_info, index) = NULL;
5309       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
5310       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5311         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5312     }
5313   }
5314
5315   ret = gst_pad_push (stream->pad, buf);
5316
5317   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5318     /* mark position in stream, we'll need this to know when to send GAP event */
5319     stream->segment.position = pts + duration;
5320   }
5321
5322 exit:
5323   return ret;
5324 }
5325
5326 static const QtDemuxRandomAccessEntry *
5327 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5328     GstClockTime pos, gboolean after)
5329 {
5330   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5331   guint n_entries = stream->n_ra_entries;
5332   guint i;
5333
5334   /* we assume the table is sorted */
5335   for (i = 0; i < n_entries; ++i) {
5336     if (entries[i].ts > pos)
5337       break;
5338   }
5339
5340   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5341    * probably okay to assume that the index lists the very first fragment */
5342   if (i == 0)
5343     return &entries[0];
5344
5345   if (after)
5346     return &entries[i];
5347   else
5348     return &entries[i - 1];
5349 }
5350
5351 static gboolean
5352 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5353 {
5354   const QtDemuxRandomAccessEntry *best_entry = NULL;
5355   guint i;
5356
5357   GST_OBJECT_LOCK (qtdemux);
5358
5359   g_assert (qtdemux->n_streams > 0);
5360
5361   for (i = 0; i < qtdemux->n_streams; i++) {
5362     const QtDemuxRandomAccessEntry *entry;
5363     QtDemuxStream *stream;
5364     gboolean is_audio_or_video;
5365
5366     stream = qtdemux->streams[i];
5367
5368     g_free (stream->samples);
5369     stream->samples = NULL;
5370     stream->n_samples = 0;
5371     stream->stbl_index = -1;    /* no samples have yet been parsed */
5372     stream->sample_index = -1;
5373
5374     if (stream->ra_entries == NULL)
5375       continue;
5376
5377     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5378       is_audio_or_video = TRUE;
5379     else
5380       is_audio_or_video = FALSE;
5381
5382     entry =
5383         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5384         stream->time_position, !is_audio_or_video);
5385
5386     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5387         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5388
5389     stream->pending_seek = entry;
5390
5391     /* decide position to jump to just based on audio/video tracks, not subs */
5392     if (!is_audio_or_video)
5393       continue;
5394
5395     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5396       best_entry = entry;
5397   }
5398
5399   if (best_entry == NULL) {
5400     GST_OBJECT_UNLOCK (qtdemux);
5401     return FALSE;
5402   }
5403
5404   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5405       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5406       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5407       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5408
5409   qtdemux->moof_offset = best_entry->moof_offset;
5410
5411   qtdemux_add_fragmented_samples (qtdemux);
5412
5413   GST_OBJECT_UNLOCK (qtdemux);
5414   return TRUE;
5415 }
5416
5417 static GstFlowReturn
5418 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5419 {
5420   GstFlowReturn ret = GST_FLOW_OK;
5421   GstBuffer *buf = NULL;
5422   QtDemuxStream *stream;
5423   GstClockTime min_time;
5424   guint64 offset = 0;
5425   GstClockTime dts = GST_CLOCK_TIME_NONE;
5426   GstClockTime pts = GST_CLOCK_TIME_NONE;
5427   GstClockTime duration = 0;
5428   gboolean keyframe = FALSE;
5429   guint sample_size = 0;
5430   gboolean empty = 0;
5431   guint size;
5432   gint index;
5433   gint i;
5434
5435   gst_qtdemux_push_pending_newsegment (qtdemux);
5436
5437   if (qtdemux->fragmented_seek_pending) {
5438     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5439     gst_qtdemux_do_fragmented_seek (qtdemux);
5440     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5441     qtdemux->fragmented_seek_pending = FALSE;
5442   }
5443
5444   /* Figure out the next stream sample to output, min_time is expressed in
5445    * global time and runs over the edit list segments. */
5446   min_time = G_MAXUINT64;
5447   index = -1;
5448   for (i = 0; i < qtdemux->n_streams; i++) {
5449     GstClockTime position;
5450
5451     stream = qtdemux->streams[i];
5452     position = stream->time_position;
5453
5454     /* position of -1 is EOS */
5455     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5456       min_time = position;
5457       index = i;
5458     }
5459   }
5460   /* all are EOS */
5461   if (G_UNLIKELY (index == -1)) {
5462     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5463     goto eos;
5464   }
5465
5466   /* check for segment end */
5467   if (G_UNLIKELY (qtdemux->segment.stop != -1
5468           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5469               || (qtdemux->segment.rate < 0
5470                   && qtdemux->segment.start > min_time))
5471           && qtdemux->streams[index]->on_keyframe)) {
5472     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5473     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5474     goto eos_stream;
5475   }
5476
5477   /* gap events for subtitle streams */
5478   for (i = 0; i < qtdemux->n_streams; i++) {
5479     stream = qtdemux->streams[i];
5480     if (stream->pad && (stream->subtype == FOURCC_subp
5481             || stream->subtype == FOURCC_text
5482             || stream->subtype == FOURCC_sbtl)) {
5483       /* send one second gap events until the stream catches up */
5484       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5485       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5486           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5487           stream->segment.position + GST_SECOND < min_time) {
5488         GstEvent *gap =
5489             gst_event_new_gap (stream->segment.position, GST_SECOND);
5490         gst_pad_push_event (stream->pad, gap);
5491         stream->segment.position += GST_SECOND;
5492       }
5493     }
5494   }
5495
5496   stream = qtdemux->streams[index];
5497   if (stream->new_caps) {
5498     gst_qtdemux_configure_stream (qtdemux, stream);
5499     qtdemux_do_allocation (qtdemux, stream);
5500   }
5501
5502   /* fetch info for the current sample of this stream */
5503   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5504               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5505     goto eos_stream;
5506
5507   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5508   if (G_UNLIKELY (qtdemux->
5509           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5510     if (stream->subtype == FOURCC_vide && !keyframe) {
5511       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5512       goto next;
5513     }
5514   }
5515
5516   GST_DEBUG_OBJECT (qtdemux,
5517       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5518       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5519       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5520       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5521
5522   if (G_UNLIKELY (empty)) {
5523     /* empty segment, push a gap and move to the next one */
5524     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5525     stream->segment.position = pts + duration;
5526     goto next;
5527   }
5528
5529   /* hmm, empty sample, skip and move to next sample */
5530   if (G_UNLIKELY (sample_size <= 0))
5531     goto next;
5532
5533   /* last pushed sample was out of boundary, goto next sample */
5534   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5535     goto next;
5536
5537   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5538     size = sample_size;
5539   } else {
5540     GST_DEBUG_OBJECT (qtdemux,
5541         "size %d larger than stream max_buffer_size %d, trimming",
5542         sample_size, stream->max_buffer_size);
5543     size =
5544         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5545   }
5546
5547   if (qtdemux->cenc_aux_info_offset > 0) {
5548     GstMapInfo map;
5549     GstByteReader br;
5550     GstBuffer *aux_info = NULL;
5551
5552     /* pull the data stored before the sample */
5553     ret =
5554         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5555         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5556     if (G_UNLIKELY (ret != GST_FLOW_OK))
5557       goto beach;
5558     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5559     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5560     gst_byte_reader_init (&br, map.data + 8, map.size);
5561     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5562             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5563       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5564       gst_buffer_unmap (aux_info, &map);
5565       gst_buffer_unref (aux_info);
5566       ret = GST_FLOW_ERROR;
5567       goto beach;
5568     }
5569     gst_buffer_unmap (aux_info, &map);
5570     gst_buffer_unref (aux_info);
5571   }
5572
5573   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5574       offset);
5575
5576   if (stream->use_allocator) {
5577     /* if we have a per-stream allocator, use it */
5578     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5579   }
5580
5581   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5582       size, &buf);
5583   if (G_UNLIKELY (ret != GST_FLOW_OK))
5584     goto beach;
5585
5586   if (size != sample_size) {
5587     pts += gst_util_uint64_scale_int (GST_SECOND,
5588         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5589     dts += gst_util_uint64_scale_int (GST_SECOND,
5590         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5591     duration = gst_util_uint64_scale_int (GST_SECOND,
5592         size / stream->bytes_per_frame, stream->timescale);
5593   }
5594
5595   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5596       dts, pts, duration, keyframe, min_time, offset);
5597
5598   if (size != sample_size) {
5599     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5600     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5601
5602     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5603         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5604     if (time_position >= segment->media_start) {
5605       /* inside the segment, update time_position, looks very familiar to
5606        * GStreamer segments, doesn't it? */
5607       stream->time_position = (time_position - segment->media_start) +
5608           segment->time;
5609     } else {
5610       /* not yet in segment, time does not yet increment. This means
5611        * that we are still prerolling keyframes to the decoder so it can
5612        * decode the first sample of the segment. */
5613       stream->time_position = segment->time;
5614     }
5615   }
5616
5617   /* combine flows */
5618   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5619   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5620    * we have no more data for the pad to push */
5621   if (ret == GST_FLOW_EOS)
5622     ret = GST_FLOW_OK;
5623
5624   stream->offset_in_sample += size;
5625   if (stream->offset_in_sample >= sample_size) {
5626     gst_qtdemux_advance_sample (qtdemux, stream);
5627   }
5628   goto beach;
5629
5630 next:
5631   gst_qtdemux_advance_sample (qtdemux, stream);
5632
5633 beach:
5634   return ret;
5635
5636   /* special cases */
5637 eos:
5638   {
5639     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5640     ret = GST_FLOW_EOS;
5641     goto beach;
5642   }
5643 eos_stream:
5644   {
5645     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5646     /* EOS will be raised if all are EOS */
5647     ret = GST_FLOW_OK;
5648     goto beach;
5649   }
5650 }
5651
5652 static void
5653 gst_qtdemux_loop (GstPad * pad)
5654 {
5655   GstQTDemux *qtdemux;
5656   guint64 cur_offset;
5657   GstFlowReturn ret;
5658
5659   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5660
5661   cur_offset = qtdemux->offset;
5662   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
5663       cur_offset, qtdemux->state);
5664
5665   switch (qtdemux->state) {
5666     case QTDEMUX_STATE_INITIAL:
5667     case QTDEMUX_STATE_HEADER:
5668       ret = gst_qtdemux_loop_state_header (qtdemux);
5669       break;
5670     case QTDEMUX_STATE_MOVIE:
5671       ret = gst_qtdemux_loop_state_movie (qtdemux);
5672       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5673         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5674       }
5675       break;
5676     default:
5677       /* ouch */
5678       goto invalid_state;
5679   }
5680
5681   /* if something went wrong, pause */
5682   if (ret != GST_FLOW_OK)
5683     goto pause;
5684
5685 done:
5686   gst_object_unref (qtdemux);
5687   return;
5688
5689   /* ERRORS */
5690 invalid_state:
5691   {
5692     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5693         (NULL), ("streaming stopped, invalid state"));
5694     gst_pad_pause_task (pad);
5695     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5696     goto done;
5697   }
5698 pause:
5699   {
5700     const gchar *reason = gst_flow_get_name (ret);
5701
5702     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5703
5704     gst_pad_pause_task (pad);
5705
5706     /* fatal errors need special actions */
5707     /* check EOS */
5708     if (ret == GST_FLOW_EOS) {
5709       if (qtdemux->n_streams == 0) {
5710         /* we have no streams, post an error */
5711         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5712       }
5713       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5714         gint64 stop;
5715
5716         if ((stop = qtdemux->segment.stop) == -1)
5717           stop = qtdemux->segment.duration;
5718
5719         if (qtdemux->segment.rate >= 0) {
5720           GstMessage *message;
5721           GstEvent *event;
5722
5723           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5724           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5725               GST_FORMAT_TIME, stop);
5726           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5727           if (qtdemux->segment_seqnum) {
5728             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5729             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5730           }
5731           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5732           gst_qtdemux_push_event (qtdemux, event);
5733         } else {
5734           GstMessage *message;
5735           GstEvent *event;
5736
5737           /*  For Reverse Playback */
5738           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5739           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5740               GST_FORMAT_TIME, qtdemux->segment.start);
5741           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5742               qtdemux->segment.start);
5743           if (qtdemux->segment_seqnum) {
5744             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5745             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5746           }
5747           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5748           gst_qtdemux_push_event (qtdemux, event);
5749         }
5750       } else {
5751         GstEvent *event;
5752
5753         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5754         event = gst_event_new_eos ();
5755         if (qtdemux->segment_seqnum)
5756           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5757         gst_qtdemux_push_event (qtdemux, event);
5758       }
5759     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5760       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5761           (NULL), ("streaming stopped, reason %s", reason));
5762       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5763     }
5764     goto done;
5765   }
5766 }
5767
5768 /*
5769  * has_next_entry
5770  *
5771  * Returns if there are samples to be played.
5772  */
5773 static gboolean
5774 has_next_entry (GstQTDemux * demux)
5775 {
5776   QtDemuxStream *stream;
5777   int i;
5778
5779   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5780
5781   for (i = 0; i < demux->n_streams; i++) {
5782     stream = demux->streams[i];
5783
5784     if (stream->sample_index == -1) {
5785       stream->sample_index = 0;
5786       stream->offset_in_sample = 0;
5787     }
5788
5789     if (stream->sample_index >= stream->n_samples) {
5790       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5791       continue;
5792     }
5793     GST_DEBUG_OBJECT (demux, "Found a sample");
5794     return TRUE;
5795   }
5796
5797   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5798   return FALSE;
5799 }
5800
5801 /*
5802  * next_entry_size
5803  *
5804  * Returns the size of the first entry at the current offset.
5805  * If -1, there are none (which means EOS or empty file).
5806  */
5807 static guint64
5808 next_entry_size (GstQTDemux * demux)
5809 {
5810   QtDemuxStream *stream;
5811   int i;
5812   int smallidx = -1;
5813   guint64 smalloffs = (guint64) - 1;
5814   QtDemuxSample *sample;
5815
5816   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5817       demux->offset);
5818
5819   for (i = 0; i < demux->n_streams; i++) {
5820     stream = demux->streams[i];
5821
5822     if (stream->sample_index == -1) {
5823       stream->sample_index = 0;
5824       stream->offset_in_sample = 0;
5825     }
5826
5827     if (stream->sample_index >= stream->n_samples) {
5828       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5829       continue;
5830     }
5831
5832     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5833       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5834           stream->sample_index);
5835       return -1;
5836     }
5837
5838     sample = &stream->samples[stream->sample_index];
5839
5840     GST_LOG_OBJECT (demux,
5841         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5842         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5843         sample->offset, sample->size);
5844
5845     if (((smalloffs == -1)
5846             || (sample->offset < smalloffs)) && (sample->size)) {
5847       smallidx = i;
5848       smalloffs = sample->offset;
5849     }
5850   }
5851
5852   GST_LOG_OBJECT (demux,
5853       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5854       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5855
5856   if (smallidx == -1)
5857     return -1;
5858
5859   stream = demux->streams[smallidx];
5860   sample = &stream->samples[stream->sample_index];
5861
5862   if (sample->offset >= demux->offset) {
5863     demux->todrop = sample->offset - demux->offset;
5864     return sample->size + demux->todrop;
5865   }
5866
5867   GST_DEBUG_OBJECT (demux,
5868       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5869   return -1;
5870 }
5871
5872 static void
5873 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5874 {
5875   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5876
5877   gst_element_post_message (GST_ELEMENT_CAST (demux),
5878       gst_message_new_element (GST_OBJECT_CAST (demux),
5879           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5880 }
5881
5882 static gboolean
5883 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5884 {
5885   GstEvent *event;
5886   gboolean res = 0;
5887
5888   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5889
5890   event =
5891       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5892       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5893       GST_SEEK_TYPE_NONE, -1);
5894
5895   /* store seqnum to drop flush events, they don't need to reach downstream */
5896   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5897   res = gst_pad_push_event (demux->sinkpad, event);
5898   demux->offset_seek_seqnum = 0;
5899
5900   return res;
5901 }
5902
5903 /* check for seekable upstream, above and beyond a mere query */
5904 static void
5905 gst_qtdemux_check_seekability (GstQTDemux * demux)
5906 {
5907   GstQuery *query;
5908   gboolean seekable = FALSE;
5909   gint64 start = -1, stop = -1;
5910
5911   if (demux->upstream_size)
5912     return;
5913
5914   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5915   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5916     GST_DEBUG_OBJECT (demux, "seeking query failed");
5917     goto done;
5918   }
5919
5920   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5921
5922   /* try harder to query upstream size if we didn't get it the first time */
5923   if (seekable && stop == -1) {
5924     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5925     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5926   }
5927
5928   /* if upstream doesn't know the size, it's likely that it's not seekable in
5929    * practice even if it technically may be seekable */
5930   if (seekable && (start != 0 || stop <= start)) {
5931     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5932     seekable = FALSE;
5933   }
5934
5935 done:
5936   gst_query_unref (query);
5937
5938   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5939       G_GUINT64_FORMAT ")", seekable, start, stop);
5940   demux->upstream_seekable = seekable;
5941   demux->upstream_size = seekable ? stop : -1;
5942 }
5943
5944 static void
5945 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5946 {
5947   g_return_if_fail (bytes <= demux->todrop);
5948
5949   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5950   gst_adapter_flush (demux->adapter, bytes);
5951   demux->neededbytes -= bytes;
5952   demux->offset += bytes;
5953   demux->todrop -= bytes;
5954 }
5955
5956 static void
5957 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5958 {
5959   if (G_UNLIKELY (demux->pending_newsegment)) {
5960     gint i;
5961
5962     gst_qtdemux_push_pending_newsegment (demux);
5963     /* clear to send tags on all streams */
5964     for (i = 0; i < demux->n_streams; i++) {
5965       QtDemuxStream *stream;
5966       stream = demux->streams[i];
5967       gst_qtdemux_push_tags (demux, stream);
5968       if (stream->sparse) {
5969         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5970         gst_pad_push_event (stream->pad,
5971             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
5972       }
5973     }
5974   }
5975 }
5976
5977 static void
5978 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
5979     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
5980 {
5981   GstClockTime ts, dur;
5982   GstEvent *gap;
5983
5984   ts = pos;
5985   dur =
5986       stream->segments[segment_index].duration - (pos -
5987       stream->segments[segment_index].time);
5988   gap = gst_event_new_gap (ts, dur);
5989   stream->time_position += dur;
5990
5991   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
5992       "segment: %" GST_PTR_FORMAT, gap);
5993   gst_pad_push_event (stream->pad, gap);
5994 }
5995
5996 static void
5997 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
5998     QtDemuxStream * stream)
5999 {
6000   gint i;
6001
6002   /* Push any initial gap segments before proceeding to the
6003    * 'real' data */
6004   for (i = 0; i < stream->n_segments; i++) {
6005     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6006
6007     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6008       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6009           stream->time_position);
6010     } else {
6011       /* Only support empty segment at the beginning followed by
6012        * one non-empty segment, this was checked when parsing the
6013        * edts atom, arriving here is unexpected */
6014       g_assert (i + 1 == stream->n_segments);
6015       break;
6016     }
6017   }
6018 }
6019
6020 static GstFlowReturn
6021 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6022 {
6023   GstQTDemux *demux;
6024
6025   demux = GST_QTDEMUX (parent);
6026
6027   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6028     gint i;
6029
6030     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6031
6032     for (i = 0; i < demux->n_streams; i++) {
6033       demux->streams[i]->discont = TRUE;
6034     }
6035
6036     /* Reverse fragmented playback, need to flush all we have before
6037      * consuming a new fragment.
6038      * The samples array have the timestamps calculated by accumulating the
6039      * durations but this won't work for reverse playback of fragments as
6040      * the timestamps of a subsequent fragment should be smaller than the
6041      * previously received one. */
6042     if (demux->fragmented && demux->segment.rate < 0) {
6043       gst_qtdemux_process_adapter (demux, TRUE);
6044       for (i = 0; i < demux->n_streams; i++)
6045         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6046     }
6047   }
6048
6049   gst_adapter_push (demux->adapter, inbuf);
6050
6051   GST_DEBUG_OBJECT (demux,
6052       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6053       demux->neededbytes, gst_adapter_available (demux->adapter));
6054
6055   return gst_qtdemux_process_adapter (demux, FALSE);
6056 }
6057
6058 static GstFlowReturn
6059 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6060 {
6061   GstFlowReturn ret = GST_FLOW_OK;
6062
6063   /* we never really mean to buffer that much */
6064   if (demux->neededbytes == -1) {
6065     goto eos;
6066   }
6067
6068   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6069       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6070
6071     GST_DEBUG_OBJECT (demux,
6072         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
6073         demux->state, demux->neededbytes, demux->offset);
6074
6075     switch (demux->state) {
6076       case QTDEMUX_STATE_INITIAL:{
6077         const guint8 *data;
6078         guint32 fourcc;
6079         guint64 size;
6080
6081         gst_qtdemux_check_seekability (demux);
6082
6083         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6084
6085         /* get fourcc/length, set neededbytes */
6086         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6087             &size, &fourcc);
6088         gst_adapter_unmap (demux->adapter);
6089         data = NULL;
6090         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6091             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6092         if (size == 0) {
6093           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6094               (_("This file is invalid and cannot be played.")),
6095               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6096                   GST_FOURCC_ARGS (fourcc)));
6097           ret = GST_FLOW_ERROR;
6098           break;
6099         }
6100         if (fourcc == FOURCC_mdat) {
6101           gint next_entry = next_entry_size (demux);
6102           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6103             /* we have the headers, start playback */
6104             demux->state = QTDEMUX_STATE_MOVIE;
6105             demux->neededbytes = next_entry;
6106             demux->mdatleft = size;
6107           } else {
6108             /* no headers yet, try to get them */
6109             guint bs;
6110             gboolean res;
6111             guint64 old, target;
6112
6113           buffer_data:
6114             old = demux->offset;
6115             target = old + size;
6116
6117             /* try to jump over the atom with a seek */
6118             /* only bother if it seems worth doing so,
6119              * and avoids possible upstream/server problems */
6120             if (demux->upstream_seekable &&
6121                 demux->upstream_size > 4 * (1 << 20)) {
6122               res = qtdemux_seek_offset (demux, target);
6123             } else {
6124               GST_DEBUG_OBJECT (demux, "skipping seek");
6125               res = FALSE;
6126             }
6127
6128             if (res) {
6129               GST_DEBUG_OBJECT (demux, "seek success");
6130               /* remember the offset fo the first mdat so we can seek back to it
6131                * after we have the headers */
6132               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6133                 demux->first_mdat = old;
6134                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6135                     demux->first_mdat);
6136               }
6137               /* seek worked, continue reading */
6138               demux->offset = target;
6139               demux->neededbytes = 16;
6140               demux->state = QTDEMUX_STATE_INITIAL;
6141             } else {
6142               /* seek failed, need to buffer */
6143               demux->offset = old;
6144               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6145               /* there may be multiple mdat (or alike) buffers */
6146               /* sanity check */
6147               if (demux->mdatbuffer)
6148                 bs = gst_buffer_get_size (demux->mdatbuffer);
6149               else
6150                 bs = 0;
6151               if (size + bs > 10 * (1 << 20))
6152                 goto no_moov;
6153               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6154               demux->neededbytes = size;
6155               if (!demux->mdatbuffer)
6156                 demux->mdatoffset = demux->offset;
6157             }
6158           }
6159         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6160           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6161               (_("This file is invalid and cannot be played.")),
6162               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6163                   GST_FOURCC_ARGS (fourcc), size));
6164           ret = GST_FLOW_ERROR;
6165           break;
6166         } else {
6167           /* this means we already started buffering and still no moov header,
6168            * let's continue buffering everything till we get moov */
6169           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6170                   || fourcc == FOURCC_moof))
6171             goto buffer_data;
6172           demux->neededbytes = size;
6173           demux->state = QTDEMUX_STATE_HEADER;
6174         }
6175         break;
6176       }
6177       case QTDEMUX_STATE_HEADER:{
6178         const guint8 *data;
6179         guint32 fourcc;
6180
6181         GST_DEBUG_OBJECT (demux, "In header");
6182
6183         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6184
6185         /* parse the header */
6186         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6187             &fourcc);
6188         if (fourcc == FOURCC_moov) {
6189           gint n;
6190
6191           /* in usual fragmented setup we could try to scan for more
6192            * and end up at the the moov (after mdat) again */
6193           if (demux->got_moov && demux->n_streams > 0 &&
6194               (!demux->fragmented
6195                   || demux->last_moov_offset == demux->offset)) {
6196             GST_DEBUG_OBJECT (demux,
6197                 "Skipping moov atom as we have (this) one already");
6198           } else {
6199             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6200
6201             if (demux->got_moov && demux->fragmented) {
6202               GST_DEBUG_OBJECT (demux,
6203                   "Got a second moov, clean up data from old one");
6204               if (demux->moov_node)
6205                 g_node_destroy (demux->moov_node);
6206               demux->moov_node = NULL;
6207               demux->moov_node_compressed = NULL;
6208             } else {
6209               /* prepare newsegment to send when streaming actually starts */
6210               if (!demux->pending_newsegment) {
6211                 demux->pending_newsegment =
6212                     gst_event_new_segment (&demux->segment);
6213                 if (demux->segment_seqnum)
6214                   gst_event_set_seqnum (demux->pending_newsegment,
6215                       demux->segment_seqnum);
6216               }
6217             }
6218
6219             demux->last_moov_offset = demux->offset;
6220
6221             qtdemux_parse_moov (demux, data, demux->neededbytes);
6222             qtdemux_node_dump (demux, demux->moov_node);
6223             qtdemux_parse_tree (demux);
6224             qtdemux_prepare_streams (demux);
6225             if (!demux->got_moov)
6226               qtdemux_expose_streams (demux);
6227             else {
6228
6229               for (n = 0; n < demux->n_streams; n++) {
6230                 QtDemuxStream *stream = demux->streams[n];
6231
6232                 gst_qtdemux_configure_stream (demux, stream);
6233               }
6234             }
6235
6236             demux->got_moov = TRUE;
6237             gst_qtdemux_check_send_pending_segment (demux);
6238
6239             /* fragmented streams headers shouldn't contain edts atoms */
6240             if (!demux->fragmented) {
6241               for (n = 0; n < demux->n_streams; n++) {
6242                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6243                     demux->streams[n]);
6244               }
6245             }
6246
6247             g_node_destroy (demux->moov_node);
6248             demux->moov_node = NULL;
6249             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6250           }
6251         } else if (fourcc == FOURCC_moof) {
6252           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6253             guint64 dist = 0;
6254             GstClockTime prev_pts;
6255             guint64 prev_offset;
6256
6257             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6258
6259             /*
6260              * The timestamp of the moof buffer is relevant as some scenarios
6261              * won't have the initial timestamp in the atoms. Whenever a new
6262              * buffer has started, we get that buffer's PTS and use it as a base
6263              * timestamp for the trun entries.
6264              *
6265              * To keep track of the current buffer timestamp and starting point
6266              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6267              * from the beggining of the buffer, with the distance and demux->offset
6268              * we know if it is still the same buffer or not.
6269              */
6270             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6271             prev_offset = demux->offset - dist;
6272             if (demux->fragment_start_offset == -1
6273                 || prev_offset > demux->fragment_start_offset) {
6274               demux->fragment_start_offset = prev_offset;
6275               demux->fragment_start = prev_pts;
6276               GST_DEBUG_OBJECT (demux,
6277                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6278                   GST_TIME_FORMAT, demux->fragment_start_offset,
6279                   GST_TIME_ARGS (demux->fragment_start));
6280             }
6281
6282             demux->moof_offset = demux->offset;
6283             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6284                     demux->offset, NULL)) {
6285               gst_adapter_unmap (demux->adapter);
6286               ret = GST_FLOW_ERROR;
6287               goto done;
6288             }
6289             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6290             if (demux->mss_mode && !demux->exposed) {
6291               if (!demux->pending_newsegment) {
6292                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6293                 demux->pending_newsegment =
6294                     gst_event_new_segment (&demux->segment);
6295                 if (demux->segment_seqnum)
6296                   gst_event_set_seqnum (demux->pending_newsegment,
6297                       demux->segment_seqnum);
6298               }
6299               qtdemux_expose_streams (demux);
6300             }
6301           } else {
6302             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6303           }
6304         } else if (fourcc == FOURCC_ftyp) {
6305           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6306           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6307         } else if (fourcc == FOURCC_uuid) {
6308           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6309           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6310         } else if (fourcc == FOURCC_sidx) {
6311           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6312           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6313         } else {
6314           GST_WARNING_OBJECT (demux,
6315               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6316               GST_FOURCC_ARGS (fourcc));
6317           /* Let's jump that one and go back to initial state */
6318         }
6319         gst_adapter_unmap (demux->adapter);
6320         data = NULL;
6321
6322         if (demux->mdatbuffer && demux->n_streams) {
6323           gsize remaining_data_size = 0;
6324
6325           /* the mdat was before the header */
6326           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6327               demux->n_streams, demux->mdatbuffer);
6328           /* restore our adapter/offset view of things with upstream;
6329            * put preceding buffered data ahead of current moov data.
6330            * This should also handle evil mdat, moov, mdat cases and alike */
6331           gst_adapter_flush (demux->adapter, demux->neededbytes);
6332
6333           /* Store any remaining data after the mdat for later usage */
6334           remaining_data_size = gst_adapter_available (demux->adapter);
6335           if (remaining_data_size > 0) {
6336             g_assert (demux->restoredata_buffer == NULL);
6337             demux->restoredata_buffer =
6338                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6339             demux->restoredata_offset = demux->offset + demux->neededbytes;
6340             GST_DEBUG_OBJECT (demux,
6341                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6342                 G_GUINT64_FORMAT, remaining_data_size,
6343                 demux->restoredata_offset);
6344           }
6345
6346           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6347           demux->mdatbuffer = NULL;
6348           demux->offset = demux->mdatoffset;
6349           demux->neededbytes = next_entry_size (demux);
6350           demux->state = QTDEMUX_STATE_MOVIE;
6351           demux->mdatleft = gst_adapter_available (demux->adapter);
6352         } else {
6353           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6354           gst_adapter_flush (demux->adapter, demux->neededbytes);
6355
6356           /* only go back to the mdat if there are samples to play */
6357           if (demux->got_moov && demux->first_mdat != -1
6358               && has_next_entry (demux)) {
6359             gboolean res;
6360
6361             /* we need to seek back */
6362             res = qtdemux_seek_offset (demux, demux->first_mdat);
6363             if (res) {
6364               demux->offset = demux->first_mdat;
6365             } else {
6366               GST_DEBUG_OBJECT (demux, "Seek back failed");
6367             }
6368           } else {
6369             demux->offset += demux->neededbytes;
6370           }
6371           demux->neededbytes = 16;
6372           demux->state = QTDEMUX_STATE_INITIAL;
6373         }
6374
6375         break;
6376       }
6377       case QTDEMUX_STATE_BUFFER_MDAT:{
6378         GstBuffer *buf;
6379         guint8 fourcc[4];
6380
6381         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6382             demux->offset);
6383         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6384         gst_buffer_extract (buf, 0, fourcc, 4);
6385         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6386             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6387         if (demux->mdatbuffer)
6388           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6389         else
6390           demux->mdatbuffer = buf;
6391         demux->offset += demux->neededbytes;
6392         demux->neededbytes = 16;
6393         demux->state = QTDEMUX_STATE_INITIAL;
6394         gst_qtdemux_post_progress (demux, 1, 1);
6395
6396         break;
6397       }
6398       case QTDEMUX_STATE_MOVIE:{
6399         QtDemuxStream *stream = NULL;
6400         QtDemuxSample *sample;
6401         int i = -1;
6402         GstClockTime dts, pts, duration;
6403         gboolean keyframe;
6404
6405         GST_DEBUG_OBJECT (demux,
6406             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6407
6408         if (demux->fragmented) {
6409           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6410               demux->mdatleft);
6411           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6412             /* if needed data starts within this atom,
6413              * then it should not exceed this atom */
6414             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6415               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6416                   (_("This file is invalid and cannot be played.")),
6417                   ("sample data crosses atom boundary"));
6418               ret = GST_FLOW_ERROR;
6419               break;
6420             }
6421             demux->mdatleft -= demux->neededbytes;
6422           } else {
6423             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6424             /* so we are dropping more than left in this atom */
6425             gst_qtdemux_drop_data (demux, demux->mdatleft);
6426             demux->mdatleft = 0;
6427
6428             /* need to resume atom parsing so we do not miss any other pieces */
6429             demux->state = QTDEMUX_STATE_INITIAL;
6430             demux->neededbytes = 16;
6431
6432             /* check if there was any stored post mdat data from previous buffers */
6433             if (demux->restoredata_buffer) {
6434               g_assert (gst_adapter_available (demux->adapter) == 0);
6435
6436               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6437               demux->restoredata_buffer = NULL;
6438               demux->offset = demux->restoredata_offset;
6439             }
6440
6441             break;
6442           }
6443         }
6444
6445         if (demux->todrop) {
6446           if (demux->cenc_aux_info_offset > 0) {
6447             GstByteReader br;
6448             const guint8 *data;
6449
6450             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6451             data = gst_adapter_map (demux->adapter, demux->todrop);
6452             gst_byte_reader_init (&br, data + 8, demux->todrop);
6453             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6454                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6455               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6456               ret = GST_FLOW_ERROR;
6457               gst_adapter_unmap (demux->adapter);
6458               g_free (demux->cenc_aux_info_sizes);
6459               demux->cenc_aux_info_sizes = NULL;
6460               goto done;
6461             }
6462             demux->cenc_aux_info_offset = 0;
6463             g_free (demux->cenc_aux_info_sizes);
6464             demux->cenc_aux_info_sizes = NULL;
6465             gst_adapter_unmap (demux->adapter);
6466           }
6467           gst_qtdemux_drop_data (demux, demux->todrop);
6468         }
6469
6470         /* first buffer? */
6471         /* initial newsegment sent here after having added pads,
6472          * possible others in sink_event */
6473         gst_qtdemux_check_send_pending_segment (demux);
6474
6475         /* Figure out which stream this packet belongs to */
6476         for (i = 0; i < demux->n_streams; i++) {
6477           stream = demux->streams[i];
6478           if (stream->sample_index >= stream->n_samples)
6479             continue;
6480           GST_LOG_OBJECT (demux,
6481               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6482               " / size:%d)", i, stream->sample_index,
6483               stream->samples[stream->sample_index].offset,
6484               stream->samples[stream->sample_index].size);
6485
6486           if (stream->samples[stream->sample_index].offset == demux->offset)
6487             break;
6488         }
6489
6490         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6491           goto unknown_stream;
6492
6493         if (stream->new_caps) {
6494           gst_qtdemux_configure_stream (demux, stream);
6495         }
6496
6497         /* Put data in a buffer, set timestamps, caps, ... */
6498         sample = &stream->samples[stream->sample_index];
6499
6500         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6501           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6502               GST_FOURCC_ARGS (stream->fourcc));
6503
6504           dts = QTSAMPLE_DTS (stream, sample);
6505           pts = QTSAMPLE_PTS (stream, sample);
6506           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6507           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6508
6509           /* check for segment end */
6510           if (G_UNLIKELY (demux->segment.stop != -1
6511                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6512             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6513             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6514
6515             /* skip this data, stream is EOS */
6516             gst_adapter_flush (demux->adapter, demux->neededbytes);
6517
6518             /* check if all streams are eos */
6519             ret = GST_FLOW_EOS;
6520             for (i = 0; i < demux->n_streams; i++) {
6521               if (!STREAM_IS_EOS (demux->streams[i])) {
6522                 ret = GST_FLOW_OK;
6523                 break;
6524               }
6525             }
6526
6527             if (ret == GST_FLOW_EOS) {
6528               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6529               goto eos;
6530             }
6531           } else {
6532             GstBuffer *outbuf;
6533
6534             outbuf =
6535                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6536
6537             /* FIXME: should either be an assert or a plain check */
6538             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6539
6540             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6541                 dts, pts, duration, keyframe, dts, demux->offset);
6542           }
6543
6544           /* combine flows */
6545           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6546           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6547             goto non_ok_unlinked_flow;
6548         } else {
6549           /* skip this data, stream is EOS */
6550           gst_adapter_flush (demux->adapter, demux->neededbytes);
6551         }
6552
6553         stream->sample_index++;
6554         stream->offset_in_sample = 0;
6555
6556         /* update current offset and figure out size of next buffer */
6557         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6558             demux->offset, demux->neededbytes);
6559         demux->offset += demux->neededbytes;
6560         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6561             demux->offset);
6562
6563         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6564           if (demux->fragmented) {
6565             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6566             /* there may be more to follow, only finish this atom */
6567             demux->todrop = demux->mdatleft;
6568             demux->neededbytes = demux->todrop;
6569             break;
6570           }
6571           goto eos;
6572         }
6573         break;
6574       }
6575       default:
6576         goto invalid_state;
6577     }
6578   }
6579
6580   /* when buffering movie data, at least show user something is happening */
6581   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6582       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6583     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6584         demux->neededbytes);
6585   }
6586 done:
6587
6588   return ret;
6589
6590   /* ERRORS */
6591 non_ok_unlinked_flow:
6592   {
6593     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6594         gst_flow_get_name (ret));
6595     return ret;
6596   }
6597 unknown_stream:
6598   {
6599     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6600     ret = GST_FLOW_ERROR;
6601     goto done;
6602   }
6603 eos:
6604   {
6605     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6606     ret = GST_FLOW_EOS;
6607     goto done;
6608   }
6609 invalid_state:
6610   {
6611     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6612         (NULL), ("qtdemuxer invalid state %d", demux->state));
6613     ret = GST_FLOW_ERROR;
6614     goto done;
6615   }
6616 no_moov:
6617   {
6618     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6619         (NULL), ("no 'moov' atom within the first 10 MB"));
6620     ret = GST_FLOW_ERROR;
6621     goto done;
6622   }
6623 }
6624
6625 static gboolean
6626 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6627 {
6628   GstQuery *query;
6629   gboolean pull_mode;
6630
6631   query = gst_query_new_scheduling ();
6632
6633   if (!gst_pad_peer_query (sinkpad, query)) {
6634     gst_query_unref (query);
6635     goto activate_push;
6636   }
6637
6638   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6639       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6640   gst_query_unref (query);
6641
6642   if (!pull_mode)
6643     goto activate_push;
6644
6645   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6646   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6647
6648 activate_push:
6649   {
6650     GST_DEBUG_OBJECT (sinkpad, "activating push");
6651     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6652   }
6653 }
6654
6655 static gboolean
6656 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6657     GstPadMode mode, gboolean active)
6658 {
6659   gboolean res;
6660   GstQTDemux *demux = GST_QTDEMUX (parent);
6661
6662   switch (mode) {
6663     case GST_PAD_MODE_PUSH:
6664       demux->pullbased = FALSE;
6665       res = TRUE;
6666       break;
6667     case GST_PAD_MODE_PULL:
6668       if (active) {
6669         demux->pullbased = TRUE;
6670         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6671             sinkpad, NULL);
6672       } else {
6673         res = gst_pad_stop_task (sinkpad);
6674       }
6675       break;
6676     default:
6677       res = FALSE;
6678       break;
6679   }
6680   return res;
6681 }
6682
6683 #ifdef HAVE_ZLIB
6684 static void *
6685 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6686 {
6687   return g_malloc (items * size);
6688 }
6689
6690 static void
6691 qtdemux_zfree (void *opaque, void *addr)
6692 {
6693   g_free (addr);
6694 }
6695
6696 static void *
6697 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6698 {
6699   guint8 *buffer;
6700   z_stream *z;
6701   int ret;
6702
6703   z = g_new0 (z_stream, 1);
6704   z->zalloc = qtdemux_zalloc;
6705   z->zfree = qtdemux_zfree;
6706   z->opaque = NULL;
6707
6708   z->next_in = z_buffer;
6709   z->avail_in = z_length;
6710
6711   buffer = (guint8 *) g_malloc (length);
6712   ret = inflateInit (z);
6713   while (z->avail_in > 0) {
6714     if (z->avail_out == 0) {
6715       length += 1024;
6716       buffer = (guint8 *) g_realloc (buffer, length);
6717       z->next_out = buffer + z->total_out;
6718       z->avail_out = 1024;
6719     }
6720     ret = inflate (z, Z_SYNC_FLUSH);
6721     if (ret != Z_OK)
6722       break;
6723   }
6724   if (ret != Z_STREAM_END) {
6725     g_warning ("inflate() returned %d", ret);
6726   }
6727
6728   g_free (z);
6729   return buffer;
6730 }
6731 #endif /* HAVE_ZLIB */
6732
6733 static gboolean
6734 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6735 {
6736   GNode *cmov;
6737
6738   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6739
6740   /* counts as header data */
6741   qtdemux->header_size += length;
6742
6743   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6744   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6745
6746   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6747   if (cmov) {
6748     guint32 method;
6749     GNode *dcom;
6750     GNode *cmvd;
6751
6752     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6753     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6754     if (dcom == NULL || cmvd == NULL)
6755       goto invalid_compression;
6756
6757     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6758     switch (method) {
6759 #ifdef HAVE_ZLIB
6760       case FOURCC_zlib:{
6761         guint uncompressed_length;
6762         guint compressed_length;
6763         guint8 *buf;
6764
6765         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6766         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6767         GST_LOG ("length = %u", uncompressed_length);
6768
6769         buf =
6770             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6771             compressed_length, uncompressed_length);
6772
6773         qtdemux->moov_node_compressed = qtdemux->moov_node;
6774         qtdemux->moov_node = g_node_new (buf);
6775
6776         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6777             uncompressed_length);
6778         break;
6779       }
6780 #endif /* HAVE_ZLIB */
6781       default:
6782         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6783             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6784         break;
6785     }
6786   }
6787   return TRUE;
6788
6789   /* ERRORS */
6790 invalid_compression:
6791   {
6792     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6793     return FALSE;
6794   }
6795 }
6796
6797 static gboolean
6798 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6799     const guint8 * end)
6800 {
6801   while (G_UNLIKELY (buf < end)) {
6802     GNode *child;
6803     guint32 len;
6804
6805     if (G_UNLIKELY (buf + 4 > end)) {
6806       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6807       break;
6808     }
6809     len = QT_UINT32 (buf);
6810     if (G_UNLIKELY (len == 0)) {
6811       GST_LOG_OBJECT (qtdemux, "empty container");
6812       break;
6813     }
6814     if (G_UNLIKELY (len < 8)) {
6815       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6816       break;
6817     }
6818     if (G_UNLIKELY (len > (end - buf))) {
6819       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6820           (gint) (end - buf));
6821       break;
6822     }
6823
6824     child = g_node_new ((guint8 *) buf);
6825     g_node_append (node, child);
6826     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6827     qtdemux_parse_node (qtdemux, child, buf, len);
6828
6829     buf += len;
6830   }
6831   return TRUE;
6832 }
6833
6834 static gboolean
6835 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6836     GNode * xdxt)
6837 {
6838   int len = QT_UINT32 (xdxt->data);
6839   guint8 *buf = xdxt->data;
6840   guint8 *end = buf + len;
6841   GstBuffer *buffer;
6842
6843   /* skip size and type */
6844   buf += 8;
6845   end -= 8;
6846
6847   while (buf < end) {
6848     gint size;
6849     guint32 type;
6850
6851     size = QT_UINT32 (buf);
6852     type = QT_FOURCC (buf + 4);
6853
6854     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6855
6856     if (buf + size > end || size <= 0)
6857       break;
6858
6859     buf += 8;
6860     size -= 8;
6861
6862     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6863         GST_FOURCC_ARGS (type));
6864
6865     switch (type) {
6866       case FOURCC_tCtH:
6867         buffer = gst_buffer_new_and_alloc (size);
6868         gst_buffer_fill (buffer, 0, buf, size);
6869         stream->buffers = g_slist_append (stream->buffers, buffer);
6870         GST_LOG_OBJECT (qtdemux, "parsing theora header");
6871         break;
6872       case FOURCC_tCt_:
6873         buffer = gst_buffer_new_and_alloc (size);
6874         gst_buffer_fill (buffer, 0, buf, size);
6875         stream->buffers = g_slist_append (stream->buffers, buffer);
6876         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6877         break;
6878       case FOURCC_tCtC:
6879         buffer = gst_buffer_new_and_alloc (size);
6880         gst_buffer_fill (buffer, 0, buf, size);
6881         stream->buffers = g_slist_append (stream->buffers, buffer);
6882         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6883         break;
6884       default:
6885         GST_WARNING_OBJECT (qtdemux,
6886             "unknown theora cookie %" GST_FOURCC_FORMAT,
6887             GST_FOURCC_ARGS (type));
6888         break;
6889     }
6890     buf += size;
6891   }
6892   return TRUE;
6893 }
6894
6895 static gboolean
6896 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
6897     guint length)
6898 {
6899   guint32 fourcc = 0;
6900   guint32 node_length = 0;
6901   const QtNodeType *type;
6902   const guint8 *end;
6903
6904   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
6905
6906   if (G_UNLIKELY (length < 8))
6907     goto not_enough_data;
6908
6909   node_length = QT_UINT32 (buffer);
6910   fourcc = QT_FOURCC (buffer + 4);
6911
6912   /* ignore empty nodes */
6913   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
6914     return TRUE;
6915
6916   type = qtdemux_type_get (fourcc);
6917
6918   end = buffer + length;
6919
6920   GST_LOG_OBJECT (qtdemux,
6921       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
6922       GST_FOURCC_ARGS (fourcc), node_length, type->name);
6923
6924   if (node_length > length)
6925     goto broken_atom_size;
6926
6927   if (type->flags & QT_FLAG_CONTAINER) {
6928     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
6929   } else {
6930     switch (fourcc) {
6931       case FOURCC_stsd:
6932       {
6933         if (node_length < 20) {
6934           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
6935           break;
6936         }
6937         GST_DEBUG_OBJECT (qtdemux,
6938             "parsing stsd (sample table, sample description) atom");
6939         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
6940         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6941         break;
6942       }
6943       case FOURCC_mp4a:
6944       case FOURCC_alac:
6945       {
6946         guint32 version;
6947         guint32 offset;
6948         guint min_size;
6949
6950         /* also read alac (or whatever) in stead of mp4a in the following,
6951          * since a similar layout is used in other cases as well */
6952         if (fourcc == FOURCC_mp4a)
6953           min_size = 20;
6954         else
6955           min_size = 40;
6956
6957         /* There are two things we might encounter here: a true mp4a atom, and
6958            an mp4a entry in an stsd atom. The latter is what we're interested
6959            in, and it looks like an atom, but isn't really one. The true mp4a
6960            atom is short, so we detect it based on length here. */
6961         if (length < min_size) {
6962           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
6963               GST_FOURCC_ARGS (fourcc));
6964           break;
6965         }
6966
6967         /* 'version' here is the sound sample description version. Types 0 and
6968            1 are documented in the QTFF reference, but type 2 is not: it's
6969            described in Apple header files instead (struct SoundDescriptionV2
6970            in Movies.h) */
6971         version = QT_UINT16 (buffer + 16);
6972
6973         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
6974             GST_FOURCC_ARGS (fourcc), version);
6975
6976         /* parse any esds descriptors */
6977         switch (version) {
6978           case 0:
6979             offset = 0x24;
6980             break;
6981           case 1:
6982             offset = 0x34;
6983             break;
6984           case 2:
6985             offset = 0x48;
6986             break;
6987           default:
6988             GST_WARNING_OBJECT (qtdemux,
6989                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
6990                 GST_FOURCC_ARGS (fourcc), version);
6991             offset = 0;
6992             break;
6993         }
6994         if (offset)
6995           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6996         break;
6997       }
6998       case FOURCC_mp4v:
6999       case FOURCC_MP4V:
7000       case FOURCC_fmp4:
7001       case FOURCC_FMP4:
7002       case FOURCC_apcs:
7003       case FOURCC_apch:
7004       case FOURCC_apcn:
7005       case FOURCC_apco:
7006       case FOURCC_ap4h:
7007       {
7008         const guint8 *buf;
7009         guint32 version;
7010         int tlen;
7011
7012         /* codec_data is contained inside these atoms, which all have
7013          * the same format. */
7014
7015         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7016             GST_FOURCC_ARGS (fourcc));
7017         version = QT_UINT32 (buffer + 16);
7018         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7019         if (1 || version == 0x00000000) {
7020           buf = buffer + 0x32;
7021
7022           /* FIXME Quicktime uses PASCAL string while
7023            * the iso format uses C strings. Check the file
7024            * type before attempting to parse the string here. */
7025           tlen = QT_UINT8 (buf);
7026           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
7027           buf++;
7028           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
7029           /* the string has a reserved space of 32 bytes so skip
7030            * the remaining 31 */
7031           buf += 31;
7032           buf += 4;             /* and 4 bytes reserved */
7033
7034           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
7035
7036           qtdemux_parse_container (qtdemux, node, buf, end);
7037         }
7038         break;
7039       }
7040       case FOURCC_H264:
7041       {
7042         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
7043         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7044         break;
7045       }
7046       case FOURCC_avc1:
7047       {
7048         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
7049         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7050         break;
7051       }
7052       case FOURCC_avc3:
7053       {
7054         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
7055         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7056         break;
7057       }
7058       case FOURCC_H265:
7059       {
7060         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
7061         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7062         break;
7063       }
7064       case FOURCC_hvc1:
7065       {
7066         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
7067         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7068         break;
7069       }
7070       case FOURCC_hev1:
7071       {
7072         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
7073         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7074         break;
7075       }
7076       case FOURCC_mjp2:
7077       {
7078         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7079         break;
7080       }
7081       case FOURCC_meta:
7082       {
7083         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7084         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7085         break;
7086       }
7087       case FOURCC_mp4s:
7088       {
7089         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7090         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7091         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7092         break;
7093       }
7094       case FOURCC_XiTh:
7095       {
7096         guint32 version;
7097         guint32 offset;
7098
7099         version = QT_UINT32 (buffer + 12);
7100         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7101
7102         switch (version) {
7103           case 0x00000001:
7104             offset = 0x62;
7105             break;
7106           default:
7107             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7108             offset = 0;
7109             break;
7110         }
7111         if (offset)
7112           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7113         break;
7114       }
7115       case FOURCC_in24:
7116       {
7117         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7118         break;
7119       }
7120       case FOURCC_uuid:
7121       {
7122         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7123         break;
7124       }
7125       case FOURCC_encv:
7126       {
7127         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7128         break;
7129       }
7130       case FOURCC_enca:
7131       {
7132         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7133         break;
7134       }
7135       default:
7136         if (!strcmp (type->name, "unknown"))
7137           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7138         break;
7139     }
7140   }
7141   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7142       GST_FOURCC_ARGS (fourcc));
7143   return TRUE;
7144
7145 /* ERRORS */
7146 not_enough_data:
7147   {
7148     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7149         (_("This file is corrupt and cannot be played.")),
7150         ("Not enough data for an atom header, got only %u bytes", length));
7151     return FALSE;
7152   }
7153 broken_atom_size:
7154   {
7155     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7156         (_("This file is corrupt and cannot be played.")),
7157         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7158             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7159             length));
7160     return FALSE;
7161   }
7162 }
7163
7164 static GNode *
7165 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7166 {
7167   GNode *child;
7168   guint8 *buffer;
7169   guint32 child_fourcc;
7170
7171   for (child = g_node_first_child (node); child;
7172       child = g_node_next_sibling (child)) {
7173     buffer = (guint8 *) child->data;
7174
7175     child_fourcc = QT_FOURCC (buffer + 4);
7176
7177     if (G_UNLIKELY (child_fourcc == fourcc)) {
7178       return child;
7179     }
7180   }
7181   return NULL;
7182 }
7183
7184 static GNode *
7185 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7186     GstByteReader * parser)
7187 {
7188   GNode *child;
7189   guint8 *buffer;
7190   guint32 child_fourcc, child_len;
7191
7192   for (child = g_node_first_child (node); child;
7193       child = g_node_next_sibling (child)) {
7194     buffer = (guint8 *) child->data;
7195
7196     child_len = QT_UINT32 (buffer);
7197     child_fourcc = QT_FOURCC (buffer + 4);
7198
7199     if (G_UNLIKELY (child_fourcc == fourcc)) {
7200       if (G_UNLIKELY (child_len < (4 + 4)))
7201         return NULL;
7202       /* FIXME: must verify if atom length < parent atom length */
7203       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7204       return child;
7205     }
7206   }
7207   return NULL;
7208 }
7209
7210 static GNode *
7211 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7212     GstByteReader * parser)
7213 {
7214   GNode *child;
7215   guint8 *buffer;
7216   guint32 child_fourcc, child_len;
7217
7218   for (child = g_node_next_sibling (node); child;
7219       child = g_node_next_sibling (child)) {
7220     buffer = (guint8 *) child->data;
7221
7222     child_fourcc = QT_FOURCC (buffer + 4);
7223
7224     if (child_fourcc == fourcc) {
7225       if (parser) {
7226         child_len = QT_UINT32 (buffer);
7227         if (G_UNLIKELY (child_len < (4 + 4)))
7228           return NULL;
7229         /* FIXME: must verify if atom length < parent atom length */
7230         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7231       }
7232       return child;
7233     }
7234   }
7235   return NULL;
7236 }
7237
7238 static GNode *
7239 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7240 {
7241   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7242 }
7243
7244 static void
7245 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7246 {
7247 /* FIXME: This can only reliably work if demuxers have a
7248  * separate streaming thread per srcpad. This should be
7249  * done in a demuxer base class, which integrates parts
7250  * of multiqueue
7251  *
7252  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7253  */
7254 #if 0
7255   GstQuery *query;
7256
7257   query = gst_query_new_allocation (stream->caps, FALSE);
7258
7259   if (!gst_pad_peer_query (stream->pad, query)) {
7260     /* not a problem, just debug a little */
7261     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7262   }
7263
7264   if (stream->allocator)
7265     gst_object_unref (stream->allocator);
7266
7267   if (gst_query_get_n_allocation_params (query) > 0) {
7268     /* try the allocator */
7269     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7270         &stream->params);
7271     stream->use_allocator = TRUE;
7272   } else {
7273     stream->allocator = NULL;
7274     gst_allocation_params_init (&stream->params);
7275     stream->use_allocator = FALSE;
7276   }
7277   gst_query_unref (query);
7278 #endif
7279 }
7280
7281 static gboolean
7282 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7283     QtDemuxStream * stream)
7284 {
7285   GstStructure *s;
7286   const gchar *selected_system;
7287
7288   g_return_val_if_fail (qtdemux != NULL, FALSE);
7289   g_return_val_if_fail (stream != NULL, FALSE);
7290   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7291
7292   if (stream->protection_scheme_type != FOURCC_cenc) {
7293     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7294     return FALSE;
7295   }
7296   if (qtdemux->protection_system_ids == NULL) {
7297     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7298         "cenc protection system information has been found");
7299     return FALSE;
7300   }
7301   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7302   selected_system = gst_protection_select_system ((const gchar **)
7303       qtdemux->protection_system_ids->pdata);
7304   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7305       qtdemux->protection_system_ids->len - 1);
7306   if (!selected_system) {
7307     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7308         "suitable decryptor element has been found");
7309     return FALSE;
7310   }
7311
7312   s = gst_caps_get_structure (stream->caps, 0);
7313   if (!gst_structure_has_name (s, "application/x-cenc")) {
7314     gst_structure_set (s,
7315         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7316         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7317         NULL);
7318     gst_structure_set_name (s, "application/x-cenc");
7319   }
7320   return TRUE;
7321 }
7322
7323 static gboolean
7324 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7325 {
7326   if (stream->subtype == FOURCC_vide) {
7327     /* fps is calculated base on the duration of the average framerate since
7328      * qt does not have a fixed framerate. */
7329     gboolean fps_available = TRUE;
7330
7331     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7332       /* still frame */
7333       stream->fps_n = 0;
7334       stream->fps_d = 1;
7335     } else {
7336       if (stream->duration == 0 || stream->n_samples < 2) {
7337         stream->fps_n = stream->timescale;
7338         stream->fps_d = 1;
7339         fps_available = FALSE;
7340       } else {
7341         GstClockTime avg_duration;
7342         guint64 duration;
7343         guint32 n_samples;
7344
7345         /* duration and n_samples can be updated for fragmented format
7346          * so, framerate of fragmented format is calculated using data in a moof */
7347         if (qtdemux->fragmented && stream->n_samples_moof > 0
7348             && stream->duration_moof > 0) {
7349           n_samples = stream->n_samples_moof;
7350           duration = stream->duration_moof;
7351         } else {
7352           n_samples = stream->n_samples;
7353           duration = stream->duration;
7354         }
7355
7356         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7357         /* stream->duration is guint64, timescale, n_samples are guint32 */
7358         avg_duration =
7359             gst_util_uint64_scale_round (duration -
7360             stream->first_duration, GST_SECOND,
7361             (guint64) (stream->timescale) * (n_samples - 1));
7362
7363         GST_LOG_OBJECT (qtdemux,
7364             "Calculating avg sample duration based on stream (or moof) duration %"
7365             G_GUINT64_FORMAT
7366             " minus first sample %u, leaving %d samples gives %"
7367             GST_TIME_FORMAT, duration, stream->first_duration,
7368             n_samples - 1, GST_TIME_ARGS (avg_duration));
7369
7370         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7371             &stream->fps_d);
7372
7373         GST_DEBUG_OBJECT (qtdemux,
7374             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7375             stream->timescale, stream->fps_n, stream->fps_d);
7376       }
7377     }
7378
7379     if (stream->caps) {
7380       stream->caps = gst_caps_make_writable (stream->caps);
7381
7382       gst_caps_set_simple (stream->caps,
7383           "width", G_TYPE_INT, stream->width,
7384           "height", G_TYPE_INT, stream->height, NULL);
7385
7386       /* set framerate if calculated framerate is reliable */
7387       if (fps_available) {
7388         gst_caps_set_simple (stream->caps,
7389             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7390       }
7391
7392       /* calculate pixel-aspect-ratio using display width and height */
7393       GST_DEBUG_OBJECT (qtdemux,
7394           "video size %dx%d, target display size %dx%d", stream->width,
7395           stream->height, stream->display_width, stream->display_height);
7396       /* qt file might have pasp atom */
7397       if (stream->par_w > 0 && stream->par_h > 0) {
7398         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7399         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7400             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7401       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7402           stream->width > 0 && stream->height > 0) {
7403         gint n, d;
7404
7405         /* calculate the pixel aspect ratio using the display and pixel w/h */
7406         n = stream->display_width * stream->height;
7407         d = stream->display_height * stream->width;
7408         if (n == d)
7409           n = d = 1;
7410         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7411         stream->par_w = n;
7412         stream->par_h = d;
7413         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7414             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7415       }
7416
7417       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7418         guint par_w = 1, par_h = 1;
7419
7420         if (stream->par_w > 0 && stream->par_h > 0) {
7421           par_w = stream->par_w;
7422           par_h = stream->par_h;
7423         }
7424
7425         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7426                 stream->width, stream->height, par_w, par_h)) {
7427           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7428         }
7429
7430         gst_caps_set_simple (stream->caps,
7431             "multiview-mode", G_TYPE_STRING,
7432             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7433             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7434             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7435       }
7436     }
7437   }
7438
7439   else if (stream->subtype == FOURCC_soun) {
7440     if (stream->caps) {
7441       stream->caps = gst_caps_make_writable (stream->caps);
7442       if (stream->rate > 0)
7443         gst_caps_set_simple (stream->caps,
7444             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7445       if (stream->n_channels > 0)
7446         gst_caps_set_simple (stream->caps,
7447             "channels", G_TYPE_INT, stream->n_channels, NULL);
7448       if (stream->n_channels > 2) {
7449         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7450          * correctly; this is just the minimum we can do - assume
7451          * we don't actually have any channel positions. */
7452         gst_caps_set_simple (stream->caps,
7453             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7454       }
7455     }
7456   }
7457
7458   if (stream->pad) {
7459     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7460     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7461     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7462     gst_pad_set_active (stream->pad, TRUE);
7463
7464     gst_pad_use_fixed_caps (stream->pad);
7465
7466     if (stream->protected) {
7467       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7468         GST_ERROR_OBJECT (qtdemux,
7469             "Failed to configure protected stream caps.");
7470         return FALSE;
7471       }
7472     }
7473
7474     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7475     if (stream->new_stream) {
7476       gchar *stream_id;
7477       GstEvent *event;
7478       GstStreamFlags stream_flags;
7479
7480       event =
7481           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7482           0);
7483       if (event) {
7484         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7485           qtdemux->have_group_id = TRUE;
7486         else
7487           qtdemux->have_group_id = FALSE;
7488         gst_event_unref (event);
7489       } else if (!qtdemux->have_group_id) {
7490         qtdemux->have_group_id = TRUE;
7491         qtdemux->group_id = gst_util_group_id_next ();
7492       }
7493
7494       stream->new_stream = FALSE;
7495       stream_id =
7496           gst_pad_create_stream_id_printf (stream->pad,
7497           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7498       event = gst_event_new_stream_start (stream_id);
7499       if (qtdemux->have_group_id)
7500         gst_event_set_group_id (event, qtdemux->group_id);
7501       stream_flags = GST_STREAM_FLAG_NONE;
7502       if (stream->disabled)
7503         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7504       if (stream->sparse)
7505         stream_flags |= GST_STREAM_FLAG_SPARSE;
7506       gst_event_set_stream_flags (event, stream_flags);
7507       gst_pad_push_event (stream->pad, event);
7508       g_free (stream_id);
7509     }
7510     gst_pad_set_caps (stream->pad, stream->caps);
7511     stream->new_caps = FALSE;
7512   }
7513   return TRUE;
7514 }
7515
7516 static gboolean
7517 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7518     QtDemuxStream * stream, GstTagList * list)
7519 {
7520   gboolean ret = TRUE;
7521   /* consistent default for push based mode */
7522   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7523
7524   if (stream->subtype == FOURCC_vide) {
7525     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7526
7527     stream->pad =
7528         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7529     g_free (name);
7530
7531     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7532       gst_object_unref (stream->pad);
7533       stream->pad = NULL;
7534       ret = FALSE;
7535       goto done;
7536     }
7537
7538     qtdemux->n_video_streams++;
7539   } else if (stream->subtype == FOURCC_soun) {
7540     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7541
7542     stream->pad =
7543         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7544     g_free (name);
7545     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7546       gst_object_unref (stream->pad);
7547       stream->pad = NULL;
7548       ret = FALSE;
7549       goto done;
7550     }
7551     qtdemux->n_audio_streams++;
7552   } else if (stream->subtype == FOURCC_strm) {
7553     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7554   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7555       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7556     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7557
7558     stream->pad =
7559         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7560     g_free (name);
7561     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7562       gst_object_unref (stream->pad);
7563       stream->pad = NULL;
7564       ret = FALSE;
7565       goto done;
7566     }
7567     qtdemux->n_sub_streams++;
7568   } else if (stream->caps) {
7569     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7570
7571     stream->pad =
7572         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7573     g_free (name);
7574     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7575       gst_object_unref (stream->pad);
7576       stream->pad = NULL;
7577       ret = FALSE;
7578       goto done;
7579     }
7580     qtdemux->n_video_streams++;
7581   } else {
7582     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7583     goto done;
7584   }
7585
7586   if (stream->pad) {
7587     GList *l;
7588
7589     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7590         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7591     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7592     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7593
7594     if (stream->pending_tags)
7595       gst_tag_list_unref (stream->pending_tags);
7596     stream->pending_tags = list;
7597     list = NULL;
7598     /* global tags go on each pad anyway */
7599     stream->send_global_tags = TRUE;
7600     /* send upstream GST_EVENT_PROTECTION events that were received before
7601        this source pad was created */
7602     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7603       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7604   }
7605 done:
7606   if (list)
7607     gst_tag_list_unref (list);
7608   return ret;
7609 }
7610
7611 /* find next atom with @fourcc starting at @offset */
7612 static GstFlowReturn
7613 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7614     guint64 * length, guint32 fourcc)
7615 {
7616   GstFlowReturn ret;
7617   guint32 lfourcc;
7618   GstBuffer *buf;
7619
7620   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7621       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7622
7623   while (TRUE) {
7624     GstMapInfo map;
7625
7626     buf = NULL;
7627     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7628     if (G_UNLIKELY (ret != GST_FLOW_OK))
7629       goto locate_failed;
7630     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7631       /* likely EOF */
7632       ret = GST_FLOW_EOS;
7633       gst_buffer_unref (buf);
7634       goto locate_failed;
7635     }
7636     gst_buffer_map (buf, &map, GST_MAP_READ);
7637     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7638     gst_buffer_unmap (buf, &map);
7639     gst_buffer_unref (buf);
7640
7641     if (G_UNLIKELY (*length == 0)) {
7642       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7643       ret = GST_FLOW_ERROR;
7644       goto locate_failed;
7645     }
7646
7647     if (lfourcc == fourcc) {
7648       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7649           *offset);
7650       break;
7651     } else {
7652       GST_LOG_OBJECT (qtdemux,
7653           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7654           GST_FOURCC_ARGS (fourcc), *offset);
7655       *offset += *length;
7656     }
7657   }
7658
7659   return GST_FLOW_OK;
7660
7661 locate_failed:
7662   {
7663     /* might simply have had last one */
7664     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7665     return ret;
7666   }
7667 }
7668
7669 /* should only do something in pull mode */
7670 /* call with OBJECT lock */
7671 static GstFlowReturn
7672 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7673 {
7674   guint64 length, offset;
7675   GstBuffer *buf = NULL;
7676   GstFlowReturn ret = GST_FLOW_OK;
7677   GstFlowReturn res = GST_FLOW_OK;
7678   GstMapInfo map;
7679
7680   offset = qtdemux->moof_offset;
7681   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7682
7683   if (!offset) {
7684     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7685     return GST_FLOW_EOS;
7686   }
7687
7688   /* best not do pull etc with lock held */
7689   GST_OBJECT_UNLOCK (qtdemux);
7690
7691   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7692   if (ret != GST_FLOW_OK)
7693     goto flow_failed;
7694
7695   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7696   if (G_UNLIKELY (ret != GST_FLOW_OK))
7697     goto flow_failed;
7698   gst_buffer_map (buf, &map, GST_MAP_READ);
7699   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7700     gst_buffer_unmap (buf, &map);
7701     gst_buffer_unref (buf);
7702     buf = NULL;
7703     goto parse_failed;
7704   }
7705
7706   gst_buffer_unmap (buf, &map);
7707   gst_buffer_unref (buf);
7708   buf = NULL;
7709
7710   offset += length;
7711   /* look for next moof */
7712   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7713   if (G_UNLIKELY (ret != GST_FLOW_OK))
7714     goto flow_failed;
7715
7716 exit:
7717   GST_OBJECT_LOCK (qtdemux);
7718
7719   qtdemux->moof_offset = offset;
7720
7721   return res;
7722
7723 parse_failed:
7724   {
7725     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7726     offset = 0;
7727     res = GST_FLOW_ERROR;
7728     goto exit;
7729   }
7730 flow_failed:
7731   {
7732     /* maybe upstream temporarily flushing */
7733     if (ret != GST_FLOW_FLUSHING) {
7734       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7735       offset = 0;
7736     } else {
7737       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7738       /* resume at current position next time */
7739     }
7740     res = ret;
7741     goto exit;
7742   }
7743 }
7744
7745 /* initialise bytereaders for stbl sub-atoms */
7746 static gboolean
7747 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7748 {
7749   stream->stbl_index = -1;      /* no samples have yet been parsed */
7750   stream->sample_index = -1;
7751
7752   /* time-to-sample atom */
7753   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7754     goto corrupt_file;
7755
7756   /* copy atom data into a new buffer for later use */
7757   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7758
7759   /* skip version + flags */
7760   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7761       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7762     goto corrupt_file;
7763   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7764
7765   /* make sure there's enough data */
7766   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7767     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7768     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7769         stream->n_sample_times);
7770     if (!stream->n_sample_times)
7771       goto corrupt_file;
7772   }
7773
7774   /* sync sample atom */
7775   stream->stps_present = FALSE;
7776   if ((stream->stss_present =
7777           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7778               &stream->stss) ? TRUE : FALSE) == TRUE) {
7779     /* copy atom data into a new buffer for later use */
7780     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7781
7782     /* skip version + flags */
7783     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7784         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7785       goto corrupt_file;
7786
7787     if (stream->n_sample_syncs) {
7788       /* make sure there's enough data */
7789       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7790         goto corrupt_file;
7791     }
7792
7793     /* partial sync sample atom */
7794     if ((stream->stps_present =
7795             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7796                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7797       /* copy atom data into a new buffer for later use */
7798       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7799
7800       /* skip version + flags */
7801       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7802           !gst_byte_reader_get_uint32_be (&stream->stps,
7803               &stream->n_sample_partial_syncs))
7804         goto corrupt_file;
7805
7806       /* if there are no entries, the stss table contains the real
7807        * sync samples */
7808       if (stream->n_sample_partial_syncs) {
7809         /* make sure there's enough data */
7810         if (!qt_atom_parser_has_chunks (&stream->stps,
7811                 stream->n_sample_partial_syncs, 4))
7812           goto corrupt_file;
7813       }
7814     }
7815   }
7816
7817   /* sample size */
7818   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7819     goto no_samples;
7820
7821   /* copy atom data into a new buffer for later use */
7822   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7823
7824   /* skip version + flags */
7825   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7826       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7827     goto corrupt_file;
7828
7829   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7830     goto corrupt_file;
7831
7832   if (!stream->n_samples)
7833     goto no_samples;
7834
7835   /* sample-to-chunk atom */
7836   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7837     goto corrupt_file;
7838
7839   /* copy atom data into a new buffer for later use */
7840   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7841
7842   /* skip version + flags */
7843   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7844       !gst_byte_reader_get_uint32_be (&stream->stsc,
7845           &stream->n_samples_per_chunk))
7846     goto corrupt_file;
7847
7848   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7849       stream->n_samples_per_chunk);
7850
7851   /* make sure there's enough data */
7852   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7853           12))
7854     goto corrupt_file;
7855
7856
7857   /* chunk offset */
7858   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7859     stream->co_size = sizeof (guint32);
7860   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7861           &stream->stco))
7862     stream->co_size = sizeof (guint64);
7863   else
7864     goto corrupt_file;
7865
7866   /* copy atom data into a new buffer for later use */
7867   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7868
7869   /* skip version + flags */
7870   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7871     goto corrupt_file;
7872
7873   /* chunks_are_samples == TRUE means treat chunks as samples */
7874   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7875   if (stream->chunks_are_samples) {
7876     /* treat chunks as samples */
7877     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7878       goto corrupt_file;
7879   } else {
7880     /* skip number of entries */
7881     if (!gst_byte_reader_skip (&stream->stco, 4))
7882       goto corrupt_file;
7883
7884     /* make sure there are enough data in the stsz atom */
7885     if (!stream->sample_size) {
7886       /* different sizes for each sample */
7887       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7888         goto corrupt_file;
7889     }
7890   }
7891
7892   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7893       stream->n_samples, (guint) sizeof (QtDemuxSample),
7894       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7895
7896   if (stream->n_samples >=
7897       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7898     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7899         "be larger than %uMB (broken file?)", stream->n_samples,
7900         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7901     return FALSE;
7902   }
7903
7904   g_assert (stream->samples == NULL);
7905   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7906   if (!stream->samples) {
7907     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7908         stream->n_samples);
7909     return FALSE;
7910   }
7911
7912   /* composition time-to-sample */
7913   if ((stream->ctts_present =
7914           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7915               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7916     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7917
7918     /* copy atom data into a new buffer for later use */
7919     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7920
7921     /* skip version + flags */
7922     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7923         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7924             &stream->n_composition_times))
7925       goto corrupt_file;
7926
7927     /* make sure there's enough data */
7928     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7929             4 + 4))
7930       goto corrupt_file;
7931
7932     /* This is optional, if missing we iterate the ctts */
7933     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7934       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7935           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7936         g_free ((gpointer) cslg.data);
7937         goto corrupt_file;
7938       }
7939     } else {
7940       gint32 cslg_least = 0;
7941       guint num_entries, pos;
7942       gint i;
7943
7944       pos = gst_byte_reader_get_pos (&stream->ctts);
7945       num_entries = stream->n_composition_times;
7946
7947       stream->cslg_shift = 0;
7948
7949       for (i = 0; i < num_entries; i++) {
7950         gint32 offset;
7951
7952         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7953         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7954
7955         if (offset < cslg_least)
7956           cslg_least = offset;
7957       }
7958
7959       if (cslg_least < 0)
7960         stream->cslg_shift = ABS (cslg_least);
7961       else
7962         stream->cslg_shift = 0;
7963
7964       /* reset the reader so we can generate sample table */
7965       gst_byte_reader_set_pos (&stream->ctts, pos);
7966     }
7967   } else {
7968     /* Ensure the cslg_shift value is consistent so we can use it
7969      * unconditionnally to produce TS and Segment */
7970     stream->cslg_shift = 0;
7971   }
7972
7973   return TRUE;
7974
7975 corrupt_file:
7976   {
7977     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7978         (_("This file is corrupt and cannot be played.")), (NULL));
7979     return FALSE;
7980   }
7981 no_samples:
7982   {
7983     gst_qtdemux_stbl_free (stream);
7984     if (!qtdemux->fragmented) {
7985       /* not quite good */
7986       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
7987       return FALSE;
7988     } else {
7989       /* may pick up samples elsewhere */
7990       return TRUE;
7991     }
7992   }
7993 }
7994
7995 /* collect samples from the next sample to be parsed up to sample @n for @stream
7996  * by reading the info from @stbl
7997  *
7998  * This code can be executed from both the streaming thread and the seeking
7999  * thread so it takes the object lock to protect itself
8000  */
8001 static gboolean
8002 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8003 {
8004   gint i, j, k;
8005   QtDemuxSample *samples, *first, *cur, *last;
8006   guint32 n_samples_per_chunk;
8007   guint32 n_samples;
8008
8009   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8010       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8011       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8012
8013   n_samples = stream->n_samples;
8014
8015   if (n >= n_samples)
8016     goto out_of_samples;
8017
8018   GST_OBJECT_LOCK (qtdemux);
8019   if (n <= stream->stbl_index)
8020     goto already_parsed;
8021
8022   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8023
8024   if (!stream->stsz.data) {
8025     /* so we already parsed and passed all the moov samples;
8026      * onto fragmented ones */
8027     g_assert (qtdemux->fragmented);
8028     goto done;
8029   }
8030
8031   /* pointer to the sample table */
8032   samples = stream->samples;
8033
8034   /* starts from -1, moves to the next sample index to parse */
8035   stream->stbl_index++;
8036
8037   /* keep track of the first and last sample to fill */
8038   first = &samples[stream->stbl_index];
8039   last = &samples[n];
8040
8041   if (!stream->chunks_are_samples) {
8042     /* set the sample sizes */
8043     if (stream->sample_size == 0) {
8044       /* different sizes for each sample */
8045       for (cur = first; cur <= last; cur++) {
8046         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8047         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8048             (guint) (cur - samples), cur->size);
8049       }
8050     } else {
8051       /* samples have the same size */
8052       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8053       for (cur = first; cur <= last; cur++)
8054         cur->size = stream->sample_size;
8055     }
8056   }
8057
8058   n_samples_per_chunk = stream->n_samples_per_chunk;
8059   cur = first;
8060
8061   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8062     guint32 last_chunk;
8063
8064     if (stream->stsc_chunk_index >= stream->last_chunk
8065         || stream->stsc_chunk_index < stream->first_chunk) {
8066       stream->first_chunk =
8067           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8068       stream->samples_per_chunk =
8069           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8070       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8071
8072       /* chunk numbers are counted from 1 it seems */
8073       if (G_UNLIKELY (stream->first_chunk == 0))
8074         goto corrupt_file;
8075
8076       --stream->first_chunk;
8077
8078       /* the last chunk of each entry is calculated by taking the first chunk
8079        * of the next entry; except if there is no next, where we fake it with
8080        * INT_MAX */
8081       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8082         stream->last_chunk = G_MAXUINT32;
8083       } else {
8084         stream->last_chunk =
8085             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8086         if (G_UNLIKELY (stream->last_chunk == 0))
8087           goto corrupt_file;
8088
8089         --stream->last_chunk;
8090       }
8091
8092       GST_LOG_OBJECT (qtdemux,
8093           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8094           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8095
8096       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8097         goto corrupt_file;
8098
8099       if (stream->last_chunk != G_MAXUINT32) {
8100         if (!qt_atom_parser_peek_sub (&stream->stco,
8101                 stream->first_chunk * stream->co_size,
8102                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8103                 &stream->co_chunk))
8104           goto corrupt_file;
8105
8106       } else {
8107         stream->co_chunk = stream->stco;
8108         if (!gst_byte_reader_skip (&stream->co_chunk,
8109                 stream->first_chunk * stream->co_size))
8110           goto corrupt_file;
8111       }
8112
8113       stream->stsc_chunk_index = stream->first_chunk;
8114     }
8115
8116     last_chunk = stream->last_chunk;
8117
8118     if (stream->chunks_are_samples) {
8119       cur = &samples[stream->stsc_chunk_index];
8120
8121       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8122         if (j > n) {
8123           /* save state */
8124           stream->stsc_chunk_index = j;
8125           goto done;
8126         }
8127
8128         cur->offset =
8129             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8130             stream->co_size);
8131
8132         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8133             "%" G_GUINT64_FORMAT, j, cur->offset);
8134
8135         if (stream->samples_per_frame * stream->bytes_per_frame) {
8136           cur->size =
8137               (stream->samples_per_chunk * stream->n_channels) /
8138               stream->samples_per_frame * stream->bytes_per_frame;
8139         } else {
8140           cur->size = stream->samples_per_chunk;
8141         }
8142
8143         GST_DEBUG_OBJECT (qtdemux,
8144             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8145             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8146                     stream->stco_sample_index)), cur->size);
8147
8148         cur->timestamp = stream->stco_sample_index;
8149         cur->duration = stream->samples_per_chunk;
8150         cur->keyframe = TRUE;
8151         cur++;
8152
8153         stream->stco_sample_index += stream->samples_per_chunk;
8154       }
8155       stream->stsc_chunk_index = j;
8156     } else {
8157       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8158         guint32 samples_per_chunk;
8159         guint64 chunk_offset;
8160
8161         if (!stream->stsc_sample_index
8162             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8163                 &stream->chunk_offset))
8164           goto corrupt_file;
8165
8166         samples_per_chunk = stream->samples_per_chunk;
8167         chunk_offset = stream->chunk_offset;
8168
8169         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8170           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8171               G_GUINT64_FORMAT " and size %d",
8172               (guint) (cur - samples), chunk_offset, cur->size);
8173
8174           cur->offset = chunk_offset;
8175           chunk_offset += cur->size;
8176           cur++;
8177
8178           if (G_UNLIKELY (cur > last)) {
8179             /* save state */
8180             stream->stsc_sample_index = k + 1;
8181             stream->chunk_offset = chunk_offset;
8182             stream->stsc_chunk_index = j;
8183             goto done2;
8184           }
8185         }
8186         stream->stsc_sample_index = 0;
8187       }
8188       stream->stsc_chunk_index = j;
8189     }
8190     stream->stsc_index++;
8191   }
8192
8193   if (stream->chunks_are_samples)
8194     goto ctts;
8195 done2:
8196   {
8197     guint32 n_sample_times;
8198
8199     n_sample_times = stream->n_sample_times;
8200     cur = first;
8201
8202     for (i = stream->stts_index; i < n_sample_times; i++) {
8203       guint32 stts_samples;
8204       gint32 stts_duration;
8205       gint64 stts_time;
8206
8207       if (stream->stts_sample_index >= stream->stts_samples
8208           || !stream->stts_sample_index) {
8209
8210         stream->stts_samples =
8211             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8212         stream->stts_duration =
8213             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8214
8215         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8216             i, stream->stts_samples, stream->stts_duration);
8217
8218         stream->stts_sample_index = 0;
8219       }
8220
8221       stts_samples = stream->stts_samples;
8222       stts_duration = stream->stts_duration;
8223       stts_time = stream->stts_time;
8224
8225       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8226         GST_DEBUG_OBJECT (qtdemux,
8227             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8228             (guint) (cur - samples), j,
8229             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8230
8231         cur->timestamp = stts_time;
8232         cur->duration = stts_duration;
8233
8234         /* avoid 32-bit wrap-around,
8235          * but still mind possible 'negative' duration */
8236         stts_time += (gint64) stts_duration;
8237         cur++;
8238
8239         if (G_UNLIKELY (cur > last)) {
8240           /* save values */
8241           stream->stts_time = stts_time;
8242           stream->stts_sample_index = j + 1;
8243           goto done3;
8244         }
8245       }
8246       stream->stts_sample_index = 0;
8247       stream->stts_time = stts_time;
8248       stream->stts_index++;
8249     }
8250     /* fill up empty timestamps with the last timestamp, this can happen when
8251      * the last samples do not decode and so we don't have timestamps for them.
8252      * We however look at the last timestamp to estimate the track length so we
8253      * need something in here. */
8254     for (; cur < last; cur++) {
8255       GST_DEBUG_OBJECT (qtdemux,
8256           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8257           (guint) (cur - samples),
8258           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8259       cur->timestamp = stream->stts_time;
8260       cur->duration = -1;
8261     }
8262   }
8263 done3:
8264   {
8265     /* sample sync, can be NULL */
8266     if (stream->stss_present == TRUE) {
8267       guint32 n_sample_syncs;
8268
8269       n_sample_syncs = stream->n_sample_syncs;
8270
8271       if (!n_sample_syncs) {
8272         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8273         stream->all_keyframe = TRUE;
8274       } else {
8275         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8276           /* note that the first sample is index 1, not 0 */
8277           guint32 index;
8278
8279           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8280
8281           if (G_LIKELY (index > 0 && index <= n_samples)) {
8282             index -= 1;
8283             samples[index].keyframe = TRUE;
8284             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8285             /* and exit if we have enough samples */
8286             if (G_UNLIKELY (index >= n)) {
8287               i++;
8288               break;
8289             }
8290           }
8291         }
8292         /* save state */
8293         stream->stss_index = i;
8294       }
8295
8296       /* stps marks partial sync frames like open GOP I-Frames */
8297       if (stream->stps_present == TRUE) {
8298         guint32 n_sample_partial_syncs;
8299
8300         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8301
8302         /* if there are no entries, the stss table contains the real
8303          * sync samples */
8304         if (n_sample_partial_syncs) {
8305           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8306             /* note that the first sample is index 1, not 0 */
8307             guint32 index;
8308
8309             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8310
8311             if (G_LIKELY (index > 0 && index <= n_samples)) {
8312               index -= 1;
8313               samples[index].keyframe = TRUE;
8314               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8315               /* and exit if we have enough samples */
8316               if (G_UNLIKELY (index >= n)) {
8317                 i++;
8318                 break;
8319               }
8320             }
8321           }
8322           /* save state */
8323           stream->stps_index = i;
8324         }
8325       }
8326     } else {
8327       /* no stss, all samples are keyframes */
8328       stream->all_keyframe = TRUE;
8329       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8330     }
8331   }
8332
8333 ctts:
8334   /* composition time to sample */
8335   if (stream->ctts_present == TRUE) {
8336     guint32 n_composition_times;
8337     guint32 ctts_count;
8338     gint32 ctts_soffset;
8339
8340     /* Fill in the pts_offsets */
8341     cur = first;
8342     n_composition_times = stream->n_composition_times;
8343
8344     for (i = stream->ctts_index; i < n_composition_times; i++) {
8345       if (stream->ctts_sample_index >= stream->ctts_count
8346           || !stream->ctts_sample_index) {
8347         stream->ctts_count =
8348             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8349         stream->ctts_soffset =
8350             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8351         stream->ctts_sample_index = 0;
8352       }
8353
8354       ctts_count = stream->ctts_count;
8355       ctts_soffset = stream->ctts_soffset;
8356
8357       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8358         cur->pts_offset = ctts_soffset;
8359         cur++;
8360
8361         if (G_UNLIKELY (cur > last)) {
8362           /* save state */
8363           stream->ctts_sample_index = j + 1;
8364           goto done;
8365         }
8366       }
8367       stream->ctts_sample_index = 0;
8368       stream->ctts_index++;
8369     }
8370   }
8371 done:
8372   stream->stbl_index = n;
8373   /* if index has been completely parsed, free data that is no-longer needed */
8374   if (n + 1 == stream->n_samples) {
8375     gst_qtdemux_stbl_free (stream);
8376     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8377     if (qtdemux->pullbased) {
8378       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8379       while (n + 1 == stream->n_samples)
8380         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8381           break;
8382     }
8383   }
8384   GST_OBJECT_UNLOCK (qtdemux);
8385
8386   return TRUE;
8387
8388   /* SUCCESS */
8389 already_parsed:
8390   {
8391     GST_LOG_OBJECT (qtdemux,
8392         "Tried to parse up to sample %u but this sample has already been parsed",
8393         n);
8394     /* if fragmented, there may be more */
8395     if (qtdemux->fragmented && n == stream->stbl_index)
8396       goto done;
8397     GST_OBJECT_UNLOCK (qtdemux);
8398     return TRUE;
8399   }
8400   /* ERRORS */
8401 out_of_samples:
8402   {
8403     GST_LOG_OBJECT (qtdemux,
8404         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8405         stream->n_samples);
8406     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8407         (_("This file is corrupt and cannot be played.")), (NULL));
8408     return FALSE;
8409   }
8410 corrupt_file:
8411   {
8412     GST_OBJECT_UNLOCK (qtdemux);
8413     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8414         (_("This file is corrupt and cannot be played.")), (NULL));
8415     return FALSE;
8416   }
8417 }
8418
8419 /* collect all segment info for @stream.
8420  */
8421 static gboolean
8422 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8423     GNode * trak)
8424 {
8425   GNode *edts;
8426   /* accept edts if they contain gaps at start and there is only
8427    * one media segment */
8428   gboolean allow_pushbased_edts = TRUE;
8429   gint media_segments_count = 0;
8430
8431   /* parse and prepare segment info from the edit list */
8432   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8433   stream->n_segments = 0;
8434   stream->segments = NULL;
8435   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8436     GNode *elst;
8437     gint n_segments;
8438     gint i, count, entry_size;
8439     guint64 time;
8440     GstClockTime stime;
8441     guint8 *buffer;
8442     guint8 version;
8443
8444     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8445     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8446       goto done;
8447
8448     buffer = elst->data;
8449
8450     version = QT_UINT8 (buffer + 8);
8451     entry_size = (version == 1) ? 20 : 12;
8452
8453     n_segments = QT_UINT32 (buffer + 12);
8454
8455     /* we might allocate a bit too much, at least allocate 1 segment */
8456     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8457
8458     /* segments always start from 0 */
8459     time = 0;
8460     stime = 0;
8461     count = 0;
8462     for (i = 0; i < n_segments; i++) {
8463       guint64 duration;
8464       guint64 media_time;
8465       gboolean time_valid = TRUE;
8466       QtDemuxSegment *segment;
8467       guint32 rate_int;
8468       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8469
8470       if (version == 1) {
8471         media_time = QT_UINT64 (buffer + 24 + i * entry_size);
8472         duration = QT_UINT64 (buffer + 16 + i * entry_size);
8473         if (media_time == G_MAXUINT64)
8474           time_valid = FALSE;
8475       } else {
8476         media_time = QT_UINT32 (buffer + 20 + i * entry_size);
8477         duration = QT_UINT32 (buffer + 16 + i * entry_size);
8478         if (media_time == G_MAXUINT32)
8479           time_valid = FALSE;
8480       }
8481
8482       if (time_valid)
8483         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8484
8485       segment = &stream->segments[count++];
8486
8487       /* time and duration expressed in global timescale */
8488       segment->time = stime;
8489       /* add non scaled values so we don't cause roundoff errors */
8490       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8491         time += duration;
8492         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8493         segment->duration = stime - segment->time;
8494       } else {
8495         /* zero duration does not imply media_start == media_stop
8496          * but, only specify media_start.*/
8497         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8498         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8499             && stime >= media_start) {
8500           segment->duration = stime - media_start;
8501         } else {
8502           segment->duration = GST_CLOCK_TIME_NONE;
8503         }
8504       }
8505       segment->stop_time = stime;
8506
8507       segment->trak_media_start = media_time;
8508       /* media_time expressed in stream timescale */
8509       if (time_valid) {
8510         segment->media_start = media_start;
8511         segment->media_stop = segment->media_start + segment->duration;
8512         media_segments_count++;
8513       } else {
8514         segment->media_start = GST_CLOCK_TIME_NONE;
8515         segment->media_stop = GST_CLOCK_TIME_NONE;
8516       }
8517       rate_int =
8518           QT_UINT32 (buffer + ((version == 1) ? 32 : 24) + i * entry_size);
8519
8520       if (rate_int <= 1) {
8521         /* 0 is not allowed, some programs write 1 instead of the floating point
8522          * value */
8523         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8524             rate_int);
8525         segment->rate = 1;
8526       } else {
8527         segment->rate = rate_int / 65536.0;
8528       }
8529
8530       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8531           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8532           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8533           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8534           i, GST_TIME_ARGS (segment->time),
8535           GST_TIME_ARGS (segment->duration),
8536           GST_TIME_ARGS (segment->media_start), media_time,
8537           GST_TIME_ARGS (segment->media_stop),
8538           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8539           stream->timescale);
8540       if (segment->stop_time > qtdemux->segment.stop) {
8541         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8542             " extends to %" GST_TIME_FORMAT
8543             " past the end of the file duration %" GST_TIME_FORMAT
8544             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8545             GST_TIME_ARGS (qtdemux->segment.stop));
8546         qtdemux->segment.stop = segment->stop_time;
8547       }
8548     }
8549     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8550     stream->n_segments = count;
8551     if (media_segments_count != 1)
8552       allow_pushbased_edts = FALSE;
8553   }
8554 done:
8555
8556   /* push based does not handle segments, so act accordingly here,
8557    * and warn if applicable */
8558   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8559     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8560     /* remove and use default one below, we stream like it anyway */
8561     g_free (stream->segments);
8562     stream->segments = NULL;
8563     stream->n_segments = 0;
8564   }
8565
8566   /* no segments, create one to play the complete trak */
8567   if (stream->n_segments == 0) {
8568     GstClockTime stream_duration =
8569         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8570
8571     if (stream->segments == NULL)
8572       stream->segments = g_new (QtDemuxSegment, 1);
8573
8574     /* represent unknown our way */
8575     if (stream_duration == 0)
8576       stream_duration = GST_CLOCK_TIME_NONE;
8577
8578     stream->segments[0].time = 0;
8579     stream->segments[0].stop_time = stream_duration;
8580     stream->segments[0].duration = stream_duration;
8581     stream->segments[0].media_start = 0;
8582     stream->segments[0].media_stop = stream_duration;
8583     stream->segments[0].rate = 1.0;
8584     stream->segments[0].trak_media_start = 0;
8585
8586     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8587         GST_TIME_ARGS (stream_duration));
8588     stream->n_segments = 1;
8589     stream->dummy_segment = TRUE;
8590   }
8591   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8592
8593   return TRUE;
8594 }
8595
8596 /*
8597  * Parses the stsd atom of a svq3 trak looking for
8598  * the SMI and gama atoms.
8599  */
8600 static void
8601 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8602     guint8 ** gamma, GstBuffer ** seqh)
8603 {
8604   guint8 *_gamma = NULL;
8605   GstBuffer *_seqh = NULL;
8606   guint8 *stsd_data = stsd->data;
8607   guint32 length = QT_UINT32 (stsd_data);
8608   guint16 version;
8609
8610   if (length < 32) {
8611     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8612     goto end;
8613   }
8614
8615   stsd_data += 32;
8616   length -= 32;
8617   version = QT_UINT16 (stsd_data);
8618   if (version == 3) {
8619     if (length >= 70) {
8620       length -= 70;
8621       stsd_data += 70;
8622       while (length > 8) {
8623         guint32 fourcc, size;
8624         guint8 *data;
8625         size = QT_UINT32 (stsd_data);
8626         fourcc = QT_FOURCC (stsd_data + 4);
8627         data = stsd_data + 8;
8628
8629         if (size == 0) {
8630           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8631               "svq3 atom parsing");
8632           goto end;
8633         }
8634
8635         switch (fourcc) {
8636           case FOURCC_gama:{
8637             if (size == 12) {
8638               _gamma = data;
8639             } else {
8640               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8641                   " for gama atom, expected 12", size);
8642             }
8643             break;
8644           }
8645           case FOURCC_SMI_:{
8646             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8647               guint32 seqh_size;
8648               if (_seqh != NULL) {
8649                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8650                     " found, ignoring");
8651               } else {
8652                 seqh_size = QT_UINT32 (data + 4);
8653                 if (seqh_size > 0) {
8654                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8655                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8656                 }
8657               }
8658             }
8659             break;
8660           }
8661           default:{
8662             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8663                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8664           }
8665         }
8666
8667         if (size <= length) {
8668           length -= size;
8669           stsd_data += size;
8670         }
8671       }
8672     } else {
8673       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8674     }
8675   } else {
8676     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8677         G_GUINT16_FORMAT, version);
8678     goto end;
8679   }
8680
8681 end:
8682   if (gamma) {
8683     *gamma = _gamma;
8684   }
8685   if (seqh) {
8686     *seqh = _seqh;
8687   } else if (_seqh) {
8688     gst_buffer_unref (_seqh);
8689   }
8690 }
8691
8692 static gchar *
8693 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8694 {
8695   GNode *dinf;
8696   GstByteReader dref;
8697   gchar *uri = NULL;
8698
8699   /*
8700    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8701    * atom that might contain a 'data' atom with the rtsp uri.
8702    * This case was reported in bug #597497, some info about
8703    * the hndl atom can be found in TN1195
8704    */
8705   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8706   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8707
8708   if (dinf) {
8709     guint32 dref_num_entries = 0;
8710     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8711         gst_byte_reader_skip (&dref, 4) &&
8712         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8713       gint i;
8714
8715       /* search dref entries for hndl atom */
8716       for (i = 0; i < dref_num_entries; i++) {
8717         guint32 size = 0, type;
8718         guint8 string_len = 0;
8719         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8720             qt_atom_parser_get_fourcc (&dref, &type)) {
8721           if (type == FOURCC_hndl) {
8722             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8723
8724             /* skip data reference handle bytes and the
8725              * following pascal string and some extra 4
8726              * bytes I have no idea what are */
8727             if (!gst_byte_reader_skip (&dref, 4) ||
8728                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8729                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8730               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8731               break;
8732             }
8733
8734             /* iterate over the atoms to find the data atom */
8735             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8736               guint32 atom_size;
8737               guint32 atom_type;
8738
8739               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8740                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8741                 if (atom_type == FOURCC_data) {
8742                   const guint8 *uri_aux = NULL;
8743
8744                   /* found the data atom that might contain the rtsp uri */
8745                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8746                       "hndl atom, interpreting it as an URI");
8747                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8748                           &uri_aux)) {
8749                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8750                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8751                     else
8752                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8753                           "didn't contain a rtsp address");
8754                   } else {
8755                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8756                         "atom contents");
8757                   }
8758                   break;
8759                 }
8760                 /* skipping to the next entry */
8761                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8762                   break;
8763               } else {
8764                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8765                     "atom header");
8766                 break;
8767               }
8768             }
8769             break;
8770           }
8771           /* skip to the next entry */
8772           if (!gst_byte_reader_skip (&dref, size - 8))
8773             break;
8774         } else {
8775           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8776         }
8777       }
8778       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8779     }
8780   }
8781   return uri;
8782 }
8783
8784 #define AMR_NB_ALL_MODES        0x81ff
8785 #define AMR_WB_ALL_MODES        0x83ff
8786 static guint
8787 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8788 {
8789   /* The 'damr' atom is of the form:
8790    *
8791    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8792    *    32 b       8 b          16 b           8 b                 8 b
8793    *
8794    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8795    * represents the highest mode used in the stream (and thus the maximum
8796    * bitrate), with a couple of special cases as seen below.
8797    */
8798
8799   /* Map of frame type ID -> bitrate */
8800   static const guint nb_bitrates[] = {
8801     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8802   };
8803   static const guint wb_bitrates[] = {
8804     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8805   };
8806   GstMapInfo map;
8807   gsize max_mode;
8808   guint16 mode_set;
8809
8810   gst_buffer_map (buf, &map, GST_MAP_READ);
8811
8812   if (map.size != 0x11) {
8813     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8814     goto bad_data;
8815   }
8816
8817   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8818     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8819         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8820     goto bad_data;
8821   }
8822
8823   mode_set = QT_UINT16 (map.data + 13);
8824
8825   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8826     max_mode = 7 + (wb ? 1 : 0);
8827   else
8828     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8829     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8830
8831   if (max_mode == -1) {
8832     GST_DEBUG ("No mode indication was found (mode set) = %x",
8833         (guint) mode_set);
8834     goto bad_data;
8835   }
8836
8837   gst_buffer_unmap (buf, &map);
8838   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8839
8840 bad_data:
8841   gst_buffer_unmap (buf, &map);
8842   return 0;
8843 }
8844
8845 static gboolean
8846 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8847     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8848 {
8849   /*
8850    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8851    * [0 1 2]
8852    * [3 4 5]
8853    * [6 7 8]
8854    */
8855
8856   if (gst_byte_reader_get_remaining (reader) < 36)
8857     return FALSE;
8858
8859   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8860   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8861   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8862   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8863   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8864   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8865   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8866   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8867   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8868
8869   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8870   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8871       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8872       matrix[2] & 0xFF);
8873   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8874       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8875       matrix[5] & 0xFF);
8876   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8877       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8878       matrix[8] & 0xFF);
8879
8880   return TRUE;
8881 }
8882
8883 static void
8884 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8885     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8886 {
8887
8888 /* [a b c]
8889  * [d e f]
8890  * [g h i]
8891  *
8892  * This macro will only compare value abdegh, it expects cfi to have already
8893  * been checked
8894  */
8895 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8896                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8897
8898   /* only handle the cases where the last column has standard values */
8899   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8900     const gchar *rotation_tag = NULL;
8901
8902     /* no rotation needed */
8903     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8904       /* NOP */
8905     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8906       rotation_tag = "rotate-90";
8907     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8908       rotation_tag = "rotate-180";
8909     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8910       rotation_tag = "rotate-270";
8911     } else {
8912       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8913     }
8914
8915     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8916         rotation_tag);
8917     if (rotation_tag != NULL) {
8918       if (*taglist == NULL)
8919         *taglist = gst_tag_list_new_empty ();
8920       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8921           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8922     }
8923   } else {
8924     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8925   }
8926 }
8927
8928 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8929  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8930  * Common Encryption (cenc), the function will also parse the tenc box (defined
8931  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8932  * (typically an enc[v|a|t|s] sample entry); the function will set
8933  * @original_fmt to the fourcc of the original unencrypted stream format.
8934  * Returns TRUE if successful; FALSE otherwise. */
8935 static gboolean
8936 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8937     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8938 {
8939   GNode *sinf;
8940   GNode *frma;
8941   GNode *schm;
8942   GNode *schi;
8943
8944   g_return_val_if_fail (qtdemux != NULL, FALSE);
8945   g_return_val_if_fail (stream != NULL, FALSE);
8946   g_return_val_if_fail (container != NULL, FALSE);
8947   g_return_val_if_fail (original_fmt != NULL, FALSE);
8948
8949   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8950   if (G_UNLIKELY (!sinf)) {
8951     if (stream->protection_scheme_type == FOURCC_cenc) {
8952       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8953           "mandatory for Common Encryption");
8954       return FALSE;
8955     }
8956     return TRUE;
8957   }
8958
8959   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8960   if (G_UNLIKELY (!frma)) {
8961     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8962     return FALSE;
8963   }
8964
8965   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8966   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8967       GST_FOURCC_ARGS (*original_fmt));
8968
8969   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8970   if (!schm) {
8971     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8972     return FALSE;
8973   }
8974   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
8975   stream->protection_scheme_version =
8976       QT_UINT32 ((const guint8 *) schm->data + 16);
8977
8978   GST_DEBUG_OBJECT (qtdemux,
8979       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
8980       "protection_scheme_version: %#010x",
8981       GST_FOURCC_ARGS (stream->protection_scheme_type),
8982       stream->protection_scheme_version);
8983
8984   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
8985   if (!schi) {
8986     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
8987     return FALSE;
8988   }
8989   if (stream->protection_scheme_type == FOURCC_cenc) {
8990     QtDemuxCencSampleSetInfo *info;
8991     GNode *tenc;
8992     const guint8 *tenc_data;
8993     guint32 isEncrypted;
8994     guint8 iv_size;
8995     const guint8 *default_kid;
8996     GstBuffer *kid_buf;
8997
8998     if (G_UNLIKELY (!stream->protection_scheme_info))
8999       stream->protection_scheme_info =
9000           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9001
9002     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9003
9004     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9005     if (!tenc) {
9006       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9007           "which is mandatory for Common Encryption");
9008       return FALSE;
9009     }
9010     tenc_data = (const guint8 *) tenc->data + 12;
9011     isEncrypted = QT_UINT24 (tenc_data);
9012     iv_size = QT_UINT8 (tenc_data + 3);
9013     default_kid = (tenc_data + 4);
9014     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9015     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9016     if (info->default_properties)
9017       gst_structure_free (info->default_properties);
9018     info->default_properties =
9019         gst_structure_new ("application/x-cenc",
9020         "iv_size", G_TYPE_UINT, iv_size,
9021         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9022         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9023     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9024         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9025     gst_buffer_unref (kid_buf);
9026   }
9027   return TRUE;
9028 }
9029
9030 /* parse the traks.
9031  * With each track we associate a new QtDemuxStream that contains all the info
9032  * about the trak.
9033  * traks that do not decode to something (like strm traks) will not have a pad.
9034  */
9035 static gboolean
9036 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9037 {
9038   GstByteReader tkhd;
9039   int offset;
9040   GNode *mdia;
9041   GNode *mdhd;
9042   GNode *hdlr;
9043   GNode *minf;
9044   GNode *stbl;
9045   GNode *stsd;
9046   GNode *mp4a;
9047   GNode *mp4v;
9048   GNode *wave;
9049   GNode *esds;
9050   GNode *pasp;
9051   GNode *tref;
9052   GNode *udta;
9053   GNode *svmi;
9054
9055   QtDemuxStream *stream = NULL;
9056   gboolean new_stream = FALSE;
9057   gchar *codec = NULL;
9058   const guint8 *stsd_data;
9059   guint16 lang_code;            /* quicktime lang code or packed iso code */
9060   guint32 version;
9061   guint32 tkhd_flags = 0;
9062   guint8 tkhd_version = 0;
9063   guint32 fourcc;
9064   guint value_size, stsd_len, len;
9065   guint32 track_id;
9066   guint32 dummy;
9067
9068   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9069
9070   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9071       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9072       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9073     goto corrupt_file;
9074
9075   /* pick between 64 or 32 bits */
9076   value_size = tkhd_version == 1 ? 8 : 4;
9077   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9078       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9079     goto corrupt_file;
9080
9081   if (!qtdemux->got_moov) {
9082     if (qtdemux_find_stream (qtdemux, track_id))
9083       goto existing_stream;
9084     stream = _create_stream ();
9085     stream->track_id = track_id;
9086     new_stream = TRUE;
9087   } else {
9088     stream = qtdemux_find_stream (qtdemux, track_id);
9089     if (!stream) {
9090       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9091       goto skip_track;
9092     }
9093
9094     /* flush samples data from this track from previous moov */
9095     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9096     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9097   }
9098   /* need defaults for fragments */
9099   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9100
9101   if (stream->pending_tags == NULL)
9102     stream->pending_tags = gst_tag_list_new_empty ();
9103
9104   if ((tkhd_flags & 1) == 0)
9105     stream->disabled = TRUE;
9106
9107   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9108       tkhd_version, tkhd_flags, stream->track_id);
9109
9110   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9111     goto corrupt_file;
9112
9113   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9114     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9115     if (qtdemux->major_brand != FOURCC_mjp2 ||
9116         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9117       goto corrupt_file;
9118   }
9119
9120   len = QT_UINT32 ((guint8 *) mdhd->data);
9121   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9122   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9123   if (version == 0x01000000) {
9124     if (len < 38)
9125       goto corrupt_file;
9126     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9127     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9128     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9129   } else {
9130     if (len < 30)
9131       goto corrupt_file;
9132     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9133     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9134     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9135   }
9136
9137   if (lang_code < 0x400) {
9138     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9139   } else if (lang_code == 0x7fff) {
9140     stream->lang_id[0] = 0;     /* unspecified */
9141   } else {
9142     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9143     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9144     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9145     stream->lang_id[3] = 0;
9146   }
9147
9148   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9149       stream->timescale);
9150   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9151       stream->duration);
9152   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9153       lang_code, stream->lang_id);
9154
9155   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9156     goto corrupt_file;
9157
9158   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9159     /* chapters track reference */
9160     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9161     if (chap) {
9162       gsize length = GST_READ_UINT32_BE (chap->data);
9163       if (qtdemux->chapters_track_id)
9164         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9165
9166       if (length >= 12) {
9167         qtdemux->chapters_track_id =
9168             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9169       }
9170     }
9171   }
9172
9173   /* fragmented files may have bogus duration in moov */
9174   if (!qtdemux->fragmented &&
9175       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9176     guint64 tdur1, tdur2;
9177
9178     /* don't overflow */
9179     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9180     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9181
9182     /* HACK:
9183      * some of those trailers, nowadays, have prologue images that are
9184      * themselves video tracks as well. I haven't really found a way to
9185      * identify those yet, except for just looking at their duration. */
9186     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9187       GST_WARNING_OBJECT (qtdemux,
9188           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9189           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9190           "found, assuming preview image or something; skipping track",
9191           stream->duration, stream->timescale, qtdemux->duration,
9192           qtdemux->timescale);
9193       if (new_stream)
9194         gst_qtdemux_stream_free (qtdemux, stream);
9195       return TRUE;
9196     }
9197   }
9198
9199   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9200     goto corrupt_file;
9201
9202   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9203       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9204
9205   len = QT_UINT32 ((guint8 *) hdlr->data);
9206   if (len >= 20)
9207     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9208   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9209       GST_FOURCC_ARGS (stream->subtype));
9210
9211   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9212     goto corrupt_file;
9213
9214   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9215     goto corrupt_file;
9216
9217   /*parse svmi header if existing */
9218   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9219   if (svmi) {
9220     len = QT_UINT32 ((guint8 *) svmi->data);
9221     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9222     if (!version) {
9223       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9224       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9225       guint8 frame_type, frame_layout;
9226
9227       /* MPEG-A stereo video */
9228       if (qtdemux->major_brand == FOURCC_ss02)
9229         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9230
9231       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9232       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9233       switch (frame_type) {
9234         case 0:
9235           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9236           break;
9237         case 1:
9238           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9239           break;
9240         case 2:
9241           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9242           break;
9243         case 3:
9244           /* mode 3 is primary/secondary view sequence, ie
9245            * left/right views in separate tracks. See section 7.2
9246            * of ISO/IEC 23000-11:2009 */
9247           GST_FIXME_OBJECT (qtdemux,
9248               "Implement stereo video in separate streams");
9249       }
9250
9251       if ((frame_layout & 0x1) == 0)
9252         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9253
9254       GST_LOG_OBJECT (qtdemux,
9255           "StereoVideo: composition type: %u, is_left_first: %u",
9256           frame_type, frame_layout);
9257       stream->multiview_mode = mode;
9258       stream->multiview_flags = flags;
9259     }
9260   }
9261
9262   /* parse stsd */
9263   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9264     goto corrupt_file;
9265   stsd_data = (const guint8 *) stsd->data;
9266
9267   /* stsd should at least have one entry */
9268   stsd_len = QT_UINT32 (stsd_data);
9269   if (stsd_len < 24) {
9270     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9271     if (stream->subtype == FOURCC_vivo) {
9272       if (new_stream)
9273         gst_qtdemux_stream_free (qtdemux, stream);
9274       return TRUE;
9275     } else {
9276       goto corrupt_file;
9277     }
9278   }
9279
9280   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9281
9282   /* and that entry should fit within stsd */
9283   len = QT_UINT32 (stsd_data + 16);
9284   if (len > stsd_len + 16)
9285     goto corrupt_file;
9286
9287   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9288   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9289       GST_FOURCC_ARGS (stream->fourcc));
9290   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9291
9292   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9293     goto error_encrypted;
9294
9295   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9296     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9297     stream->protected = TRUE;
9298     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9299       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9300   }
9301
9302   if (stream->subtype == FOURCC_vide) {
9303     guint32 w = 0, h = 0;
9304     gboolean gray;
9305     gint depth, palette_size, palette_count;
9306     guint32 matrix[9];
9307     guint32 *palette_data = NULL;
9308
9309     stream->sampled = TRUE;
9310
9311     /* version 1 uses some 64-bit ints */
9312     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9313       goto corrupt_file;
9314
9315     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9316       goto corrupt_file;
9317
9318     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9319         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9320       goto corrupt_file;
9321
9322     stream->display_width = w >> 16;
9323     stream->display_height = h >> 16;
9324
9325     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9326         &stream->pending_tags);
9327
9328     offset = 16;
9329     if (len < 86)
9330       goto corrupt_file;
9331
9332     stream->width = QT_UINT16 (stsd_data + offset + 32);
9333     stream->height = QT_UINT16 (stsd_data + offset + 34);
9334     stream->fps_n = 0;          /* this is filled in later */
9335     stream->fps_d = 0;          /* this is filled in later */
9336     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9337     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9338
9339     /* if color_table_id is 0, ctab atom must follow; however some files
9340      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9341      * if color table is not present we'll correct the value */
9342     if (stream->color_table_id == 0 &&
9343         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9344       stream->color_table_id = -1;
9345     }
9346
9347     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9348         stream->width, stream->height, stream->bits_per_sample,
9349         stream->color_table_id);
9350
9351     depth = stream->bits_per_sample;
9352
9353     /* more than 32 bits means grayscale */
9354     gray = (depth > 32);
9355     /* low 32 bits specify the depth  */
9356     depth &= 0x1F;
9357
9358     /* different number of palette entries is determined by depth. */
9359     palette_count = 0;
9360     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9361       palette_count = (1 << depth);
9362     palette_size = palette_count * 4;
9363
9364     if (stream->color_table_id) {
9365       switch (palette_count) {
9366         case 0:
9367           break;
9368         case 2:
9369           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9370           break;
9371         case 4:
9372           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9373           break;
9374         case 16:
9375           if (gray)
9376             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9377           else
9378             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9379           break;
9380         case 256:
9381           if (gray)
9382             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9383           else
9384             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9385           break;
9386         default:
9387           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9388               (_("The video in this file might not play correctly.")),
9389               ("unsupported palette depth %d", depth));
9390           break;
9391       }
9392     } else {
9393       gint i, j, start, end;
9394
9395       if (len < 94)
9396         goto corrupt_file;
9397
9398       /* read table */
9399       start = QT_UINT32 (stsd_data + offset + 86);
9400       palette_count = QT_UINT16 (stsd_data + offset + 90);
9401       end = QT_UINT16 (stsd_data + offset + 92);
9402
9403       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9404           start, end, palette_count);
9405
9406       if (end > 255)
9407         end = 255;
9408       if (start > end)
9409         start = end;
9410
9411       if (len < 94 + (end - start) * 8)
9412         goto corrupt_file;
9413
9414       /* palette is always the same size */
9415       palette_data = g_malloc0 (256 * 4);
9416       palette_size = 256 * 4;
9417
9418       for (j = 0, i = start; i <= end; j++, i++) {
9419         guint32 a, r, g, b;
9420
9421         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9422         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9423         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9424         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9425
9426         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9427             (g & 0xff00) | (b >> 8);
9428       }
9429     }
9430
9431     if (stream->caps)
9432       gst_caps_unref (stream->caps);
9433
9434     stream->caps =
9435         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9436     if (G_UNLIKELY (!stream->caps)) {
9437       g_free (palette_data);
9438       goto unknown_stream;
9439     }
9440
9441     if (codec) {
9442       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9443           GST_TAG_VIDEO_CODEC, codec, NULL);
9444       g_free (codec);
9445       codec = NULL;
9446     }
9447
9448
9449     if (palette_data) {
9450       GstStructure *s;
9451
9452       if (stream->rgb8_palette)
9453         gst_memory_unref (stream->rgb8_palette);
9454       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9455           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9456
9457       s = gst_caps_get_structure (stream->caps, 0);
9458
9459       /* non-raw video has a palette_data property. raw video has the palette as
9460        * an extra plane that we append to the output buffers before we push
9461        * them*/
9462       if (!gst_structure_has_name (s, "video/x-raw")) {
9463         GstBuffer *palette;
9464
9465         palette = gst_buffer_new ();
9466         gst_buffer_append_memory (palette, stream->rgb8_palette);
9467         stream->rgb8_palette = NULL;
9468
9469         gst_caps_set_simple (stream->caps, "palette_data",
9470             GST_TYPE_BUFFER, palette, NULL);
9471         gst_buffer_unref (palette);
9472       }
9473     } else if (palette_count != 0) {
9474       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9475           (NULL), ("Unsupported palette depth %d", depth));
9476     }
9477
9478     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9479         QT_UINT16 (stsd_data + offset + 48));
9480
9481     esds = NULL;
9482     pasp = NULL;
9483     /* pick 'the' stsd child */
9484     if (!stream->protected)
9485       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9486     else
9487       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9488
9489     if (mp4v) {
9490       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9491       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9492     }
9493
9494     if (pasp) {
9495       const guint8 *pasp_data = (const guint8 *) pasp->data;
9496
9497       stream->par_w = QT_UINT32 (pasp_data + 8);
9498       stream->par_h = QT_UINT32 (pasp_data + 12);
9499     } else {
9500       stream->par_w = 0;
9501       stream->par_h = 0;
9502     }
9503
9504     if (esds) {
9505       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9506     } else {
9507       switch (fourcc) {
9508         case FOURCC_H264:
9509         case FOURCC_avc1:
9510         case FOURCC_avc3:
9511         {
9512           gint len = QT_UINT32 (stsd_data) - 0x66;
9513           const guint8 *avc_data = stsd_data + 0x66;
9514
9515           /* find avcC */
9516           while (len >= 0x8) {
9517             gint size;
9518
9519             if (QT_UINT32 (avc_data) <= len)
9520               size = QT_UINT32 (avc_data) - 0x8;
9521             else
9522               size = len - 0x8;
9523
9524             if (size < 1)
9525               /* No real data, so break out */
9526               break;
9527
9528             switch (QT_FOURCC (avc_data + 0x4)) {
9529               case FOURCC_avcC:
9530               {
9531                 /* parse, if found */
9532                 GstBuffer *buf;
9533
9534                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9535
9536                 /* First 4 bytes are the length of the atom, the next 4 bytes
9537                  * are the fourcc, the next 1 byte is the version, and the
9538                  * subsequent bytes are profile_tier_level structure like data. */
9539                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9540                     avc_data + 8 + 1, size - 1);
9541                 buf = gst_buffer_new_and_alloc (size);
9542                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9543                 gst_caps_set_simple (stream->caps,
9544                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9545                 gst_buffer_unref (buf);
9546
9547                 break;
9548               }
9549               case FOURCC_strf:
9550               {
9551                 GstBuffer *buf;
9552
9553                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9554
9555                 /* First 4 bytes are the length of the atom, the next 4 bytes
9556                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9557                  * next 1 byte is the version, and the
9558                  * subsequent bytes are sequence parameter set like data. */
9559
9560                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9561                 if (size > 1) {
9562                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9563                       avc_data + 8 + 40 + 1, size - 1);
9564
9565                   buf = gst_buffer_new_and_alloc (size);
9566                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9567                   gst_caps_set_simple (stream->caps,
9568                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9569                   gst_buffer_unref (buf);
9570                 }
9571                 break;
9572               }
9573               case FOURCC_btrt:
9574               {
9575                 guint avg_bitrate, max_bitrate;
9576
9577                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9578                 if (size < 12)
9579                   break;
9580
9581                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9582                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9583
9584                 if (!max_bitrate && !avg_bitrate)
9585                   break;
9586
9587                 /* Some muxers seem to swap the average and maximum bitrates
9588                  * (I'm looking at you, YouTube), so we swap for sanity. */
9589                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9590                   guint temp = avg_bitrate;
9591
9592                   avg_bitrate = max_bitrate;
9593                   max_bitrate = temp;
9594                 }
9595
9596                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9597                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9598                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9599                 }
9600                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9601                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9602                       GST_TAG_BITRATE, avg_bitrate, NULL);
9603                 }
9604
9605                 break;
9606               }
9607
9608               default:
9609                 break;
9610             }
9611
9612             len -= size + 8;
9613             avc_data += size + 8;
9614           }
9615
9616           break;
9617         }
9618         case FOURCC_H265:
9619         case FOURCC_hvc1:
9620         case FOURCC_hev1:
9621         {
9622           gint len = QT_UINT32 (stsd_data) - 0x66;
9623           const guint8 *hevc_data = stsd_data + 0x66;
9624
9625           /* find hevc */
9626           while (len >= 0x8) {
9627             gint size;
9628
9629             if (QT_UINT32 (hevc_data) <= len)
9630               size = QT_UINT32 (hevc_data) - 0x8;
9631             else
9632               size = len - 0x8;
9633
9634             if (size < 1)
9635               /* No real data, so break out */
9636               break;
9637
9638             switch (QT_FOURCC (hevc_data + 0x4)) {
9639               case FOURCC_hvcC:
9640               {
9641                 /* parse, if found */
9642                 GstBuffer *buf;
9643
9644                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9645
9646                 /* First 4 bytes are the length of the atom, the next 4 bytes
9647                  * are the fourcc, the next 1 byte is the version, and the
9648                  * subsequent bytes are sequence parameter set like data. */
9649                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9650                     (stream->caps, hevc_data + 8 + 1, size - 1);
9651
9652                 buf = gst_buffer_new_and_alloc (size);
9653                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9654                 gst_caps_set_simple (stream->caps,
9655                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9656                 gst_buffer_unref (buf);
9657                 break;
9658               }
9659               default:
9660                 break;
9661             }
9662             len -= size + 8;
9663             hevc_data += size + 8;
9664           }
9665           break;
9666         }
9667         case FOURCC_mp4v:
9668         case FOURCC_MP4V:
9669         case FOURCC_fmp4:
9670         case FOURCC_FMP4:
9671         {
9672           GNode *glbl;
9673
9674           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9675               GST_FOURCC_ARGS (fourcc));
9676
9677           /* codec data might be in glbl extension atom */
9678           glbl = mp4v ?
9679               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9680           if (glbl) {
9681             guint8 *data;
9682             GstBuffer *buf;
9683             gint len;
9684
9685             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9686             data = glbl->data;
9687             len = QT_UINT32 (data);
9688             if (len > 0x8) {
9689               len -= 0x8;
9690               buf = gst_buffer_new_and_alloc (len);
9691               gst_buffer_fill (buf, 0, data + 8, len);
9692               gst_caps_set_simple (stream->caps,
9693                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9694               gst_buffer_unref (buf);
9695             }
9696           }
9697           break;
9698         }
9699         case FOURCC_mjp2:
9700         {
9701           /* see annex I of the jpeg2000 spec */
9702           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9703           const guint8 *data;
9704           const gchar *colorspace = NULL;
9705           gint ncomp = 0;
9706           guint32 ncomp_map = 0;
9707           gint32 *comp_map = NULL;
9708           guint32 nchan_def = 0;
9709           gint32 *chan_def = NULL;
9710
9711           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9712           /* some required atoms */
9713           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9714           if (!mjp2)
9715             break;
9716           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9717           if (!jp2h)
9718             break;
9719
9720           /* number of components; redundant with info in codestream, but useful
9721              to a muxer */
9722           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9723           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9724             break;
9725           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9726
9727           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9728           if (!colr)
9729             break;
9730           GST_DEBUG_OBJECT (qtdemux, "found colr");
9731           /* extract colour space info */
9732           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9733             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9734               case 16:
9735                 colorspace = "sRGB";
9736                 break;
9737               case 17:
9738                 colorspace = "GRAY";
9739                 break;
9740               case 18:
9741                 colorspace = "sYUV";
9742                 break;
9743               default:
9744                 colorspace = NULL;
9745                 break;
9746             }
9747           }
9748           if (!colorspace)
9749             /* colr is required, and only values 16, 17, and 18 are specified,
9750                so error if we have no colorspace */
9751             break;
9752
9753           /* extract component mapping */
9754           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9755           if (cmap) {
9756             guint32 cmap_len = 0;
9757             int i;
9758             cmap_len = QT_UINT32 (cmap->data);
9759             if (cmap_len >= 8) {
9760               /* normal box, subtract off header */
9761               cmap_len -= 8;
9762               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9763               if (cmap_len % 4 == 0) {
9764                 ncomp_map = (cmap_len / 4);
9765                 comp_map = g_new0 (gint32, ncomp_map);
9766                 for (i = 0; i < ncomp_map; i++) {
9767                   guint16 cmp;
9768                   guint8 mtyp, pcol;
9769                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9770                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9771                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9772                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9773                 }
9774               }
9775             }
9776           }
9777           /* extract channel definitions */
9778           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9779           if (cdef) {
9780             guint32 cdef_len = 0;
9781             int i;
9782             cdef_len = QT_UINT32 (cdef->data);
9783             if (cdef_len >= 10) {
9784               /* normal box, subtract off header and len */
9785               cdef_len -= 10;
9786               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9787               if (cdef_len % 6 == 0) {
9788                 nchan_def = (cdef_len / 6);
9789                 chan_def = g_new0 (gint32, nchan_def);
9790                 for (i = 0; i < nchan_def; i++)
9791                   chan_def[i] = -1;
9792                 for (i = 0; i < nchan_def; i++) {
9793                   guint16 cn, typ, asoc;
9794                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9795                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9796                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9797                   if (cn < nchan_def) {
9798                     switch (typ) {
9799                       case 0:
9800                         chan_def[cn] = asoc;
9801                         break;
9802                       case 1:
9803                         chan_def[cn] = 0;       /* alpha */
9804                         break;
9805                       default:
9806                         chan_def[cn] = -typ;
9807                     }
9808                   }
9809                 }
9810               }
9811             }
9812           }
9813
9814           gst_caps_set_simple (stream->caps,
9815               "num-components", G_TYPE_INT, ncomp, NULL);
9816           gst_caps_set_simple (stream->caps,
9817               "colorspace", G_TYPE_STRING, colorspace, NULL);
9818
9819           if (comp_map) {
9820             GValue arr = { 0, };
9821             GValue elt = { 0, };
9822             int i;
9823             g_value_init (&arr, GST_TYPE_ARRAY);
9824             g_value_init (&elt, G_TYPE_INT);
9825             for (i = 0; i < ncomp_map; i++) {
9826               g_value_set_int (&elt, comp_map[i]);
9827               gst_value_array_append_value (&arr, &elt);
9828             }
9829             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9830                 "component-map", &arr);
9831             g_value_unset (&elt);
9832             g_value_unset (&arr);
9833             g_free (comp_map);
9834           }
9835
9836           if (chan_def) {
9837             GValue arr = { 0, };
9838             GValue elt = { 0, };
9839             int i;
9840             g_value_init (&arr, GST_TYPE_ARRAY);
9841             g_value_init (&elt, G_TYPE_INT);
9842             for (i = 0; i < nchan_def; i++) {
9843               g_value_set_int (&elt, chan_def[i]);
9844               gst_value_array_append_value (&arr, &elt);
9845             }
9846             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9847                 "channel-definitions", &arr);
9848             g_value_unset (&elt);
9849             g_value_unset (&arr);
9850             g_free (chan_def);
9851           }
9852
9853           /* some optional atoms */
9854           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9855           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9856
9857           /* indicate possible fields in caps */
9858           if (field) {
9859             data = (guint8 *) field->data + 8;
9860             if (*data != 1)
9861               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9862                   (gint) * data, NULL);
9863           }
9864           /* add codec_data if provided */
9865           if (prefix) {
9866             GstBuffer *buf;
9867             gint len;
9868
9869             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9870             data = prefix->data;
9871             len = QT_UINT32 (data);
9872             if (len > 0x8) {
9873               len -= 0x8;
9874               buf = gst_buffer_new_and_alloc (len);
9875               gst_buffer_fill (buf, 0, data + 8, len);
9876               gst_caps_set_simple (stream->caps,
9877                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9878               gst_buffer_unref (buf);
9879             }
9880           }
9881           break;
9882         }
9883         case FOURCC_SVQ3:
9884         case FOURCC_VP31:
9885         {
9886           GstBuffer *buf;
9887           GstBuffer *seqh = NULL;
9888           guint8 *gamma_data = NULL;
9889           gint len = QT_UINT32 (stsd_data);
9890
9891           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9892           if (gamma_data) {
9893             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9894                 QT_FP32 (gamma_data), NULL);
9895           }
9896           if (seqh) {
9897             /* sorry for the bad name, but we don't know what this is, other
9898              * than its own fourcc */
9899             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9900                 NULL);
9901           }
9902
9903           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9904           buf = gst_buffer_new_and_alloc (len);
9905           gst_buffer_fill (buf, 0, stsd_data, len);
9906           gst_caps_set_simple (stream->caps,
9907               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9908           gst_buffer_unref (buf);
9909           break;
9910         }
9911         case FOURCC_rle_:
9912         case FOURCC_WRLE:
9913         {
9914           gst_caps_set_simple (stream->caps,
9915               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9916           break;
9917         }
9918         case FOURCC_XiTh:
9919         {
9920           GNode *xith, *xdxt;
9921
9922           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9923           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9924           if (!xith)
9925             break;
9926
9927           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9928           if (!xdxt)
9929             break;
9930
9931           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9932           /* collect the headers and store them in a stream list so that we can
9933            * send them out first */
9934           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9935           break;
9936         }
9937         case FOURCC_ovc1:
9938         {
9939           GNode *ovc1;
9940           guint8 *ovc1_data;
9941           guint ovc1_len;
9942           GstBuffer *buf;
9943
9944           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9945           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9946           if (!ovc1)
9947             break;
9948           ovc1_data = ovc1->data;
9949           ovc1_len = QT_UINT32 (ovc1_data);
9950           if (ovc1_len <= 198) {
9951             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9952             break;
9953           }
9954           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9955           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9956           gst_caps_set_simple (stream->caps,
9957               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9958           gst_buffer_unref (buf);
9959           break;
9960         }
9961         case FOURCC_vc_1:
9962         {
9963           gint len = QT_UINT32 (stsd_data) - 0x66;
9964           const guint8 *vc1_data = stsd_data + 0x66;
9965
9966           /* find dvc1 */
9967           while (len >= 8) {
9968             gint size;
9969
9970             if (QT_UINT32 (vc1_data) <= len)
9971               size = QT_UINT32 (vc1_data) - 8;
9972             else
9973               size = len - 8;
9974
9975             if (size < 1)
9976               /* No real data, so break out */
9977               break;
9978
9979             switch (QT_FOURCC (vc1_data + 0x4)) {
9980               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
9981               {
9982                 GstBuffer *buf;
9983
9984                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
9985                 buf = gst_buffer_new_and_alloc (size);
9986                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
9987                 gst_caps_set_simple (stream->caps,
9988                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9989                 gst_buffer_unref (buf);
9990                 break;
9991               }
9992               default:
9993                 break;
9994             }
9995             len -= size + 8;
9996             vc1_data += size + 8;
9997           }
9998           break;
9999         }
10000         default:
10001           break;
10002       }
10003     }
10004
10005     GST_INFO_OBJECT (qtdemux,
10006         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10007         GST_FOURCC_ARGS (fourcc), stream->caps);
10008
10009   } else if (stream->subtype == FOURCC_soun) {
10010     int version, samplesize;
10011     guint16 compression_id;
10012     gboolean amrwb = FALSE;
10013
10014     offset = 32;
10015     /* sample description entry (16) + sound sample description v0 (20) */
10016     if (len < 36)
10017       goto corrupt_file;
10018
10019     version = QT_UINT32 (stsd_data + offset);
10020     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10021     samplesize = QT_UINT16 (stsd_data + offset + 10);
10022     compression_id = QT_UINT16 (stsd_data + offset + 12);
10023     stream->rate = QT_FP32 (stsd_data + offset + 16);
10024
10025     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10026     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10027         QT_UINT32 (stsd_data + offset + 4));
10028     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10029     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10030     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10031     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10032         QT_UINT16 (stsd_data + offset + 14));
10033     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10034
10035     if (compression_id == 0xfffe)
10036       stream->sampled = TRUE;
10037
10038     /* first assume uncompressed audio */
10039     stream->bytes_per_sample = samplesize / 8;
10040     stream->samples_per_frame = stream->n_channels;
10041     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10042     stream->samples_per_packet = stream->samples_per_frame;
10043     stream->bytes_per_packet = stream->bytes_per_sample;
10044
10045     offset = 52;
10046     switch (fourcc) {
10047         /* Yes, these have to be hard-coded */
10048       case FOURCC_MAC6:
10049       {
10050         stream->samples_per_packet = 6;
10051         stream->bytes_per_packet = 1;
10052         stream->bytes_per_frame = 1 * stream->n_channels;
10053         stream->bytes_per_sample = 1;
10054         stream->samples_per_frame = 6 * stream->n_channels;
10055         break;
10056       }
10057       case FOURCC_MAC3:
10058       {
10059         stream->samples_per_packet = 3;
10060         stream->bytes_per_packet = 1;
10061         stream->bytes_per_frame = 1 * stream->n_channels;
10062         stream->bytes_per_sample = 1;
10063         stream->samples_per_frame = 3 * stream->n_channels;
10064         break;
10065       }
10066       case FOURCC_ima4:
10067       {
10068         stream->samples_per_packet = 64;
10069         stream->bytes_per_packet = 34;
10070         stream->bytes_per_frame = 34 * stream->n_channels;
10071         stream->bytes_per_sample = 2;
10072         stream->samples_per_frame = 64 * stream->n_channels;
10073         break;
10074       }
10075       case FOURCC_ulaw:
10076       case FOURCC_alaw:
10077       {
10078         stream->samples_per_packet = 1;
10079         stream->bytes_per_packet = 1;
10080         stream->bytes_per_frame = 1 * stream->n_channels;
10081         stream->bytes_per_sample = 1;
10082         stream->samples_per_frame = 1 * stream->n_channels;
10083         break;
10084       }
10085       case FOURCC_agsm:
10086       {
10087         stream->samples_per_packet = 160;
10088         stream->bytes_per_packet = 33;
10089         stream->bytes_per_frame = 33 * stream->n_channels;
10090         stream->bytes_per_sample = 2;
10091         stream->samples_per_frame = 160 * stream->n_channels;
10092         break;
10093       }
10094       default:
10095         break;
10096     }
10097
10098     if (version == 0x00010000) {
10099       /* sample description entry (16) + sound sample description v1 (20+16) */
10100       if (len < 52)
10101         goto corrupt_file;
10102
10103       switch (fourcc) {
10104         case FOURCC_twos:
10105         case FOURCC_sowt:
10106         case FOURCC_raw_:
10107           break;
10108         default:
10109         {
10110           /* only parse extra decoding config for non-pcm audio */
10111           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10112           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10113           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10114           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10115
10116           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10117               stream->samples_per_packet);
10118           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10119               stream->bytes_per_packet);
10120           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10121               stream->bytes_per_frame);
10122           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10123               stream->bytes_per_sample);
10124
10125           if (!stream->sampled && stream->bytes_per_packet) {
10126             stream->samples_per_frame = (stream->bytes_per_frame /
10127                 stream->bytes_per_packet) * stream->samples_per_packet;
10128             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10129                 stream->samples_per_frame);
10130           }
10131           break;
10132         }
10133       }
10134     } else if (version == 0x00020000) {
10135       union
10136       {
10137         gdouble fp;
10138         guint64 val;
10139       } qtfp;
10140
10141       /* sample description entry (16) + sound sample description v2 (56) */
10142       if (len < 72)
10143         goto corrupt_file;
10144
10145       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10146       stream->rate = qtfp.fp;
10147       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10148
10149       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10150       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10151       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10152       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10153           QT_UINT32 (stsd_data + offset + 20));
10154       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10155           QT_UINT32 (stsd_data + offset + 24));
10156       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10157           QT_UINT32 (stsd_data + offset + 28));
10158       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10159           QT_UINT32 (stsd_data + offset + 32));
10160     } else if (version != 0x00000) {
10161       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10162     }
10163
10164     if (stream->caps)
10165       gst_caps_unref (stream->caps);
10166
10167     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10168         stsd_data + 32, len - 16, &codec);
10169
10170     switch (fourcc) {
10171       case FOURCC_in24:
10172       {
10173         GNode *enda;
10174         GNode *in24;
10175
10176         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10177
10178         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10179         if (!enda) {
10180           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10181           if (wave)
10182             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10183         }
10184         if (enda) {
10185           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10186           gst_caps_set_simple (stream->caps,
10187               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10188         }
10189         break;
10190       }
10191       case FOURCC_owma:
10192       {
10193         GNode *owma;
10194         const guint8 *owma_data;
10195         const gchar *codec_name = NULL;
10196         guint owma_len;
10197         GstBuffer *buf;
10198         gint version = 1;
10199         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10200         /* FIXME this should also be gst_riff_strf_auds,
10201          * but the latter one is actually missing bits-per-sample :( */
10202         typedef struct
10203         {
10204           gint16 wFormatTag;
10205           gint16 nChannels;
10206           gint32 nSamplesPerSec;
10207           gint32 nAvgBytesPerSec;
10208           gint16 nBlockAlign;
10209           gint16 wBitsPerSample;
10210           gint16 cbSize;
10211         } WAVEFORMATEX;
10212         WAVEFORMATEX *wfex;
10213
10214         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10215         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10216         if (!owma)
10217           break;
10218         owma_data = owma->data;
10219         owma_len = QT_UINT32 (owma_data);
10220         if (owma_len <= 54) {
10221           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10222           break;
10223         }
10224         wfex = (WAVEFORMATEX *) (owma_data + 36);
10225         buf = gst_buffer_new_and_alloc (owma_len - 54);
10226         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10227         if (wfex->wFormatTag == 0x0161) {
10228           codec_name = "Windows Media Audio";
10229           version = 2;
10230         } else if (wfex->wFormatTag == 0x0162) {
10231           codec_name = "Windows Media Audio 9 Pro";
10232           version = 3;
10233         } else if (wfex->wFormatTag == 0x0163) {
10234           codec_name = "Windows Media Audio 9 Lossless";
10235           /* is that correct? gstffmpegcodecmap.c is missing it, but
10236            * fluendo codec seems to support it */
10237           version = 4;
10238         }
10239
10240         gst_caps_set_simple (stream->caps,
10241             "codec_data", GST_TYPE_BUFFER, buf,
10242             "wmaversion", G_TYPE_INT, version,
10243             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10244             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10245             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10246             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10247             NULL);
10248         gst_buffer_unref (buf);
10249
10250         if (codec_name) {
10251           g_free (codec);
10252           codec = g_strdup (codec_name);
10253         }
10254         break;
10255       }
10256       case FOURCC_wma_:
10257       {
10258         gint len = QT_UINT32 (stsd_data) - offset;
10259         const guint8 *wfex_data = stsd_data + offset;
10260         const gchar *codec_name = NULL;
10261         gint version = 1;
10262         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10263         /* FIXME this should also be gst_riff_strf_auds,
10264          * but the latter one is actually missing bits-per-sample :( */
10265         typedef struct
10266         {
10267           gint16 wFormatTag;
10268           gint16 nChannels;
10269           gint32 nSamplesPerSec;
10270           gint32 nAvgBytesPerSec;
10271           gint16 nBlockAlign;
10272           gint16 wBitsPerSample;
10273           gint16 cbSize;
10274         } WAVEFORMATEX;
10275         WAVEFORMATEX wfex;
10276
10277         /* FIXME: unify with similar wavformatex parsing code above */
10278         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10279
10280         /* find wfex */
10281         while (len >= 8) {
10282           gint size;
10283
10284           if (QT_UINT32 (wfex_data) <= len)
10285             size = QT_UINT32 (wfex_data) - 8;
10286           else
10287             size = len - 8;
10288
10289           if (size < 1)
10290             /* No real data, so break out */
10291             break;
10292
10293           switch (QT_FOURCC (wfex_data + 4)) {
10294             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10295             {
10296               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10297
10298               if (size < 8 + 18)
10299                 break;
10300
10301               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10302               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10303               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10304               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10305               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10306               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10307               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10308
10309               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10310               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10311                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10312                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10313                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10314                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10315
10316               if (wfex.wFormatTag == 0x0161) {
10317                 codec_name = "Windows Media Audio";
10318                 version = 2;
10319               } else if (wfex.wFormatTag == 0x0162) {
10320                 codec_name = "Windows Media Audio 9 Pro";
10321                 version = 3;
10322               } else if (wfex.wFormatTag == 0x0163) {
10323                 codec_name = "Windows Media Audio 9 Lossless";
10324                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10325                  * fluendo codec seems to support it */
10326                 version = 4;
10327               }
10328
10329               gst_caps_set_simple (stream->caps,
10330                   "wmaversion", G_TYPE_INT, version,
10331                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10332                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10333                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10334                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10335
10336               if (size > wfex.cbSize) {
10337                 GstBuffer *buf;
10338
10339                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10340                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10341                     size - wfex.cbSize);
10342                 gst_caps_set_simple (stream->caps,
10343                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10344                 gst_buffer_unref (buf);
10345               } else {
10346                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10347               }
10348
10349               if (codec_name) {
10350                 g_free (codec);
10351                 codec = g_strdup (codec_name);
10352               }
10353               break;
10354             }
10355             default:
10356               break;
10357           }
10358           len -= size + 8;
10359           wfex_data += size + 8;
10360         }
10361         break;
10362       }
10363       case FOURCC_opus:
10364       {
10365         GNode *opus;
10366         const guint8 *opus_data;
10367         guint8 *channel_mapping = NULL;
10368         guint32 rate;
10369         guint8 channels;
10370         guint8 channel_mapping_family;
10371         guint8 stream_count;
10372         guint8 coupled_count;
10373         guint8 i;
10374
10375         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10376         opus_data = opus->data;
10377
10378         channels = GST_READ_UINT8 (opus_data + 45);
10379         rate = GST_READ_UINT32_LE (opus_data + 48);
10380         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10381         stream_count = GST_READ_UINT8 (opus_data + 55);
10382         coupled_count = GST_READ_UINT8 (opus_data + 56);
10383
10384         if (channels > 0) {
10385           channel_mapping = g_malloc (channels * sizeof (guint8));
10386           for (i = 0; i < channels; i++)
10387             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10388         }
10389
10390         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10391             channel_mapping_family, stream_count, coupled_count,
10392             channel_mapping);
10393         break;
10394       }
10395       default:
10396         break;
10397     }
10398
10399     if (codec) {
10400       GstStructure *s;
10401       gint bitrate = 0;
10402
10403       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10404           GST_TAG_AUDIO_CODEC, codec, NULL);
10405       g_free (codec);
10406       codec = NULL;
10407
10408       /* some bitrate info may have ended up in caps */
10409       s = gst_caps_get_structure (stream->caps, 0);
10410       gst_structure_get_int (s, "bitrate", &bitrate);
10411       if (bitrate > 0)
10412         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10413             GST_TAG_BITRATE, bitrate, NULL);
10414     }
10415
10416     if (stream->protected && fourcc == FOURCC_mp4a)
10417       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10418     else
10419       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10420
10421     wave = NULL;
10422     esds = NULL;
10423     if (mp4a) {
10424       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10425       if (wave)
10426         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10427       if (!esds)
10428         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10429     }
10430
10431
10432     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10433        16 bits is a byte-swapped wave-style codec identifier,
10434        and we can find a WAVE header internally to a 'wave' atom here.
10435        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10436        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10437        is big-endian).
10438      */
10439     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10440       if (len < offset + 20) {
10441         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10442       } else {
10443         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10444         const guint8 *data = stsd_data + offset + 16;
10445         GNode *wavenode;
10446         GNode *waveheadernode;
10447
10448         wavenode = g_node_new ((guint8 *) data);
10449         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10450           const guint8 *waveheader;
10451           guint32 headerlen;
10452
10453           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10454           if (waveheadernode) {
10455             waveheader = (const guint8 *) waveheadernode->data;
10456             headerlen = QT_UINT32 (waveheader);
10457
10458             if (headerlen > 8) {
10459               gst_riff_strf_auds *header = NULL;
10460               GstBuffer *headerbuf;
10461               GstBuffer *extra;
10462
10463               waveheader += 8;
10464               headerlen -= 8;
10465
10466               headerbuf = gst_buffer_new_and_alloc (headerlen);
10467               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10468
10469               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10470                       headerbuf, &header, &extra)) {
10471                 gst_caps_unref (stream->caps);
10472                 /* FIXME: Need to do something with the channel reorder map */
10473                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10474                     header, extra, NULL, NULL, NULL);
10475
10476                 if (extra)
10477                   gst_buffer_unref (extra);
10478                 g_free (header);
10479               }
10480             }
10481           } else
10482             GST_DEBUG ("Didn't find waveheadernode for this codec");
10483         }
10484         g_node_destroy (wavenode);
10485       }
10486     } else if (esds) {
10487       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10488     } else {
10489       switch (fourcc) {
10490 #if 0
10491           /* FIXME: what is in the chunk? */
10492         case FOURCC_QDMC:
10493         {
10494           gint len = QT_UINT32 (stsd_data);
10495
10496           /* seems to be always = 116 = 0x74 */
10497           break;
10498         }
10499 #endif
10500         case FOURCC_QDM2:
10501         {
10502           gint len = QT_UINT32 (stsd_data);
10503
10504           if (len > 0x4C) {
10505             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10506
10507             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10508             gst_caps_set_simple (stream->caps,
10509                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10510             gst_buffer_unref (buf);
10511           }
10512           gst_caps_set_simple (stream->caps,
10513               "samplesize", G_TYPE_INT, samplesize, NULL);
10514           break;
10515         }
10516         case FOURCC_alac:
10517         {
10518           GNode *alac, *wave = NULL;
10519
10520           /* apparently, m4a has this atom appended directly in the stsd entry,
10521            * while mov has it in a wave atom */
10522           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10523           if (alac) {
10524             /* alac now refers to stsd entry atom */
10525             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10526             if (wave)
10527               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10528             else
10529               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10530           }
10531           if (alac) {
10532             const guint8 *alac_data = alac->data;
10533             gint len = QT_UINT32 (alac->data);
10534             GstBuffer *buf;
10535
10536             if (len < 36) {
10537               GST_DEBUG_OBJECT (qtdemux,
10538                   "discarding alac atom with unexpected len %d", len);
10539             } else {
10540               /* codec-data contains alac atom size and prefix,
10541                * ffmpeg likes it that way, not quite gst-ish though ...*/
10542               buf = gst_buffer_new_and_alloc (len);
10543               gst_buffer_fill (buf, 0, alac->data, len);
10544               gst_caps_set_simple (stream->caps,
10545                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10546               gst_buffer_unref (buf);
10547
10548               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10549               stream->n_channels = QT_UINT8 (alac_data + 21);
10550               stream->rate = QT_UINT32 (alac_data + 32);
10551             }
10552           }
10553           gst_caps_set_simple (stream->caps,
10554               "samplesize", G_TYPE_INT, samplesize, NULL);
10555           break;
10556         }
10557         case FOURCC_sawb:
10558           /* Fallthrough! */
10559           amrwb = TRUE;
10560         case FOURCC_samr:
10561         {
10562           gint len = QT_UINT32 (stsd_data);
10563
10564           if (len > 0x34) {
10565             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10566             guint bitrate;
10567
10568             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10569
10570             /* If we have enough data, let's try to get the 'damr' atom. See
10571              * the 3GPP container spec (26.244) for more details. */
10572             if ((len - 0x34) > 8 &&
10573                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10574               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10575                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10576             }
10577
10578             gst_caps_set_simple (stream->caps,
10579                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10580             gst_buffer_unref (buf);
10581           }
10582           break;
10583         }
10584         case FOURCC_mp4a:
10585         {
10586           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10587           gint len = QT_UINT32 (stsd_data);
10588
10589           if (len >= 50) {
10590             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10591
10592             if (sound_version == 1) {
10593               guint16 channels = QT_UINT16 (stsd_data + 40);
10594               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10595               guint8 codec_data[2];
10596               GstBuffer *buf;
10597               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10598
10599               gint sample_rate_index =
10600                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10601
10602               /* build AAC codec data */
10603               codec_data[0] = profile << 3;
10604               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10605               codec_data[1] = (sample_rate_index & 0x01) << 7;
10606               codec_data[1] |= (channels & 0xF) << 3;
10607
10608               buf = gst_buffer_new_and_alloc (2);
10609               gst_buffer_fill (buf, 0, codec_data, 2);
10610               gst_caps_set_simple (stream->caps,
10611                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10612               gst_buffer_unref (buf);
10613             }
10614           }
10615           break;
10616         }
10617         default:
10618           GST_INFO_OBJECT (qtdemux,
10619               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10620           break;
10621       }
10622     }
10623     GST_INFO_OBJECT (qtdemux,
10624         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10625         GST_FOURCC_ARGS (fourcc), stream->caps);
10626
10627   } else if (stream->subtype == FOURCC_strm) {
10628     if (fourcc == FOURCC_rtsp) {
10629       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10630     } else {
10631       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10632           GST_FOURCC_ARGS (fourcc));
10633       goto unknown_stream;
10634     }
10635     stream->sampled = TRUE;
10636   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10637       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10638
10639     stream->sampled = TRUE;
10640     stream->sparse = TRUE;
10641
10642     stream->caps =
10643         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10644     if (codec) {
10645       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10646           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10647       g_free (codec);
10648       codec = NULL;
10649     }
10650
10651     /* hunt for sort-of codec data */
10652     switch (fourcc) {
10653       case FOURCC_mp4s:
10654       {
10655         GNode *mp4s = NULL;
10656         GNode *esds = NULL;
10657
10658         /* look for palette in a stsd->mp4s->esds sub-atom */
10659         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10660         if (mp4s)
10661           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10662         if (esds == NULL) {
10663           /* Invalid STSD */
10664           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10665           break;
10666         }
10667
10668         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10669         break;
10670       }
10671       default:
10672         GST_INFO_OBJECT (qtdemux,
10673             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10674         break;
10675     }
10676     GST_INFO_OBJECT (qtdemux,
10677         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10678         GST_FOURCC_ARGS (fourcc), stream->caps);
10679   } else {
10680     /* everything in 1 sample */
10681     stream->sampled = TRUE;
10682
10683     stream->caps =
10684         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10685
10686     if (stream->caps == NULL)
10687       goto unknown_stream;
10688
10689     if (codec) {
10690       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10691           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10692       g_free (codec);
10693       codec = NULL;
10694     }
10695   }
10696
10697   /* promote to sampled format */
10698   if (stream->fourcc == FOURCC_samr) {
10699     /* force mono 8000 Hz for AMR */
10700     stream->sampled = TRUE;
10701     stream->n_channels = 1;
10702     stream->rate = 8000;
10703   } else if (stream->fourcc == FOURCC_sawb) {
10704     /* force mono 16000 Hz for AMR-WB */
10705     stream->sampled = TRUE;
10706     stream->n_channels = 1;
10707     stream->rate = 16000;
10708   } else if (stream->fourcc == FOURCC_mp4a) {
10709     stream->sampled = TRUE;
10710   }
10711
10712   /* collect sample information */
10713   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10714     goto samples_failed;
10715
10716   if (qtdemux->fragmented) {
10717     guint64 offset;
10718
10719     /* need all moov samples as basis; probably not many if any at all */
10720     /* prevent moof parsing taking of at this time */
10721     offset = qtdemux->moof_offset;
10722     qtdemux->moof_offset = 0;
10723     if (stream->n_samples &&
10724         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10725       qtdemux->moof_offset = offset;
10726       goto samples_failed;
10727     }
10728     qtdemux->moof_offset = 0;
10729     /* movie duration more reliable in this case (e.g. mehd) */
10730     if (qtdemux->segment.duration &&
10731         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10732       stream->duration =
10733           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10734   }
10735
10736   /* configure segments */
10737   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10738     goto segments_failed;
10739
10740   /* add some language tag, if useful */
10741   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10742       strcmp (stream->lang_id, "und")) {
10743     const gchar *lang_code;
10744
10745     /* convert ISO 639-2 code to ISO 639-1 */
10746     lang_code = gst_tag_get_language_code (stream->lang_id);
10747     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10748         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10749   }
10750
10751   /* Check for UDTA tags */
10752   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10753     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10754   }
10755
10756   /* now we are ready to add the stream */
10757   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10758     goto too_many_streams;
10759
10760   if (!qtdemux->got_moov) {
10761     qtdemux->streams[qtdemux->n_streams] = stream;
10762     qtdemux->n_streams++;
10763     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10764   }
10765
10766   return TRUE;
10767
10768 /* ERRORS */
10769 skip_track:
10770   {
10771     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10772     if (new_stream)
10773       gst_qtdemux_stream_free (qtdemux, stream);
10774     return TRUE;
10775   }
10776 corrupt_file:
10777   {
10778     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10779         (_("This file is corrupt and cannot be played.")), (NULL));
10780     if (new_stream)
10781       gst_qtdemux_stream_free (qtdemux, stream);
10782     return FALSE;
10783   }
10784 error_encrypted:
10785   {
10786     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10787     if (new_stream)
10788       gst_qtdemux_stream_free (qtdemux, stream);
10789     return FALSE;
10790   }
10791 samples_failed:
10792 segments_failed:
10793   {
10794     /* we posted an error already */
10795     /* free stbl sub-atoms */
10796     gst_qtdemux_stbl_free (stream);
10797     if (new_stream)
10798       gst_qtdemux_stream_free (qtdemux, stream);
10799     return FALSE;
10800   }
10801 existing_stream:
10802   {
10803     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10804         track_id);
10805     if (new_stream)
10806       gst_qtdemux_stream_free (qtdemux, stream);
10807     return TRUE;
10808   }
10809 unknown_stream:
10810   {
10811     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10812         GST_FOURCC_ARGS (stream->subtype));
10813     if (new_stream)
10814       gst_qtdemux_stream_free (qtdemux, stream);
10815     return TRUE;
10816   }
10817 too_many_streams:
10818   {
10819     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10820         (_("This file contains too many streams. Only playing first %d"),
10821             GST_QTDEMUX_MAX_STREAMS), (NULL));
10822     return TRUE;
10823   }
10824 }
10825
10826 /* If we can estimate the overall bitrate, and don't have information about the
10827  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10828  * the overall bitrate minus the sum of the bitrates of all other streams. This
10829  * should be useful for the common case where we have one audio and one video
10830  * stream and can estimate the bitrate of one, but not the other. */
10831 static void
10832 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10833 {
10834   QtDemuxStream *stream = NULL;
10835   gint64 size, sys_bitrate, sum_bitrate = 0;
10836   GstClockTime duration;
10837   gint i;
10838   guint bitrate;
10839
10840   if (qtdemux->fragmented)
10841     return;
10842
10843   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10844
10845   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10846       || size <= 0) {
10847     GST_DEBUG_OBJECT (qtdemux,
10848         "Size in bytes of the stream not known - bailing");
10849     return;
10850   }
10851
10852   /* Subtract the header size */
10853   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10854       size, qtdemux->header_size);
10855
10856   if (size < qtdemux->header_size)
10857     return;
10858
10859   size = size - qtdemux->header_size;
10860
10861   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
10862     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10863     return;
10864   }
10865
10866   for (i = 0; i < qtdemux->n_streams; i++) {
10867     switch (qtdemux->streams[i]->subtype) {
10868       case FOURCC_soun:
10869       case FOURCC_vide:
10870         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10871             qtdemux->streams[i]->caps);
10872         /* retrieve bitrate, prefer avg then max */
10873         bitrate = 0;
10874         if (qtdemux->streams[i]->pending_tags) {
10875           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10876               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10877           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10878           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10879               GST_TAG_NOMINAL_BITRATE, &bitrate);
10880           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10881           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10882               GST_TAG_BITRATE, &bitrate);
10883           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10884         }
10885         if (bitrate)
10886           sum_bitrate += bitrate;
10887         else {
10888           if (stream) {
10889             GST_DEBUG_OBJECT (qtdemux,
10890                 ">1 stream with unknown bitrate - bailing");
10891             return;
10892           } else
10893             stream = qtdemux->streams[i];
10894         }
10895
10896       default:
10897         /* For other subtypes, we assume no significant impact on bitrate */
10898         break;
10899     }
10900   }
10901
10902   if (!stream) {
10903     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10904     return;
10905   }
10906
10907   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10908
10909   if (sys_bitrate < sum_bitrate) {
10910     /* This can happen, since sum_bitrate might be derived from maximum
10911      * bitrates and not average bitrates */
10912     GST_DEBUG_OBJECT (qtdemux,
10913         "System bitrate less than sum bitrate - bailing");
10914     return;
10915   }
10916
10917   bitrate = sys_bitrate - sum_bitrate;
10918   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10919       ", Stream bitrate = %u", sys_bitrate, bitrate);
10920
10921   if (!stream->pending_tags)
10922     stream->pending_tags = gst_tag_list_new_empty ();
10923
10924   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10925       GST_TAG_BITRATE, bitrate, NULL);
10926 }
10927
10928 static GstFlowReturn
10929 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10930 {
10931   gint i;
10932   GstFlowReturn ret = GST_FLOW_OK;
10933
10934   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10935
10936   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10937     QtDemuxStream *stream = qtdemux->streams[i];
10938     guint32 sample_num = 0;
10939
10940     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10941         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10942
10943     if (qtdemux->fragmented) {
10944       /* need all moov samples first */
10945       GST_OBJECT_LOCK (qtdemux);
10946       while (stream->n_samples == 0)
10947         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10948           break;
10949       GST_OBJECT_UNLOCK (qtdemux);
10950     } else {
10951       /* discard any stray moof */
10952       qtdemux->moof_offset = 0;
10953     }
10954
10955     /* prepare braking */
10956     if (ret != GST_FLOW_ERROR)
10957       ret = GST_FLOW_OK;
10958
10959     /* in pull mode, we should have parsed some sample info by now;
10960      * and quite some code will not handle no samples.
10961      * in push mode, we'll just have to deal with it */
10962     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10963       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10964       gst_qtdemux_remove_stream (qtdemux, i);
10965       i--;
10966       continue;
10967     }
10968
10969     /* parse the initial sample for use in setting the frame rate cap */
10970     while (sample_num == 0 && sample_num < stream->n_samples) {
10971       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10972         break;
10973       ++sample_num;
10974     }
10975     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
10976       stream->first_duration = stream->samples[0].duration;
10977       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
10978           stream->track_id, stream->first_duration);
10979     }
10980   }
10981
10982   return ret;
10983 }
10984
10985 static GstFlowReturn
10986 qtdemux_expose_streams (GstQTDemux * qtdemux)
10987 {
10988   gint i;
10989   GstFlowReturn ret = GST_FLOW_OK;
10990   GSList *oldpads = NULL;
10991   GSList *iter;
10992
10993   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
10994
10995   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10996     QtDemuxStream *stream = qtdemux->streams[i];
10997     GstPad *oldpad = stream->pad;
10998     GstTagList *list;
10999
11000     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11001         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11002
11003     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11004         stream->track_id == qtdemux->chapters_track_id) {
11005       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11006          so that it doesn't look like a subtitle track */
11007       gst_qtdemux_remove_stream (qtdemux, i);
11008       i--;
11009       continue;
11010     }
11011
11012     /* now we have all info and can expose */
11013     list = stream->pending_tags;
11014     stream->pending_tags = NULL;
11015     if (oldpad)
11016       oldpads = g_slist_prepend (oldpads, oldpad);
11017     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11018       return GST_FLOW_ERROR;
11019   }
11020
11021   gst_qtdemux_guess_bitrate (qtdemux);
11022
11023   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11024
11025   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11026     GstPad *oldpad = iter->data;
11027     GstEvent *event;
11028
11029     event = gst_event_new_eos ();
11030     if (qtdemux->segment_seqnum)
11031       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11032
11033     gst_pad_push_event (oldpad, event);
11034     gst_pad_set_active (oldpad, FALSE);
11035     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11036     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11037     gst_object_unref (oldpad);
11038   }
11039
11040   /* check if we should post a redirect in case there is a single trak
11041    * and it is a redirecting trak */
11042   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11043     GstMessage *m;
11044
11045     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11046         "an external content");
11047     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11048         gst_structure_new ("redirect",
11049             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11050             NULL));
11051     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11052     qtdemux->posted_redirect = TRUE;
11053   }
11054
11055   for (i = 0; i < qtdemux->n_streams; i++) {
11056     QtDemuxStream *stream = qtdemux->streams[i];
11057
11058     qtdemux_do_allocation (qtdemux, stream);
11059   }
11060
11061   qtdemux->exposed = TRUE;
11062   return ret;
11063 }
11064
11065 /* check if major or compatible brand is 3GP */
11066 static inline gboolean
11067 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11068 {
11069   if (major) {
11070     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11071         FOURCC_3g__);
11072   } else if (qtdemux->comp_brands != NULL) {
11073     GstMapInfo map;
11074     guint8 *data;
11075     gsize size;
11076     gboolean res = FALSE;
11077
11078     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11079     data = map.data;
11080     size = map.size;
11081     while (size >= 4) {
11082       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11083           FOURCC_3g__);
11084       data += 4;
11085       size -= 4;
11086     }
11087     gst_buffer_unmap (qtdemux->comp_brands, &map);
11088     return res;
11089   } else {
11090     return FALSE;
11091   }
11092 }
11093
11094 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11095 static inline gboolean
11096 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11097 {
11098   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11099       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11100       || fourcc == FOURCC_albm;
11101 }
11102
11103 static void
11104 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11105     const char *tag, const char *dummy, GNode * node)
11106 {
11107   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11108   int offset;
11109   char *name;
11110   gchar *data;
11111   gdouble longitude, latitude, altitude;
11112   gint len;
11113
11114   len = QT_UINT32 (node->data);
11115   if (len <= 14)
11116     goto short_read;
11117
11118   data = node->data;
11119   offset = 14;
11120
11121   /* TODO: language code skipped */
11122
11123   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11124
11125   if (!name) {
11126     /* do not alarm in trivial case, but bail out otherwise */
11127     if (*(data + offset) != 0) {
11128       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11129           "giving up", tag);
11130     }
11131   } else {
11132     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11133         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11134     offset += strlen (name);
11135     g_free (name);
11136   }
11137
11138   if (len < offset + 2 + 4 + 4 + 4)
11139     goto short_read;
11140
11141   /* +1 +1 = skip null-terminator and location role byte */
11142   offset += 1 + 1;
11143   /* table in spec says unsigned, semantics say negative has meaning ... */
11144   longitude = QT_SFP32 (data + offset);
11145
11146   offset += 4;
11147   latitude = QT_SFP32 (data + offset);
11148
11149   offset += 4;
11150   altitude = QT_SFP32 (data + offset);
11151
11152   /* one invalid means all are invalid */
11153   if (longitude >= -180.0 && longitude <= 180.0 &&
11154       latitude >= -90.0 && latitude <= 90.0) {
11155     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11156         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11157         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11158         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11159   }
11160
11161   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11162
11163   return;
11164
11165   /* ERRORS */
11166 short_read:
11167   {
11168     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11169     return;
11170   }
11171 }
11172
11173
11174 static void
11175 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11176     const char *tag, const char *dummy, GNode * node)
11177 {
11178   guint16 y;
11179   GDate *date;
11180   gint len;
11181
11182   len = QT_UINT32 (node->data);
11183   if (len < 14)
11184     return;
11185
11186   y = QT_UINT16 ((guint8 *) node->data + 12);
11187   if (y == 0) {
11188     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11189     return;
11190   }
11191   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11192
11193   date = g_date_new_dmy (1, 1, y);
11194   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11195   g_date_free (date);
11196 }
11197
11198 static void
11199 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11200     const char *tag, const char *dummy, GNode * node)
11201 {
11202   int offset;
11203   char *tag_str = NULL;
11204   guint8 *entity;
11205   guint16 table;
11206   gint len;
11207
11208   len = QT_UINT32 (node->data);
11209   if (len <= 20)
11210     goto short_read;
11211
11212   offset = 12;
11213   entity = (guint8 *) node->data + offset;
11214   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11215     GST_DEBUG_OBJECT (qtdemux,
11216         "classification info: %c%c%c%c invalid classification entity",
11217         entity[0], entity[1], entity[2], entity[3]);
11218     return;
11219   }
11220
11221   offset += 4;
11222   table = QT_UINT16 ((guint8 *) node->data + offset);
11223
11224   /* Language code skipped */
11225
11226   offset += 4;
11227
11228   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11229    * XXXX: classification entity, fixed length 4 chars.
11230    * Y[YYYY]: classification table, max 5 chars.
11231    */
11232   tag_str = g_strdup_printf ("----://%u/%s",
11233       table, (char *) node->data + offset);
11234
11235   /* memcpy To be sure we're preserving byte order */
11236   memcpy (tag_str, entity, 4);
11237   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11238
11239   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11240
11241   g_free (tag_str);
11242
11243   return;
11244
11245   /* ERRORS */
11246 short_read:
11247   {
11248     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11249     return;
11250   }
11251 }
11252
11253 static gboolean
11254 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11255     const char *tag, const char *dummy, GNode * node)
11256 {
11257   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11258   GNode *data;
11259   char *s;
11260   int len;
11261   guint32 type;
11262   int offset;
11263   gboolean ret = TRUE;
11264   const gchar *charset = NULL;
11265
11266   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11267   if (data) {
11268     len = QT_UINT32 (data->data);
11269     type = QT_UINT32 ((guint8 *) data->data + 8);
11270     if (type == 0x00000001 && len > 16) {
11271       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11272           env_vars);
11273       if (s) {
11274         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11275         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11276         g_free (s);
11277       } else {
11278         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11279       }
11280     }
11281   } else {
11282     len = QT_UINT32 (node->data);
11283     type = QT_UINT32 ((guint8 *) node->data + 4);
11284     if ((type >> 24) == 0xa9) {
11285       gint str_len;
11286       gint lang_code;
11287
11288       /* Type starts with the (C) symbol, so the next data is a list
11289        * of (string size(16), language code(16), string) */
11290
11291       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11292       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11293
11294       /* the string + fourcc + size + 2 16bit fields,
11295        * means that there are more tags in this atom */
11296       if (len > str_len + 8 + 4) {
11297         /* TODO how to represent the same tag in different languages? */
11298         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11299             "text alternatives, reading only first one");
11300       }
11301
11302       offset = 12;
11303       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
11304       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11305
11306       if (lang_code < 0x800) {  /* MAC encoded string */
11307         charset = "mac";
11308       }
11309     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11310             QT_FOURCC ((guint8 *) node->data + 4))) {
11311       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11312
11313       /* we go for 3GP style encoding if major brands claims so,
11314        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11315       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11316           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11317               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11318         offset = 14;
11319         /* 16-bit Language code is ignored here as well */
11320         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11321       } else {
11322         goto normal;
11323       }
11324     } else {
11325     normal:
11326       offset = 8;
11327       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11328       ret = FALSE;              /* may have to fallback */
11329     }
11330     if (charset) {
11331       GError *err = NULL;
11332
11333       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11334           charset, NULL, NULL, &err);
11335       if (err) {
11336         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11337             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11338             err->message);
11339         g_error_free (err);
11340       }
11341     } else {
11342       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11343           len - offset, env_vars);
11344     }
11345     if (s) {
11346       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11347       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11348       g_free (s);
11349       ret = TRUE;
11350     } else {
11351       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11352     }
11353   }
11354   return ret;
11355 }
11356
11357 static void
11358 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11359     const char *tag, const char *dummy, GNode * node)
11360 {
11361   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11362 }
11363
11364 static void
11365 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11366     const char *tag, const char *dummy, GNode * node)
11367 {
11368   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11369   guint8 *data;
11370   char *s, *t, *k = NULL;
11371   int len;
11372   int offset;
11373   int count;
11374
11375   /* first try normal string tag if major brand not 3GP */
11376   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11377     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11378       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11379        * let's try it 3gpp way after minor safety check */
11380       data = node->data;
11381       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11382         return;
11383     } else
11384       return;
11385   }
11386
11387   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11388
11389   data = node->data;
11390
11391   len = QT_UINT32 (data);
11392   if (len < 15)
11393     goto short_read;
11394
11395   count = QT_UINT8 (data + 14);
11396   offset = 15;
11397   for (; count; count--) {
11398     gint slen;
11399
11400     if (offset + 1 > len)
11401       goto short_read;
11402     slen = QT_UINT8 (data + offset);
11403     offset += 1;
11404     if (offset + slen > len)
11405       goto short_read;
11406     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11407         slen, env_vars);
11408     if (s) {
11409       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11410       if (k) {
11411         t = g_strjoin (",", k, s, NULL);
11412         g_free (s);
11413         g_free (k);
11414         k = t;
11415       } else {
11416         k = s;
11417       }
11418     } else {
11419       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11420     }
11421     offset += slen;
11422   }
11423
11424 done:
11425   if (k) {
11426     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11427     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11428   }
11429   g_free (k);
11430
11431   return;
11432
11433   /* ERRORS */
11434 short_read:
11435   {
11436     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11437     goto done;
11438   }
11439 }
11440
11441 static void
11442 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11443     const char *tag1, const char *tag2, GNode * node)
11444 {
11445   GNode *data;
11446   int len;
11447   int type;
11448   int n1, n2;
11449
11450   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11451   if (data) {
11452     len = QT_UINT32 (data->data);
11453     type = QT_UINT32 ((guint8 *) data->data + 8);
11454     if (type == 0x00000000 && len >= 22) {
11455       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11456       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11457       if (n1 > 0) {
11458         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11459         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11460       }
11461       if (n2 > 0) {
11462         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11463         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11464       }
11465     }
11466   }
11467 }
11468
11469 static void
11470 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11471     const char *tag1, const char *dummy, GNode * node)
11472 {
11473   GNode *data;
11474   int len;
11475   int type;
11476   int n1;
11477
11478   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11479   if (data) {
11480     len = QT_UINT32 (data->data);
11481     type = QT_UINT32 ((guint8 *) data->data + 8);
11482     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11483     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11484     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11485       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11486       if (n1) {
11487         /* do not add bpm=0 */
11488         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11489         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11490             NULL);
11491       }
11492     }
11493   }
11494 }
11495
11496 static void
11497 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11498     const char *tag1, const char *dummy, GNode * node)
11499 {
11500   GNode *data;
11501   int len;
11502   int type;
11503   guint32 num;
11504
11505   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11506   if (data) {
11507     len = QT_UINT32 (data->data);
11508     type = QT_UINT32 ((guint8 *) data->data + 8);
11509     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11510     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11511     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11512       num = QT_UINT32 ((guint8 *) data->data + 16);
11513       if (num) {
11514         /* do not add num=0 */
11515         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11516         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11517       }
11518     }
11519   }
11520 }
11521
11522 static void
11523 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11524     const char *tag1, const char *dummy, GNode * node)
11525 {
11526   GNode *data;
11527   int len;
11528   int type;
11529   GstSample *sample;
11530
11531   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11532   if (data) {
11533     len = QT_UINT32 (data->data);
11534     type = QT_UINT32 ((guint8 *) data->data + 8);
11535     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11536     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11537       if ((sample =
11538               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11539                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11540         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11541         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11542         gst_sample_unref (sample);
11543       }
11544     }
11545   }
11546 }
11547
11548 static void
11549 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11550     const char *tag, const char *dummy, GNode * node)
11551 {
11552   GNode *data;
11553   char *s;
11554   int len;
11555   int type;
11556
11557   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11558   if (data) {
11559     len = QT_UINT32 (data->data);
11560     type = QT_UINT32 ((guint8 *) data->data + 8);
11561     if (type == 0x00000001 && len > 16) {
11562       guint y, m = 1, d = 1;
11563       gint ret;
11564
11565       s = g_strndup ((char *) data->data + 16, len - 16);
11566       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11567       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11568       if (ret >= 1 && y > 1500 && y < 3000) {
11569         GDate *date;
11570
11571         date = g_date_new_dmy (d, m, y);
11572         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11573         g_date_free (date);
11574       } else {
11575         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11576       }
11577       g_free (s);
11578     }
11579   }
11580 }
11581
11582 static void
11583 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11584     const char *tag, const char *dummy, GNode * node)
11585 {
11586   GNode *data;
11587
11588   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11589
11590   /* re-route to normal string tag if major brand says so
11591    * or no data atom and compatible brand suggests so */
11592   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11593       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11594     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11595     return;
11596   }
11597
11598   if (data) {
11599     guint len, type, n;
11600
11601     len = QT_UINT32 (data->data);
11602     type = QT_UINT32 ((guint8 *) data->data + 8);
11603     if (type == 0x00000000 && len >= 18) {
11604       n = QT_UINT16 ((guint8 *) data->data + 16);
11605       if (n > 0) {
11606         const gchar *genre;
11607
11608         genre = gst_tag_id3_genre_get (n - 1);
11609         if (genre != NULL) {
11610           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11611           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11612         }
11613       }
11614     }
11615   }
11616 }
11617
11618 static void
11619 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11620     const gchar * tag, guint8 * data, guint32 datasize)
11621 {
11622   gdouble value;
11623   gchar *datacopy;
11624
11625   /* make a copy to have \0 at the end */
11626   datacopy = g_strndup ((gchar *) data, datasize);
11627
11628   /* convert the str to double */
11629   if (sscanf (datacopy, "%lf", &value) == 1) {
11630     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11631     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11632   } else {
11633     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11634         datacopy);
11635   }
11636   g_free (datacopy);
11637 }
11638
11639
11640 static void
11641 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11642     const char *tag, const char *tag_bis, GNode * node)
11643 {
11644   GNode *mean;
11645   GNode *name;
11646   GNode *data;
11647   guint32 meansize;
11648   guint32 namesize;
11649   guint32 datatype;
11650   guint32 datasize;
11651   const gchar *meanstr;
11652   const gchar *namestr;
11653
11654   /* checking the whole ---- atom size for consistency */
11655   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11656     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11657     return;
11658   }
11659
11660   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11661   if (!mean) {
11662     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11663     return;
11664   }
11665
11666   meansize = QT_UINT32 (mean->data);
11667   if (meansize <= 12) {
11668     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11669     return;
11670   }
11671   meanstr = ((gchar *) mean->data) + 12;
11672   meansize -= 12;
11673
11674   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11675   if (!name) {
11676     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11677     return;
11678   }
11679
11680   namesize = QT_UINT32 (name->data);
11681   if (namesize <= 12) {
11682     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11683     return;
11684   }
11685   namestr = ((gchar *) name->data) + 12;
11686   namesize -= 12;
11687
11688   /*
11689    * Data atom is:
11690    * uint32 - size
11691    * uint32 - name
11692    * uint8  - version
11693    * uint24 - data type
11694    * uint32 - all 0
11695    * rest   - the data
11696    */
11697   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11698   if (!data) {
11699     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11700     return;
11701   }
11702   datasize = QT_UINT32 (data->data);
11703   if (datasize <= 16) {
11704     GST_WARNING_OBJECT (demux, "Data atom too small");
11705     return;
11706   }
11707   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11708
11709   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11710       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11711     static const struct
11712     {
11713       const gchar name[28];
11714       const gchar tag[28];
11715     } tags[] = {
11716       {
11717       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11718       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11719       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11720       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11721       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11722       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11723       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11724       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11725     };
11726     int i;
11727
11728     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11729       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11730         switch (gst_tag_get_type (tags[i].tag)) {
11731           case G_TYPE_DOUBLE:
11732             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11733                 ((guint8 *) data->data) + 16, datasize - 16);
11734             break;
11735           case G_TYPE_STRING:
11736             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11737             break;
11738           default:
11739             /* not reached */
11740             break;
11741         }
11742         break;
11743       }
11744     }
11745     if (i == G_N_ELEMENTS (tags))
11746       goto unknown_tag;
11747   } else {
11748     goto unknown_tag;
11749   }
11750
11751   return;
11752
11753 /* errors */
11754 unknown_tag:
11755 #ifndef GST_DISABLE_GST_DEBUG
11756   {
11757     gchar *namestr_dbg;
11758     gchar *meanstr_dbg;
11759
11760     meanstr_dbg = g_strndup (meanstr, meansize);
11761     namestr_dbg = g_strndup (namestr, namesize);
11762
11763     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11764         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11765
11766     g_free (namestr_dbg);
11767     g_free (meanstr_dbg);
11768   }
11769 #endif
11770   return;
11771 }
11772
11773 static void
11774 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11775     const char *tag_bis, GNode * node)
11776 {
11777   guint8 *data;
11778   GstBuffer *buf;
11779   guint len;
11780   GstTagList *id32_taglist = NULL;
11781
11782   GST_LOG_OBJECT (demux, "parsing ID32");
11783
11784   data = node->data;
11785   len = GST_READ_UINT32_BE (data);
11786
11787   /* need at least full box and language tag */
11788   if (len < 12 + 2)
11789     return;
11790
11791   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11792   gst_buffer_fill (buf, 0, data + 14, len - 14);
11793
11794   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11795   if (id32_taglist) {
11796     GST_LOG_OBJECT (demux, "parsing ok");
11797     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11798     gst_tag_list_unref (id32_taglist);
11799   } else {
11800     GST_LOG_OBJECT (demux, "parsing failed");
11801   }
11802
11803   gst_buffer_unref (buf);
11804 }
11805
11806 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11807     const char *tag, const char *tag_bis, GNode * node);
11808
11809 /* unmapped tags
11810 FOURCC_pcst -> if media is a podcast -> bool
11811 FOURCC_cpil -> if media is part of a compilation -> bool
11812 FOURCC_pgap -> if media is part of a gapless context -> bool
11813 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11814 */
11815
11816 static const struct
11817 {
11818   guint32 fourcc;
11819   const gchar *gst_tag;
11820   const gchar *gst_tag_bis;
11821   const GstQTDemuxAddTagFunc func;
11822 } add_funcs[] = {
11823   {
11824   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11825   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11826   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11827   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11828   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11829   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11830   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11831   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11832   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11833   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11834   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11835   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11836   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11837   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11838   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11839   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11840   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11841   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11842   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11843   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11844   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11845   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11846   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11847         qtdemux_tag_add_num}, {
11848   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11849         qtdemux_tag_add_num}, {
11850   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11851   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11852   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11853   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11854   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11855   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11856   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11857   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11858   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11859   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11860   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11861   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11862   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11863   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11864   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11865   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11866   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11867   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11868         qtdemux_tag_add_classification}, {
11869   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11870   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11871   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11872
11873     /* This is a special case, some tags are stored in this
11874      * 'reverse dns naming', according to:
11875      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11876      * bug #614471
11877      */
11878   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11879     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11880   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11881 };
11882
11883 struct _GstQtDemuxTagList
11884 {
11885   GstQTDemux *demux;
11886   GstTagList *taglist;
11887 };
11888 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11889
11890 static void
11891 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11892 {
11893   gint len;
11894   guint8 *data;
11895   GstBuffer *buf;
11896   gchar *media_type;
11897   const gchar *style;
11898   GstSample *sample;
11899   GstStructure *s;
11900   guint i;
11901   guint8 ndata[4];
11902   GstQTDemux *demux = qtdemuxtaglist->demux;
11903   GstTagList *taglist = qtdemuxtaglist->taglist;
11904
11905   data = node->data;
11906   len = QT_UINT32 (data);
11907   buf = gst_buffer_new_and_alloc (len);
11908   gst_buffer_fill (buf, 0, data, len);
11909
11910   /* heuristic to determine style of tag */
11911   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11912       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11913     style = "itunes";
11914   else if (demux->major_brand == FOURCC_qt__)
11915     style = "quicktime";
11916   /* fall back to assuming iso/3gp tag style */
11917   else
11918     style = "iso";
11919
11920   /* santize the name for the caps. */
11921   for (i = 0; i < 4; i++) {
11922     guint8 d = data[4 + i];
11923     if (g_ascii_isalnum (d))
11924       ndata[i] = g_ascii_tolower (d);
11925     else
11926       ndata[i] = '_';
11927   }
11928
11929   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11930       ndata[0], ndata[1], ndata[2], ndata[3]);
11931   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11932
11933   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11934   sample = gst_sample_new (buf, NULL, NULL, s);
11935   gst_buffer_unref (buf);
11936   g_free (media_type);
11937
11938   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11939       len, s);
11940
11941   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11942       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11943
11944   gst_sample_unref (sample);
11945 }
11946
11947 static void
11948 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11949 {
11950   GNode *meta;
11951   GNode *ilst;
11952   GNode *xmp_;
11953   GNode *node;
11954   gint i;
11955   GstQtDemuxTagList demuxtaglist;
11956
11957   demuxtaglist.demux = qtdemux;
11958   demuxtaglist.taglist = taglist;
11959
11960   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11961   if (meta != NULL) {
11962     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11963     if (ilst == NULL) {
11964       GST_LOG_OBJECT (qtdemux, "no ilst");
11965       return;
11966     }
11967   } else {
11968     ilst = udta;
11969     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11970   }
11971
11972   i = 0;
11973   while (i < G_N_ELEMENTS (add_funcs)) {
11974     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
11975     if (node) {
11976       gint len;
11977
11978       len = QT_UINT32 (node->data);
11979       if (len < 12) {
11980         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
11981             GST_FOURCC_ARGS (add_funcs[i].fourcc));
11982       } else {
11983         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
11984             add_funcs[i].gst_tag_bis, node);
11985       }
11986       g_node_destroy (node);
11987     } else {
11988       i++;
11989     }
11990   }
11991
11992   /* parsed nodes have been removed, pass along remainder as blob */
11993   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
11994       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
11995
11996   /* parse up XMP_ node if existing */
11997   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
11998   if (xmp_ != NULL) {
11999     GstBuffer *buf;
12000     GstTagList *xmptaglist;
12001
12002     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12003         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12004     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12005     gst_buffer_unref (buf);
12006
12007     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12008   } else {
12009     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12010   }
12011 }
12012
12013 typedef struct
12014 {
12015   GstStructure *structure;      /* helper for sort function */
12016   gchar *location;
12017   guint min_req_bitrate;
12018   guint min_req_qt_version;
12019 } GstQtReference;
12020
12021 static gint
12022 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12023 {
12024   GstQtReference *ref_a = (GstQtReference *) a;
12025   GstQtReference *ref_b = (GstQtReference *) b;
12026
12027   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12028     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12029
12030   /* known bitrates go before unknown; higher bitrates go first */
12031   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12032 }
12033
12034 /* sort the redirects and post a message for the application.
12035  */
12036 static void
12037 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12038 {
12039   GstQtReference *best;
12040   GstStructure *s;
12041   GstMessage *msg;
12042   GValue list_val = { 0, };
12043   GList *l;
12044
12045   g_assert (references != NULL);
12046
12047   references = g_list_sort (references, qtdemux_redirects_sort_func);
12048
12049   best = (GstQtReference *) references->data;
12050
12051   g_value_init (&list_val, GST_TYPE_LIST);
12052
12053   for (l = references; l != NULL; l = l->next) {
12054     GstQtReference *ref = (GstQtReference *) l->data;
12055     GValue struct_val = { 0, };
12056
12057     ref->structure = gst_structure_new ("redirect",
12058         "new-location", G_TYPE_STRING, ref->location, NULL);
12059
12060     if (ref->min_req_bitrate > 0) {
12061       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12062           ref->min_req_bitrate, NULL);
12063     }
12064
12065     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12066     g_value_set_boxed (&struct_val, ref->structure);
12067     gst_value_list_append_value (&list_val, &struct_val);
12068     g_value_unset (&struct_val);
12069     /* don't free anything here yet, since we need best->structure below */
12070   }
12071
12072   g_assert (best != NULL);
12073   s = gst_structure_copy (best->structure);
12074
12075   if (g_list_length (references) > 1) {
12076     gst_structure_set_value (s, "locations", &list_val);
12077   }
12078
12079   g_value_unset (&list_val);
12080
12081   for (l = references; l != NULL; l = l->next) {
12082     GstQtReference *ref = (GstQtReference *) l->data;
12083
12084     gst_structure_free (ref->structure);
12085     g_free (ref->location);
12086     g_free (ref);
12087   }
12088   g_list_free (references);
12089
12090   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12091   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12092   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12093   qtdemux->posted_redirect = TRUE;
12094 }
12095
12096 /* look for redirect nodes, collect all redirect information and
12097  * process it.
12098  */
12099 static gboolean
12100 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12101 {
12102   GNode *rmra, *rmda, *rdrf;
12103
12104   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12105   if (rmra) {
12106     GList *redirects = NULL;
12107
12108     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12109     while (rmda) {
12110       GstQtReference ref = { NULL, NULL, 0, 0 };
12111       GNode *rmdr, *rmvc;
12112
12113       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12114         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12115         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12116             ref.min_req_bitrate);
12117       }
12118
12119       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12120         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12121         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12122
12123 #ifndef GST_DISABLE_GST_DEBUG
12124         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12125 #endif
12126         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12127
12128         GST_LOG_OBJECT (qtdemux,
12129             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12130             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12131             bitmask, check_type);
12132         if (package == FOURCC_qtim && check_type == 0) {
12133           ref.min_req_qt_version = version;
12134         }
12135       }
12136
12137       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12138       if (rdrf) {
12139         guint32 ref_type;
12140         guint8 *ref_data;
12141         guint ref_len;
12142
12143         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12144         if (ref_len > 20) {
12145           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12146           ref_data = (guint8 *) rdrf->data + 20;
12147           if (ref_type == FOURCC_alis) {
12148             guint record_len, record_version, fn_len;
12149
12150             if (ref_len > 70) {
12151               /* MacOSX alias record, google for alias-layout.txt */
12152               record_len = QT_UINT16 (ref_data + 4);
12153               record_version = QT_UINT16 (ref_data + 4 + 2);
12154               fn_len = QT_UINT8 (ref_data + 50);
12155               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12156                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12157               }
12158             } else {
12159               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12160                   ref_len);
12161             }
12162           } else if (ref_type == FOURCC_url_) {
12163             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12164           } else {
12165             GST_DEBUG_OBJECT (qtdemux,
12166                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12167                 GST_FOURCC_ARGS (ref_type));
12168           }
12169           if (ref.location != NULL) {
12170             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12171             redirects =
12172                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12173           } else {
12174             GST_WARNING_OBJECT (qtdemux,
12175                 "Failed to extract redirect location from rdrf atom");
12176           }
12177         } else {
12178           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12179         }
12180       }
12181
12182       /* look for others */
12183       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12184     }
12185
12186     if (redirects != NULL) {
12187       qtdemux_process_redirects (qtdemux, redirects);
12188     }
12189   }
12190   return TRUE;
12191 }
12192
12193 static GstTagList *
12194 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12195 {
12196   const gchar *fmt;
12197
12198   if (tags == NULL) {
12199     tags = gst_tag_list_new_empty ();
12200     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12201   }
12202
12203   if (qtdemux->major_brand == FOURCC_mjp2)
12204     fmt = "Motion JPEG 2000";
12205   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12206     fmt = "3GP";
12207   else if (qtdemux->major_brand == FOURCC_qt__)
12208     fmt = "Quicktime";
12209   else if (qtdemux->fragmented)
12210     fmt = "ISO fMP4";
12211   else
12212     fmt = "ISO MP4/M4A";
12213
12214   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12215       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12216
12217   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12218       fmt, NULL);
12219
12220   return tags;
12221 }
12222
12223 /* we have read the complete moov node now.
12224  * This function parses all of the relevant info, creates the traks and
12225  * prepares all data structures for playback
12226  */
12227 static gboolean
12228 qtdemux_parse_tree (GstQTDemux * qtdemux)
12229 {
12230   GNode *mvhd;
12231   GNode *trak;
12232   GNode *udta;
12233   GNode *mvex;
12234   GstClockTime duration;
12235   GNode *pssh;
12236   guint64 creation_time;
12237   GstDateTime *datetime = NULL;
12238   gint version;
12239
12240   /* make sure we have a usable taglist */
12241   if (!qtdemux->tag_list) {
12242     qtdemux->tag_list = gst_tag_list_new_empty ();
12243     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12244   } else {
12245     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12246   }
12247
12248   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12249   if (mvhd == NULL) {
12250     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12251     return qtdemux_parse_redirects (qtdemux);
12252   }
12253
12254   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12255   if (version == 1) {
12256     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12257     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12258     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12259   } else if (version == 0) {
12260     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12261     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12262     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12263   } else {
12264     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12265     return FALSE;
12266   }
12267
12268   /* Moving qt creation time (secs since 1904) to unix time */
12269   if (creation_time != 0) {
12270     /* Try to use epoch first as it should be faster and more commonly found */
12271     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12272       GTimeVal now;
12273
12274       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12275       /* some data cleansing sanity */
12276       g_get_current_time (&now);
12277       if (now.tv_sec + 24 * 3600 < creation_time) {
12278         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12279       } else {
12280         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12281       }
12282     } else {
12283       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12284       GDateTime *dt, *dt_local;
12285
12286       dt = g_date_time_add_seconds (base_dt, creation_time);
12287       dt_local = g_date_time_to_local (dt);
12288       datetime = gst_date_time_new_from_g_date_time (dt_local);
12289
12290       g_date_time_unref (base_dt);
12291       g_date_time_unref (dt);
12292     }
12293   }
12294   if (datetime) {
12295     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12296     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12297         datetime, NULL);
12298     gst_date_time_unref (datetime);
12299   }
12300
12301   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12302   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12303
12304   /* check for fragmented file and get some (default) data */
12305   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12306   if (mvex) {
12307     GNode *mehd;
12308     GstByteReader mehd_data;
12309
12310     /* let track parsing or anyone know weird stuff might happen ... */
12311     qtdemux->fragmented = TRUE;
12312
12313     /* compensate for total duration */
12314     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12315     if (mehd)
12316       qtdemux_parse_mehd (qtdemux, &mehd_data);
12317   }
12318
12319   /* set duration in the segment info */
12320   gst_qtdemux_get_duration (qtdemux, &duration);
12321   if (duration) {
12322     qtdemux->segment.duration = duration;
12323     /* also do not exceed duration; stop is set that way post seek anyway,
12324      * and segment activation falls back to duration,
12325      * whereas loop only checks stop, so let's align this here as well */
12326     qtdemux->segment.stop = duration;
12327   }
12328
12329   /* parse all traks */
12330   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12331   while (trak) {
12332     qtdemux_parse_trak (qtdemux, trak);
12333     /* iterate all siblings */
12334     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12335   }
12336
12337   if (!qtdemux->tag_list) {
12338     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12339     qtdemux->tag_list = gst_tag_list_new_empty ();
12340     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12341   } else {
12342     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12343   }
12344
12345   /* find tags */
12346   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12347   if (udta) {
12348     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12349   } else {
12350     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12351   }
12352
12353   /* maybe also some tags in meta box */
12354   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12355   if (udta) {
12356     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12357     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12358   } else {
12359     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12360   }
12361
12362   /* parse any protection system info */
12363   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12364   while (pssh) {
12365     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12366     qtdemux_parse_pssh (qtdemux, pssh);
12367     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12368   }
12369
12370   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12371
12372   return TRUE;
12373 }
12374
12375 /* taken from ffmpeg */
12376 static int
12377 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12378 {
12379   int count = 4;
12380   int len = 0;
12381
12382   while (count--) {
12383     int c;
12384
12385     if (ptr >= end)
12386       return -1;
12387
12388     c = *ptr++;
12389     len = (len << 7) | (c & 0x7f);
12390     if (!(c & 0x80))
12391       break;
12392   }
12393   *end_out = ptr;
12394   return len;
12395 }
12396
12397 /* this can change the codec originally present in @list */
12398 static void
12399 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12400     GNode * esds, GstTagList * list)
12401 {
12402   int len = QT_UINT32 (esds->data);
12403   guint8 *ptr = esds->data;
12404   guint8 *end = ptr + len;
12405   int tag;
12406   guint8 *data_ptr = NULL;
12407   int data_len = 0;
12408   guint8 object_type_id = 0;
12409   const char *codec_name = NULL;
12410   GstCaps *caps = NULL;
12411
12412   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12413   ptr += 8;
12414   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12415   ptr += 4;
12416   while (ptr + 1 < end) {
12417     tag = QT_UINT8 (ptr);
12418     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12419     ptr++;
12420     len = read_descr_size (ptr, end, &ptr);
12421     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12422
12423     /* Check the stated amount of data is available for reading */
12424     if (len < 0 || ptr + len > end)
12425       break;
12426
12427     switch (tag) {
12428       case ES_DESCRIPTOR_TAG:
12429         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12430         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12431         ptr += 3;
12432         break;
12433       case DECODER_CONFIG_DESC_TAG:{
12434         guint max_bitrate, avg_bitrate;
12435
12436         object_type_id = QT_UINT8 (ptr);
12437         max_bitrate = QT_UINT32 (ptr + 5);
12438         avg_bitrate = QT_UINT32 (ptr + 9);
12439         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12440         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12441         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12442         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12443         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12444         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12445           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12446               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12447         }
12448         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12449           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12450               avg_bitrate, NULL);
12451         }
12452         ptr += 13;
12453         break;
12454       }
12455       case DECODER_SPECIFIC_INFO_TAG:
12456         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12457         if (object_type_id == 0xe0 && len == 0x40) {
12458           guint8 *data;
12459           GstStructure *s;
12460           guint32 clut[16];
12461           gint i;
12462
12463           GST_DEBUG_OBJECT (qtdemux,
12464               "Have VOBSUB palette. Creating palette event");
12465           /* move to decConfigDescr data and read palette */
12466           data = ptr;
12467           for (i = 0; i < 16; i++) {
12468             clut[i] = QT_UINT32 (data);
12469             data += 4;
12470           }
12471
12472           s = gst_structure_new ("application/x-gst-dvd", "event",
12473               G_TYPE_STRING, "dvd-spu-clut-change",
12474               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12475               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12476               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12477               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12478               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12479               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12480               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12481               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12482               NULL);
12483
12484           /* store event and trigger custom processing */
12485           stream->pending_event =
12486               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12487         } else {
12488           /* Generic codec_data handler puts it on the caps */
12489           data_ptr = ptr;
12490           data_len = len;
12491         }
12492
12493         ptr += len;
12494         break;
12495       case SL_CONFIG_DESC_TAG:
12496         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12497         ptr += 1;
12498         break;
12499       default:
12500         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12501             tag);
12502         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12503         ptr += len;
12504         break;
12505     }
12506   }
12507
12508   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12509    * in use, and should also be used to override some other parameters for some
12510    * codecs. */
12511   switch (object_type_id) {
12512     case 0x20:                 /* MPEG-4 */
12513       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12514        * profile_and_level_indication */
12515       if (data_ptr != NULL && data_len >= 5 &&
12516           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12517         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12518             data_ptr + 4, data_len - 4);
12519       }
12520       break;                    /* Nothing special needed here */
12521     case 0x21:                 /* H.264 */
12522       codec_name = "H.264 / AVC";
12523       caps = gst_caps_new_simple ("video/x-h264",
12524           "stream-format", G_TYPE_STRING, "avc",
12525           "alignment", G_TYPE_STRING, "au", NULL);
12526       break;
12527     case 0x40:                 /* AAC (any) */
12528     case 0x66:                 /* AAC Main */
12529     case 0x67:                 /* AAC LC */
12530     case 0x68:                 /* AAC SSR */
12531       /* Override channels and rate based on the codec_data, as it's often
12532        * wrong. */
12533       /* Only do so for basic setup without HE-AAC extension */
12534       if (data_ptr && data_len == 2) {
12535         guint channels, rate;
12536
12537         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
12538         if (channels > 0)
12539           stream->n_channels = channels;
12540
12541         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
12542         if (rate > 0)
12543           stream->rate = rate;
12544       }
12545
12546       /* Set level and profile if possible */
12547       if (data_ptr != NULL && data_len >= 2) {
12548         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12549             data_ptr, data_len);
12550       }
12551       break;
12552     case 0x60:                 /* MPEG-2, various profiles */
12553     case 0x61:
12554     case 0x62:
12555     case 0x63:
12556     case 0x64:
12557     case 0x65:
12558       codec_name = "MPEG-2 video";
12559       caps = gst_caps_new_simple ("video/mpeg",
12560           "mpegversion", G_TYPE_INT, 2,
12561           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12562       break;
12563     case 0x69:                 /* MPEG-2 BC audio */
12564     case 0x6B:                 /* MPEG-1 audio */
12565       caps = gst_caps_new_simple ("audio/mpeg",
12566           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12567       codec_name = "MPEG-1 audio";
12568       break;
12569     case 0x6A:                 /* MPEG-1 */
12570       codec_name = "MPEG-1 video";
12571       caps = gst_caps_new_simple ("video/mpeg",
12572           "mpegversion", G_TYPE_INT, 1,
12573           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12574       break;
12575     case 0x6C:                 /* MJPEG */
12576       caps =
12577           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12578           NULL);
12579       codec_name = "Motion-JPEG";
12580       break;
12581     case 0x6D:                 /* PNG */
12582       caps =
12583           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12584           NULL);
12585       codec_name = "PNG still images";
12586       break;
12587     case 0x6E:                 /* JPEG2000 */
12588       codec_name = "JPEG-2000";
12589       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12590       break;
12591     case 0xA4:                 /* Dirac */
12592       codec_name = "Dirac";
12593       caps = gst_caps_new_empty_simple ("video/x-dirac");
12594       break;
12595     case 0xA5:                 /* AC3 */
12596       codec_name = "AC-3 audio";
12597       caps = gst_caps_new_simple ("audio/x-ac3",
12598           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12599       break;
12600     case 0xA9:                 /* AC3 */
12601       codec_name = "DTS audio";
12602       caps = gst_caps_new_simple ("audio/x-dts",
12603           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12604       break;
12605     case 0xE1:                 /* QCELP */
12606       /* QCELP, the codec_data is a riff tag (little endian) with
12607        * 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). */
12608       caps = gst_caps_new_empty_simple ("audio/qcelp");
12609       codec_name = "QCELP";
12610       break;
12611     default:
12612       break;
12613   }
12614
12615   /* If we have a replacement caps, then change our caps for this stream */
12616   if (caps) {
12617     gst_caps_unref (stream->caps);
12618     stream->caps = caps;
12619   }
12620
12621   if (codec_name && list)
12622     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12623         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12624
12625   /* Add the codec_data attribute to caps, if we have it */
12626   if (data_ptr) {
12627     GstBuffer *buffer;
12628
12629     buffer = gst_buffer_new_and_alloc (data_len);
12630     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12631
12632     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12633     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12634
12635     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12636         buffer, NULL);
12637     gst_buffer_unref (buffer);
12638   }
12639
12640 }
12641
12642 #define _codec(name) \
12643   do { \
12644     if (codec_name) { \
12645       *codec_name = g_strdup (name); \
12646     } \
12647   } while (0)
12648
12649 static GstCaps *
12650 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12651     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12652 {
12653   GstCaps *caps = NULL;
12654   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12655
12656   switch (fourcc) {
12657     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12658       _codec ("PNG still images");
12659       caps = gst_caps_new_empty_simple ("image/png");
12660       break;
12661     case FOURCC_jpeg:
12662       _codec ("JPEG still images");
12663       caps =
12664           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12665           NULL);
12666       break;
12667     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12668     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12669     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12670     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12671       _codec ("Motion-JPEG");
12672       caps =
12673           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12674           NULL);
12675       break;
12676     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12677       _codec ("Motion-JPEG format B");
12678       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12679       break;
12680     case FOURCC_mjp2:
12681       _codec ("JPEG-2000");
12682       /* override to what it should be according to spec, avoid palette_data */
12683       stream->bits_per_sample = 24;
12684       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12685       break;
12686     case FOURCC_SVQ3:
12687       _codec ("Sorensen video v.3");
12688       caps = gst_caps_new_simple ("video/x-svq",
12689           "svqversion", G_TYPE_INT, 3, NULL);
12690       break;
12691     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12692     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12693       _codec ("Sorensen video v.1");
12694       caps = gst_caps_new_simple ("video/x-svq",
12695           "svqversion", G_TYPE_INT, 1, NULL);
12696       break;
12697     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12698       caps = gst_caps_new_empty_simple ("video/x-raw");
12699       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12700       _codec ("Windows Raw RGB");
12701       break;
12702     case FOURCC_raw_:
12703     {
12704       guint16 bps;
12705
12706       bps = QT_UINT16 (stsd_data + 98);
12707       switch (bps) {
12708         case 15:
12709           format = GST_VIDEO_FORMAT_RGB15;
12710           break;
12711         case 16:
12712           format = GST_VIDEO_FORMAT_RGB16;
12713           break;
12714         case 24:
12715           format = GST_VIDEO_FORMAT_RGB;
12716           break;
12717         case 32:
12718           format = GST_VIDEO_FORMAT_ARGB;
12719           break;
12720         default:
12721           /* unknown */
12722           break;
12723       }
12724       break;
12725     }
12726     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12727       format = GST_VIDEO_FORMAT_I420;
12728       break;
12729     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12730     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12731       format = GST_VIDEO_FORMAT_I420;
12732       break;
12733     case FOURCC_2vuy:
12734     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12735       format = GST_VIDEO_FORMAT_UYVY;
12736       break;
12737     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12738       format = GST_VIDEO_FORMAT_v308;
12739       break;
12740     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12741       format = GST_VIDEO_FORMAT_v216;
12742       break;
12743     case FOURCC_v210:
12744       format = GST_VIDEO_FORMAT_v210;
12745       break;
12746     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12747       format = GST_VIDEO_FORMAT_r210;
12748       break;
12749       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12750          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12751          format = GST_VIDEO_FORMAT_v410;
12752          break;
12753        */
12754       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12755        * but different order than AYUV
12756        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12757        format = GST_VIDEO_FORMAT_v408;
12758        break;
12759        */
12760     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12761     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12762       _codec ("MPEG-1 video");
12763       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12764           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12765       break;
12766     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12767     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12768     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12769     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12770     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12771     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12772     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12773     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12774     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12775     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12776     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12777     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12778     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12779     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12780     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12781     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12782     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12783     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12784     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12785     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12786     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12787     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12788     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12789     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12790     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12791     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12792     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12793     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12794     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12795     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12796     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12797     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12798     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12799     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12800     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12801     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12802     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12803     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12804     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12805     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12806     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12807     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12808     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12809     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12810     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12811     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12812       _codec ("MPEG-2 video");
12813       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12814           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12815       break;
12816     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12817       _codec ("GIF still images");
12818       caps = gst_caps_new_empty_simple ("image/gif");
12819       break;
12820     case FOURCC_h263:
12821     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12822     case FOURCC_s263:
12823     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12824       _codec ("H.263");
12825       /* ffmpeg uses the height/width props, don't know why */
12826       caps = gst_caps_new_simple ("video/x-h263",
12827           "variant", G_TYPE_STRING, "itu", NULL);
12828       break;
12829     case FOURCC_mp4v:
12830     case FOURCC_MP4V:
12831       _codec ("MPEG-4 video");
12832       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12833           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12834       break;
12835     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12836     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12837       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12838       caps = gst_caps_new_simple ("video/x-msmpeg",
12839           "msmpegversion", G_TYPE_INT, 43, NULL);
12840       break;
12841     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12842       _codec ("DivX 3");
12843       caps = gst_caps_new_simple ("video/x-divx",
12844           "divxversion", G_TYPE_INT, 3, NULL);
12845       break;
12846     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12847     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12848       _codec ("DivX 4");
12849       caps = gst_caps_new_simple ("video/x-divx",
12850           "divxversion", G_TYPE_INT, 4, NULL);
12851       break;
12852     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12853       _codec ("DivX 5");
12854       caps = gst_caps_new_simple ("video/x-divx",
12855           "divxversion", G_TYPE_INT, 5, NULL);
12856       break;
12857
12858     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
12859       _codec ("FFV1");
12860       caps = gst_caps_new_simple ("video/x-ffv",
12861           "ffvversion", G_TYPE_INT, 1, NULL);
12862       break;
12863
12864     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12865     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12866     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12867     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12868     case FOURCC_FMP4:
12869     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12870       caps = gst_caps_new_simple ("video/mpeg",
12871           "mpegversion", G_TYPE_INT, 4, NULL);
12872       _codec ("MPEG-4");
12873       break;
12874
12875     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12876       _codec ("Cinepak");
12877       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12878       break;
12879     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12880       _codec ("Apple QuickDraw");
12881       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12882       break;
12883     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12884       _codec ("Apple video");
12885       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12886       break;
12887     case FOURCC_H264:
12888     case FOURCC_avc1:
12889       _codec ("H.264 / AVC");
12890       caps = gst_caps_new_simple ("video/x-h264",
12891           "stream-format", G_TYPE_STRING, "avc",
12892           "alignment", G_TYPE_STRING, "au", NULL);
12893       break;
12894     case FOURCC_avc3:
12895       _codec ("H.264 / AVC");
12896       caps = gst_caps_new_simple ("video/x-h264",
12897           "stream-format", G_TYPE_STRING, "avc3",
12898           "alignment", G_TYPE_STRING, "au", NULL);
12899       break;
12900     case FOURCC_H265:
12901     case FOURCC_hvc1:
12902       _codec ("H.265 / HEVC");
12903       caps = gst_caps_new_simple ("video/x-h265",
12904           "stream-format", G_TYPE_STRING, "hvc1",
12905           "alignment", G_TYPE_STRING, "au", NULL);
12906       break;
12907     case FOURCC_hev1:
12908       _codec ("H.265 / HEVC");
12909       caps = gst_caps_new_simple ("video/x-h265",
12910           "stream-format", G_TYPE_STRING, "hev1",
12911           "alignment", G_TYPE_STRING, "au", NULL);
12912       break;
12913     case FOURCC_rle_:
12914       _codec ("Run-length encoding");
12915       caps = gst_caps_new_simple ("video/x-rle",
12916           "layout", G_TYPE_STRING, "quicktime", NULL);
12917       break;
12918     case FOURCC_WRLE:
12919       _codec ("Run-length encoding");
12920       caps = gst_caps_new_simple ("video/x-rle",
12921           "layout", G_TYPE_STRING, "microsoft", NULL);
12922       break;
12923     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12924     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12925       _codec ("Indeo Video 3");
12926       caps = gst_caps_new_simple ("video/x-indeo",
12927           "indeoversion", G_TYPE_INT, 3, NULL);
12928       break;
12929     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12930     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12931       _codec ("Intel Video 4");
12932       caps = gst_caps_new_simple ("video/x-indeo",
12933           "indeoversion", G_TYPE_INT, 4, NULL);
12934       break;
12935     case FOURCC_dvcp:
12936     case FOURCC_dvc_:
12937     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12938     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12939     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12940     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12941     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12942     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12943       _codec ("DV Video");
12944       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12945           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12946       break;
12947     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
12948     case FOURCC_dv5p:          /* DVCPRO50 PAL */
12949       _codec ("DVCPro50 Video");
12950       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12951           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12952       break;
12953     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12954     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12955       _codec ("DVCProHD Video");
12956       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12957           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12958       break;
12959     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12960       _codec ("Apple Graphics (SMC)");
12961       caps = gst_caps_new_empty_simple ("video/x-smc");
12962       break;
12963     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12964       _codec ("VP3");
12965       caps = gst_caps_new_empty_simple ("video/x-vp3");
12966       break;
12967     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12968       _codec ("VP6 Flash");
12969       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12970       break;
12971     case FOURCC_XiTh:
12972       _codec ("Theora");
12973       caps = gst_caps_new_empty_simple ("video/x-theora");
12974       /* theora uses one byte of padding in the data stream because it does not
12975        * allow 0 sized packets while theora does */
12976       stream->padding = 1;
12977       break;
12978     case FOURCC_drac:
12979       _codec ("Dirac");
12980       caps = gst_caps_new_empty_simple ("video/x-dirac");
12981       break;
12982     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
12983       _codec ("TIFF still images");
12984       caps = gst_caps_new_empty_simple ("image/tiff");
12985       break;
12986     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
12987       _codec ("Apple Intermediate Codec");
12988       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
12989       break;
12990     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
12991       _codec ("AVID DNxHD");
12992       caps = gst_caps_from_string ("video/x-dnxhd");
12993       break;
12994     case FOURCC_VP80:
12995       _codec ("On2 VP8");
12996       caps = gst_caps_from_string ("video/x-vp8");
12997       break;
12998     case FOURCC_apcs:
12999       _codec ("Apple ProRes LT");
13000       caps =
13001           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13002           NULL);
13003       break;
13004     case FOURCC_apch:
13005       _codec ("Apple ProRes HQ");
13006       caps =
13007           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13008           NULL);
13009       break;
13010     case FOURCC_apcn:
13011       _codec ("Apple ProRes");
13012       caps =
13013           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13014           "standard", NULL);
13015       break;
13016     case FOURCC_apco:
13017       _codec ("Apple ProRes Proxy");
13018       caps =
13019           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13020           "proxy", NULL);
13021       break;
13022     case FOURCC_ap4h:
13023       _codec ("Apple ProRes 4444");
13024       caps =
13025           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13026           "4444", NULL);
13027       break;
13028     case FOURCC_vc_1:
13029     case FOURCC_ovc1:
13030       _codec ("VC-1");
13031       caps = gst_caps_new_simple ("video/x-wmv",
13032           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13033       break;
13034     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13035     default:
13036     {
13037       char *s, fourstr[5];
13038
13039       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13040       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
13041       caps = gst_caps_new_empty_simple (s);
13042       g_free (s);
13043       break;
13044     }
13045   }
13046
13047   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13048     GstVideoInfo info;
13049
13050     gst_video_info_init (&info);
13051     gst_video_info_set_format (&info, format, stream->width, stream->height);
13052
13053     caps = gst_video_info_to_caps (&info);
13054     *codec_name = gst_pb_utils_get_codec_description (caps);
13055
13056     /* enable clipping for raw video streams */
13057     stream->need_clip = TRUE;
13058   }
13059
13060   return caps;
13061 }
13062
13063 static GstCaps *
13064 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13065     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13066 {
13067   GstCaps *caps;
13068   const GstStructure *s;
13069   const gchar *name;
13070   gint endian = 0;
13071   GstAudioFormat format = 0;
13072   gint depth;
13073
13074   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13075
13076   depth = stream->bytes_per_packet * 8;
13077
13078   switch (fourcc) {
13079     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13080     case FOURCC_raw_:
13081       /* 8-bit audio is unsigned */
13082       if (depth == 8)
13083         format = GST_AUDIO_FORMAT_U8;
13084       /* otherwise it's signed and big-endian just like 'twos' */
13085     case FOURCC_twos:
13086       endian = G_BIG_ENDIAN;
13087       /* fall-through */
13088     case FOURCC_sowt:
13089     {
13090       gchar *str;
13091
13092       if (!endian)
13093         endian = G_LITTLE_ENDIAN;
13094
13095       if (!format)
13096         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13097
13098       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13099       _codec (str);
13100       g_free (str);
13101
13102       caps = gst_caps_new_simple ("audio/x-raw",
13103           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13104           "layout", G_TYPE_STRING, "interleaved", NULL);
13105       break;
13106     }
13107     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13108       _codec ("Raw 64-bit floating-point audio");
13109       caps = gst_caps_new_simple ("audio/x-raw",
13110           "format", G_TYPE_STRING, "F64BE",
13111           "layout", G_TYPE_STRING, "interleaved", NULL);
13112       break;
13113     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13114       _codec ("Raw 32-bit floating-point audio");
13115       caps = gst_caps_new_simple ("audio/x-raw",
13116           "format", G_TYPE_STRING, "F32BE",
13117           "layout", G_TYPE_STRING, "interleaved", NULL);
13118       break;
13119     case FOURCC_in24:
13120       _codec ("Raw 24-bit PCM audio");
13121       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13122        * endian later */
13123       caps = gst_caps_new_simple ("audio/x-raw",
13124           "format", G_TYPE_STRING, "S24BE",
13125           "layout", G_TYPE_STRING, "interleaved", NULL);
13126       break;
13127     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13128       _codec ("Raw 32-bit PCM audio");
13129       caps = gst_caps_new_simple ("audio/x-raw",
13130           "format", G_TYPE_STRING, "S32BE",
13131           "layout", G_TYPE_STRING, "interleaved", NULL);
13132       break;
13133     case FOURCC_ulaw:
13134       _codec ("Mu-law audio");
13135       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13136       break;
13137     case FOURCC_alaw:
13138       _codec ("A-law audio");
13139       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13140       break;
13141     case 0x0200736d:
13142     case 0x6d730002:
13143       _codec ("Microsoft ADPCM");
13144       /* Microsoft ADPCM-ACM code 2 */
13145       caps = gst_caps_new_simple ("audio/x-adpcm",
13146           "layout", G_TYPE_STRING, "microsoft", NULL);
13147       break;
13148     case 0x1100736d:
13149     case 0x6d730011:
13150       _codec ("DVI/IMA ADPCM");
13151       caps = gst_caps_new_simple ("audio/x-adpcm",
13152           "layout", G_TYPE_STRING, "dvi", NULL);
13153       break;
13154     case 0x1700736d:
13155     case 0x6d730017:
13156       _codec ("DVI/Intel IMA ADPCM");
13157       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13158       caps = gst_caps_new_simple ("audio/x-adpcm",
13159           "layout", G_TYPE_STRING, "quicktime", NULL);
13160       break;
13161     case 0x5500736d:
13162     case 0x6d730055:
13163       /* MPEG layer 3, CBR only (pre QT4.1) */
13164     case FOURCC__mp3:
13165       _codec ("MPEG-1 layer 3");
13166       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13167       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13168           "mpegversion", G_TYPE_INT, 1, NULL);
13169       break;
13170     case 0x20736d:
13171     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13172       _codec ("EAC-3 audio");
13173       caps = gst_caps_new_simple ("audio/x-eac3",
13174           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13175       stream->sampled = TRUE;
13176       break;
13177     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13178     case FOURCC_ac_3:
13179       _codec ("AC-3 audio");
13180       caps = gst_caps_new_simple ("audio/x-ac3",
13181           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13182       stream->sampled = TRUE;
13183       break;
13184     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13185     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13186       _codec ("DTS audio");
13187       caps = gst_caps_new_simple ("audio/x-dts",
13188           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13189       stream->sampled = TRUE;
13190       break;
13191     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13192     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13193       _codec ("DTS-HD audio");
13194       caps = gst_caps_new_simple ("audio/x-dts",
13195           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13196       stream->sampled = TRUE;
13197       break;
13198     case FOURCC_MAC3:
13199       _codec ("MACE-3");
13200       caps = gst_caps_new_simple ("audio/x-mace",
13201           "maceversion", G_TYPE_INT, 3, NULL);
13202       break;
13203     case FOURCC_MAC6:
13204       _codec ("MACE-6");
13205       caps = gst_caps_new_simple ("audio/x-mace",
13206           "maceversion", G_TYPE_INT, 6, NULL);
13207       break;
13208     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13209       /* ogg/vorbis */
13210       caps = gst_caps_new_empty_simple ("application/ogg");
13211       break;
13212     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13213       _codec ("DV audio");
13214       caps = gst_caps_new_empty_simple ("audio/x-dv");
13215       break;
13216     case FOURCC_mp4a:
13217       _codec ("MPEG-4 AAC audio");
13218       caps = gst_caps_new_simple ("audio/mpeg",
13219           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13220           "stream-format", G_TYPE_STRING, "raw", NULL);
13221       break;
13222     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13223       _codec ("QDesign Music");
13224       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13225       break;
13226     case FOURCC_QDM2:
13227       _codec ("QDesign Music v.2");
13228       /* FIXME: QDesign music version 2 (no constant) */
13229       if (FALSE && data) {
13230         caps = gst_caps_new_simple ("audio/x-qdm2",
13231             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13232             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13233             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13234       } else {
13235         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13236       }
13237       break;
13238     case FOURCC_agsm:
13239       _codec ("GSM audio");
13240       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13241       break;
13242     case FOURCC_samr:
13243       _codec ("AMR audio");
13244       caps = gst_caps_new_empty_simple ("audio/AMR");
13245       break;
13246     case FOURCC_sawb:
13247       _codec ("AMR-WB audio");
13248       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13249       break;
13250     case FOURCC_ima4:
13251       _codec ("Quicktime IMA ADPCM");
13252       caps = gst_caps_new_simple ("audio/x-adpcm",
13253           "layout", G_TYPE_STRING, "quicktime", NULL);
13254       break;
13255     case FOURCC_alac:
13256       _codec ("Apple lossless audio");
13257       caps = gst_caps_new_empty_simple ("audio/x-alac");
13258       break;
13259     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13260       _codec ("QualComm PureVoice");
13261       caps = gst_caps_from_string ("audio/qcelp");
13262       break;
13263     case FOURCC_wma_:
13264     case FOURCC_owma:
13265       _codec ("WMA");
13266       caps = gst_caps_new_empty_simple ("audio/x-wma");
13267       break;
13268     case FOURCC_opus:
13269       _codec ("Opus");
13270       caps = gst_caps_new_empty_simple ("audio/x-opus");
13271       break;
13272     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13273     {
13274       guint32 flags = 0;
13275       guint32 depth = 0;
13276       guint32 width = 0;
13277       GstAudioFormat format;
13278       enum
13279       {
13280         FLAG_IS_FLOAT = 0x1,
13281         FLAG_IS_BIG_ENDIAN = 0x2,
13282         FLAG_IS_SIGNED = 0x4,
13283         FLAG_IS_PACKED = 0x8,
13284         FLAG_IS_ALIGNED_HIGH = 0x10,
13285         FLAG_IS_NON_INTERLEAVED = 0x20
13286       };
13287       _codec ("Raw LPCM audio");
13288
13289       if (data && len >= 56) {
13290         depth = QT_UINT32 (data + 40);
13291         flags = QT_UINT32 (data + 44);
13292         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13293       }
13294       if ((flags & FLAG_IS_FLOAT) == 0) {
13295         if (depth == 0)
13296           depth = 16;
13297         if (width == 0)
13298           width = 16;
13299         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13300             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13301             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13302         caps = gst_caps_new_simple ("audio/x-raw",
13303             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13304             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13305             "non-interleaved" : "interleaved", NULL);
13306       } else {
13307         if (width == 0)
13308           width = 32;
13309         if (width == 64) {
13310           if (flags & FLAG_IS_BIG_ENDIAN)
13311             format = GST_AUDIO_FORMAT_F64BE;
13312           else
13313             format = GST_AUDIO_FORMAT_F64LE;
13314         } else {
13315           if (flags & FLAG_IS_BIG_ENDIAN)
13316             format = GST_AUDIO_FORMAT_F32BE;
13317           else
13318             format = GST_AUDIO_FORMAT_F32LE;
13319         }
13320         caps = gst_caps_new_simple ("audio/x-raw",
13321             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13322             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13323             "non-interleaved" : "interleaved", NULL);
13324       }
13325       break;
13326     }
13327     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
13328       /* ? */
13329     default:
13330     {
13331       char *s, fourstr[5];
13332
13333       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13334       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
13335       caps = gst_caps_new_empty_simple (s);
13336       g_free (s);
13337       break;
13338     }
13339   }
13340
13341   if (caps) {
13342     GstCaps *templ_caps =
13343         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
13344     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
13345     gst_caps_unref (caps);
13346     gst_caps_unref (templ_caps);
13347     caps = intersection;
13348   }
13349
13350   /* enable clipping for raw audio streams */
13351   s = gst_caps_get_structure (caps, 0);
13352   name = gst_structure_get_name (s);
13353   if (g_str_has_prefix (name, "audio/x-raw")) {
13354     stream->need_clip = TRUE;
13355     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
13356     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
13357   }
13358   return caps;
13359 }
13360
13361 static GstCaps *
13362 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13363     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13364 {
13365   GstCaps *caps;
13366
13367   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13368
13369   switch (fourcc) {
13370     case FOURCC_mp4s:
13371       _codec ("DVD subtitle");
13372       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
13373       stream->need_process = TRUE;
13374       break;
13375     case FOURCC_text:
13376       _codec ("Quicktime timed text");
13377       goto text;
13378     case FOURCC_tx3g:
13379       _codec ("3GPP timed text");
13380     text:
13381       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
13382           "utf8", NULL);
13383       /* actual text piece needs to be extracted */
13384       stream->need_process = TRUE;
13385       break;
13386     case FOURCC_stpp:
13387       _codec ("XML subtitles");
13388       caps = gst_caps_new_empty_simple ("application/ttml+xml");
13389       break;
13390     default:
13391     {
13392       char *s, fourstr[5];
13393
13394       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13395       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
13396       caps = gst_caps_new_empty_simple (s);
13397       g_free (s);
13398       break;
13399     }
13400   }
13401   return caps;
13402 }
13403
13404 static GstCaps *
13405 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13406     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13407 {
13408   GstCaps *caps;
13409
13410   switch (fourcc) {
13411     case FOURCC_m1v:
13412       _codec ("MPEG 1 video");
13413       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13414           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13415       break;
13416     default:
13417       caps = NULL;
13418       break;
13419   }
13420   return caps;
13421 }
13422
13423 static void
13424 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
13425     const gchar * system_id)
13426 {
13427   gint i;
13428
13429   if (!qtdemux->protection_system_ids)
13430     qtdemux->protection_system_ids =
13431         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13432   /* Check whether we already have an entry for this system ID. */
13433   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13434     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13435     if (g_ascii_strcasecmp (system_id, id) == 0) {
13436       return;
13437     }
13438   }
13439   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13440   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13441           -1));
13442 }