qtdemux: Fix key_time in gst_qtdemux_adjust_seek()
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59
60 #include "qtatomparser.h"
61 #include "qtdemux_types.h"
62 #include "qtdemux_dump.h"
63 #include "fourcc.h"
64 #include "descriptors.h"
65 #include "qtdemux_lang.h"
66 #include "qtdemux.h"
67 #include "qtpalette.h"
68
69 #include "gst/riff/riff-media.h"
70 #include "gst/riff/riff-read.h"
71
72 #include <gst/pbutils/pbutils.h>
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
98
99 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
100
101 GST_DEBUG_CATEGORY (qtdemux_debug);
102
103 typedef struct _QtDemuxSegment QtDemuxSegment;
104 typedef struct _QtDemuxSample QtDemuxSample;
105
106 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
107
108 struct _QtDemuxSample
109 {
110   guint32 size;
111   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
112   guint64 offset;
113   guint64 timestamp;            /* DTS In mov time */
114   guint32 duration;             /* In mov time */
115   gboolean keyframe;            /* TRUE when this packet is a keyframe */
116 };
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset is the PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + duration - dts is the duration */
130 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
131
132 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
133
134 /*
135  * Quicktime has tracks and segments. A track is a continuous piece of
136  * multimedia content. The track is not always played from start to finish but
137  * instead, pieces of the track are 'cut out' and played in sequence. This is
138  * what the segments do.
139  *
140  * Inside the track we have keyframes (K) and delta frames. The track has its
141  * own timing, which starts from 0 and extends to end. The position in the track
142  * is called the media_time.
143  *
144  * The segments now describe the pieces that should be played from this track
145  * and are basically tuples of media_time/duration/rate entries. We can have
146  * multiple segments and they are all played after one another. An example:
147  *
148  * segment 1: media_time: 1 second, duration: 1 second, rate 1
149  * segment 2: media_time: 3 second, duration: 2 second, rate 2
150  *
151  * To correctly play back this track, one must play: 1 second of media starting
152  * from media_time 1 followed by 2 seconds of media starting from media_time 3
153  * at a rate of 2.
154  *
155  * Each of the segments will be played at a specific time, the first segment at
156  * time 0, the second one after the duration of the first one, etc.. Note that
157  * the time in resulting playback is not identical to the media_time of the
158  * track anymore.
159  *
160  * Visually, assuming the track has 4 second of media_time:
161  *
162  *                (a)                   (b)          (c)              (d)
163  *         .-----------------------------------------------------------.
164  * track:  | K.....K.........K........K.......K.......K...........K... |
165  *         '-----------------------------------------------------------'
166  *         0              1              2              3              4
167  *           .------------^              ^   .----------^              ^
168  *          /              .-------------'  /       .------------------'
169  *         /              /          .-----'       /
170  *         .--------------.         .--------------.
171  *         | segment 1    |         | segment 2    |
172  *         '--------------'         '--------------'
173  *
174  * The challenge here is to cut out the right pieces of the track for each of
175  * the playback segments. This fortunately can easily be done with the SEGMENT
176  * events of GStreamer.
177  *
178  * For playback of segment 1, we need to provide the decoder with the keyframe
179  * (a), in the above figure, but we must instruct it only to output the decoded
180  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
181  * position set to the time of the segment: 0.
182  *
183  * We then proceed to push data from keyframe (a) to frame (b). The decoder
184  * decodes but clips all before media_time 1.
185  *
186  * After finishing a segment, we push out a new SEGMENT event with the clipping
187  * boundaries of the new data.
188  *
189  * This is a good usecase for the GStreamer accumulated SEGMENT events.
190  */
191
192 struct _QtDemuxSegment
193 {
194   /* global time and duration, all gst time */
195   GstClockTime time;
196   GstClockTime stop_time;
197   GstClockTime duration;
198   /* media time of trak, all gst time */
199   GstClockTime media_start;
200   GstClockTime media_stop;
201   gdouble rate;
202   /* Media start time in trak timescale units */
203   guint32 trak_media_start;
204 };
205
206 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
207
208 /* Used with fragmented MP4 files (mfra atom) */
209 typedef struct
210 {
211   GstClockTime ts;
212   guint64 moof_offset;
213 } QtDemuxRandomAccessEntry;
214
215 struct _QtDemuxStream
216 {
217   GstPad *pad;
218
219   /* stream type */
220   guint32 subtype;
221   GstCaps *caps;
222   guint32 fourcc;
223   gboolean sparse;
224
225   gboolean new_caps;            /* If TRUE, caps need to be generated (by
226                                  * calling _configure_stream()) This happens
227                                  * for MSS and fragmented streams */
228
229   gboolean new_stream;          /* signals that a stream_start is required */
230   gboolean on_keyframe;         /* if this stream last pushed buffer was a
231                                  * keyframe. This is important to identify
232                                  * where to stop pushing buffers after a
233                                  * segment stop time */
234
235   /* if the stream has a redirect URI in its headers, we store it here */
236   gchar *redirect_uri;
237
238   /* track id */
239   guint track_id;
240
241   /* duration/scale */
242   guint64 duration;             /* in timescale units */
243   guint32 timescale;
244
245   /* language */
246   gchar lang_id[4];             /* ISO 639-2T language code */
247
248   /* our samples */
249   guint32 n_samples;
250   QtDemuxSample *samples;
251   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
252   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
253                                    the framerate */
254   guint32 n_samples_moof;       /* sample count in a moof */
255   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
256                                  * the framerate of fragmented format stream */
257   guint64 duration_last_moof;
258
259   guint32 offset_in_sample;     /* Offset in the current sample, used for
260                                  * streams which have got exceedingly big
261                                  * sample size (such as 24s of raw audio).
262                                  * Only used when max_buffer_size is non-NULL */
263   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
264                                  * Currently only set for raw audio streams*/
265
266   /* if we use chunks or samples */
267   gboolean sampled;
268   guint padding;
269
270   /* video info */
271   gint width;
272   gint height;
273   /* aspect ratio */
274   gint display_width;
275   gint display_height;
276   gint par_w;
277   gint par_h;
278   /* Numerator/denominator framerate */
279   gint fps_n;
280   gint fps_d;
281   GstVideoColorimetry colorimetry;
282   guint16 bits_per_sample;
283   guint16 color_table_id;
284   GstMemory *rgb8_palette;
285   guint interlace_mode;
286   guint field_order;
287
288   /* audio info */
289   gdouble rate;
290   gint n_channels;
291   guint samples_per_packet;
292   guint samples_per_frame;
293   guint bytes_per_packet;
294   guint bytes_per_sample;
295   guint bytes_per_frame;
296   guint compression;
297
298   /* allocation */
299   gboolean use_allocator;
300   GstAllocator *allocator;
301   GstAllocationParams params;
302
303   gsize alignment;
304
305   /* when a discontinuity is pending */
306   gboolean discont;
307
308   /* list of buffers to push first */
309   GSList *buffers;
310
311   /* if we need to clip this buffer. This is only needed for uncompressed
312    * data */
313   gboolean need_clip;
314
315   /* buffer needs some custom processing, e.g. subtitles */
316   gboolean need_process;
317
318   /* current position */
319   guint32 segment_index;
320   guint32 sample_index;
321   GstClockTime time_position;   /* in gst time */
322   guint64 accumulated_base;
323
324   /* the Gst segment we are processing out, used for clipping */
325   GstSegment segment;
326
327   /* quicktime segments */
328   guint32 n_segments;
329   QtDemuxSegment *segments;
330   gboolean dummy_segment;
331   guint32 from_sample;
332   guint32 to_sample;
333
334   gboolean sent_eos;
335   GstTagList *pending_tags;
336   gboolean send_global_tags;
337
338   GstEvent *pending_event;
339
340   GstByteReader stco;
341   GstByteReader stsz;
342   GstByteReader stsc;
343   GstByteReader stts;
344   GstByteReader stss;
345   GstByteReader stps;
346   GstByteReader ctts;
347
348   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
349   gint64 stbl_index;
350   /* stco */
351   guint co_size;
352   GstByteReader co_chunk;
353   guint32 first_chunk;
354   guint32 current_chunk;
355   guint32 last_chunk;
356   guint32 samples_per_chunk;
357   guint32 stco_sample_index;
358   /* stsz */
359   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
360   /* stsc */
361   guint32 stsc_index;
362   guint32 n_samples_per_chunk;
363   guint32 stsc_chunk_index;
364   guint32 stsc_sample_index;
365   guint64 chunk_offset;
366   /* stts */
367   guint32 stts_index;
368   guint32 stts_samples;
369   guint32 n_sample_times;
370   guint32 stts_sample_index;
371   guint64 stts_time;
372   guint32 stts_duration;
373   /* stss */
374   gboolean stss_present;
375   guint32 n_sample_syncs;
376   guint32 stss_index;
377   /* stps */
378   gboolean stps_present;
379   guint32 n_sample_partial_syncs;
380   guint32 stps_index;
381   QtDemuxRandomAccessEntry *ra_entries;
382   guint n_ra_entries;
383
384   const QtDemuxRandomAccessEntry *pending_seek;
385
386   /* ctts */
387   gboolean ctts_present;
388   guint32 n_composition_times;
389   guint32 ctts_index;
390   guint32 ctts_sample_index;
391   guint32 ctts_count;
392   gint32 ctts_soffset;
393
394   /* cslg */
395   guint32 cslg_shift;
396
397   /* fragmented */
398   gboolean parsed_trex;
399   guint32 def_sample_duration;
400   guint32 def_sample_size;
401   guint32 def_sample_flags;
402
403   gboolean disabled;
404
405   /* stereoscopic video streams */
406   GstVideoMultiviewMode multiview_mode;
407   GstVideoMultiviewFlags multiview_flags;
408
409   /* protected streams */
410   gboolean protected;
411   guint32 protection_scheme_type;
412   guint32 protection_scheme_version;
413   gpointer protection_scheme_info;      /* specific to the protection scheme */
414   GQueue protection_scheme_event_queue;
415 };
416
417 /* Contains properties and cryptographic info for a set of samples from a
418  * track protected using Common Encryption (cenc) */
419 struct _QtDemuxCencSampleSetInfo
420 {
421   GstStructure *default_properties;
422
423   /* @crypto_info holds one GstStructure per sample */
424   GPtrArray *crypto_info;
425 };
426
427 static const gchar *
428 qt_demux_state_string (enum QtDemuxState state)
429 {
430   switch (state) {
431     case QTDEMUX_STATE_INITIAL:
432       return "<INITIAL>";
433     case QTDEMUX_STATE_HEADER:
434       return "<HEADER>";
435     case QTDEMUX_STATE_MOVIE:
436       return "<MOVIE>";
437     case QTDEMUX_STATE_BUFFER_MDAT:
438       return "<BUFFER_MDAT>";
439     default:
440       return "<UNKNOWN>";
441   }
442 }
443
444 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
445 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
446     guint32 fourcc, GstByteReader * parser);
447 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
448 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
449     guint32 fourcc, GstByteReader * parser);
450
451 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
452
453 static GstStaticPadTemplate gst_qtdemux_sink_template =
454     GST_STATIC_PAD_TEMPLATE ("sink",
455     GST_PAD_SINK,
456     GST_PAD_ALWAYS,
457     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
458         "application/x-3gp")
459     );
460
461 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
462 GST_STATIC_PAD_TEMPLATE ("video_%u",
463     GST_PAD_SRC,
464     GST_PAD_SOMETIMES,
465     GST_STATIC_CAPS_ANY);
466
467 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
468 GST_STATIC_PAD_TEMPLATE ("audio_%u",
469     GST_PAD_SRC,
470     GST_PAD_SOMETIMES,
471     GST_STATIC_CAPS_ANY);
472
473 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
474 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
475     GST_PAD_SRC,
476     GST_PAD_SOMETIMES,
477     GST_STATIC_CAPS_ANY);
478
479 #define gst_qtdemux_parent_class parent_class
480 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
481
482 static void gst_qtdemux_dispose (GObject * object);
483
484 static guint32
485 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
486     GstClockTime media_time);
487 static guint32
488 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
489     QtDemuxStream * str, gint64 media_offset);
490
491 #if 0
492 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
493 static GstIndex *gst_qtdemux_get_index (GstElement * element);
494 #endif
495 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
496     GstStateChange transition);
497 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
498 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
499     GstObject * parent, GstPadMode mode, gboolean active);
500
501 static void gst_qtdemux_loop (GstPad * pad);
502 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
503     GstBuffer * inbuf);
504 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
505     GstEvent * event);
506 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
507 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
508     QtDemuxStream * stream);
509 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
510     gboolean force);
511
512 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
513     const guint8 * buffer, guint length);
514 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
515     const guint8 * buffer, guint length);
516 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
517 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
518     GNode * udta);
519
520 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
521     QtDemuxStream * stream, GNode * esds, GstTagList * list);
522 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
523     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
524     gchar ** codec_name);
525 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
526     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
527     gchar ** codec_name);
528 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
529     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
530     gchar ** codec_name);
531 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
532     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
533     gchar ** codec_name);
534
535 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
536     QtDemuxStream * stream, guint32 n);
537 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
538 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
539     QtDemuxStream * stream);
540 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
541     QtDemuxStream * stream);
542 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
543 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
544 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
545     QtDemuxStream * stream);
546 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
547     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
548 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
549     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
550     GstClockTime * _start, GstClockTime * _stop);
551 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
552     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
553
554 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
555 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
556
557 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
558
559 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
560     QtDemuxStream * stream, guint sample_index);
561 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
562     const gchar * id);
563 static void qtdemux_gst_structure_free (GstStructure * gststructure);
564
565 static void
566 gst_qtdemux_class_init (GstQTDemuxClass * klass)
567 {
568   GObjectClass *gobject_class;
569   GstElementClass *gstelement_class;
570
571   gobject_class = (GObjectClass *) klass;
572   gstelement_class = (GstElementClass *) klass;
573
574   parent_class = g_type_class_peek_parent (klass);
575
576   gobject_class->dispose = gst_qtdemux_dispose;
577
578   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
579 #if 0
580   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
581   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
582 #endif
583
584   gst_tag_register_musicbrainz_tags ();
585
586   gst_element_class_add_static_pad_template (gstelement_class,
587       &gst_qtdemux_sink_template);
588   gst_element_class_add_static_pad_template (gstelement_class,
589       &gst_qtdemux_videosrc_template);
590   gst_element_class_add_static_pad_template (gstelement_class,
591       &gst_qtdemux_audiosrc_template);
592   gst_element_class_add_static_pad_template (gstelement_class,
593       &gst_qtdemux_subsrc_template);
594   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
595       "Codec/Demuxer",
596       "Demultiplex a QuickTime file into audio and video streams",
597       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
598
599   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
600
601 }
602
603 static void
604 gst_qtdemux_init (GstQTDemux * qtdemux)
605 {
606   qtdemux->sinkpad =
607       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
608   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
609   gst_pad_set_activatemode_function (qtdemux->sinkpad,
610       qtdemux_sink_activate_mode);
611   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
612   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
613   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
614
615   qtdemux->state = QTDEMUX_STATE_INITIAL;
616   qtdemux->pullbased = FALSE;
617   qtdemux->posted_redirect = FALSE;
618   qtdemux->neededbytes = 16;
619   qtdemux->todrop = 0;
620   qtdemux->adapter = gst_adapter_new ();
621   qtdemux->offset = 0;
622   qtdemux->first_mdat = -1;
623   qtdemux->got_moov = FALSE;
624   qtdemux->mdatoffset = -1;
625   qtdemux->mdatbuffer = NULL;
626   qtdemux->restoredata_buffer = NULL;
627   qtdemux->restoredata_offset = -1;
628   qtdemux->fragment_start = -1;
629   qtdemux->fragment_start_offset = -1;
630   qtdemux->media_caps = NULL;
631   qtdemux->exposed = FALSE;
632   qtdemux->mss_mode = FALSE;
633   qtdemux->pending_newsegment = NULL;
634   qtdemux->upstream_format_is_time = FALSE;
635   qtdemux->have_group_id = FALSE;
636   qtdemux->group_id = G_MAXUINT;
637   qtdemux->cenc_aux_info_offset = 0;
638   qtdemux->cenc_aux_info_sizes = NULL;
639   qtdemux->cenc_aux_sample_count = 0;
640   qtdemux->protection_system_ids = NULL;
641   g_queue_init (&qtdemux->protection_event_queue);
642   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
643   qtdemux->flowcombiner = gst_flow_combiner_new ();
644
645   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
646 }
647
648 static void
649 gst_qtdemux_dispose (GObject * object)
650 {
651   GstQTDemux *qtdemux = GST_QTDEMUX (object);
652
653   if (qtdemux->adapter) {
654     g_object_unref (G_OBJECT (qtdemux->adapter));
655     qtdemux->adapter = NULL;
656   }
657   gst_flow_combiner_free (qtdemux->flowcombiner);
658   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
659       NULL);
660   g_queue_clear (&qtdemux->protection_event_queue);
661
662   g_free (qtdemux->cenc_aux_info_sizes);
663   qtdemux->cenc_aux_info_sizes = NULL;
664
665   G_OBJECT_CLASS (parent_class)->dispose (object);
666 }
667
668 static void
669 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
670 {
671   if (qtdemux->posted_redirect) {
672     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
673         (_("This file contains no playable streams.")),
674         ("no known streams found, a redirect message has been posted"));
675   } else {
676     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
677         (_("This file contains no playable streams.")),
678         ("no known streams found"));
679   }
680 }
681
682 static GstBuffer *
683 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
684 {
685   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
686       mem, size, 0, size, mem, free_func);
687 }
688
689 static GstFlowReturn
690 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
691     GstBuffer ** buf)
692 {
693   GstFlowReturn flow;
694   GstMapInfo map;
695   gsize bsize;
696
697   if (G_UNLIKELY (size == 0)) {
698     GstFlowReturn ret;
699     GstBuffer *tmp = NULL;
700
701     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
702     if (ret != GST_FLOW_OK)
703       return ret;
704
705     gst_buffer_map (tmp, &map, GST_MAP_READ);
706     size = QT_UINT32 (map.data);
707     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
708
709     gst_buffer_unmap (tmp, &map);
710     gst_buffer_unref (tmp);
711   }
712
713   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
714   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
715     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
716       /* we're pulling header but already got most interesting bits,
717        * so never mind the rest (e.g. tags) (that much) */
718       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
719           size);
720       return GST_FLOW_EOS;
721     } else {
722       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
723           (_("This file is invalid and cannot be played.")),
724           ("atom has bogus size %" G_GUINT64_FORMAT, size));
725       return GST_FLOW_ERROR;
726     }
727   }
728
729   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
730
731   if (G_UNLIKELY (flow != GST_FLOW_OK))
732     return flow;
733
734   bsize = gst_buffer_get_size (*buf);
735   /* Catch short reads - we don't want any partial atoms */
736   if (G_UNLIKELY (bsize < size)) {
737     GST_WARNING_OBJECT (qtdemux,
738         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
739     gst_buffer_unref (*buf);
740     *buf = NULL;
741     return GST_FLOW_EOS;
742   }
743
744   return flow;
745 }
746
747 #if 1
748 static gboolean
749 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
750     GstFormat src_format, gint64 src_value, GstFormat dest_format,
751     gint64 * dest_value)
752 {
753   gboolean res = TRUE;
754   QtDemuxStream *stream = gst_pad_get_element_private (pad);
755   gint32 index;
756
757   if (stream->subtype != FOURCC_vide) {
758     res = FALSE;
759     goto done;
760   }
761
762   switch (src_format) {
763     case GST_FORMAT_TIME:
764       switch (dest_format) {
765         case GST_FORMAT_BYTES:{
766           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
767           if (-1 == index) {
768             res = FALSE;
769             goto done;
770           }
771
772           *dest_value = stream->samples[index].offset;
773
774           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
775               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
776               GST_TIME_ARGS (src_value), *dest_value);
777           break;
778         }
779         default:
780           res = FALSE;
781           break;
782       }
783       break;
784     case GST_FORMAT_BYTES:
785       switch (dest_format) {
786         case GST_FORMAT_TIME:{
787           index =
788               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
789               stream, src_value);
790
791           if (-1 == index) {
792             res = FALSE;
793             goto done;
794           }
795
796           *dest_value =
797               QTSTREAMTIME_TO_GSTTIME (stream,
798               stream->samples[index].timestamp);
799           GST_DEBUG_OBJECT (qtdemux,
800               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
801               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
802           break;
803         }
804         default:
805           res = FALSE;
806           break;
807       }
808       break;
809     default:
810       res = FALSE;
811       break;
812   }
813
814 done:
815   return res;
816 }
817 #endif
818
819 static gboolean
820 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
821 {
822   gboolean res = FALSE;
823
824   *duration = GST_CLOCK_TIME_NONE;
825
826   if (qtdemux->duration != 0 &&
827       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
828     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
829     res = TRUE;
830   } else {
831     *duration = GST_CLOCK_TIME_NONE;
832   }
833
834   return res;
835 }
836
837 static gboolean
838 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
839     GstQuery * query)
840 {
841   gboolean res = FALSE;
842   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
843
844   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
845
846   switch (GST_QUERY_TYPE (query)) {
847     case GST_QUERY_POSITION:{
848       GstFormat fmt;
849
850       gst_query_parse_position (query, &fmt, NULL);
851       if (fmt == GST_FORMAT_TIME
852           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
853         gst_query_set_position (query, GST_FORMAT_TIME,
854             qtdemux->segment.position);
855         res = TRUE;
856       }
857     }
858       break;
859     case GST_QUERY_DURATION:{
860       GstFormat fmt;
861
862       gst_query_parse_duration (query, &fmt, NULL);
863       if (fmt == GST_FORMAT_TIME) {
864         /* First try to query upstream */
865         res = gst_pad_query_default (pad, parent, query);
866         if (!res) {
867           GstClockTime duration;
868           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
869             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
870             res = TRUE;
871           }
872         }
873       }
874       break;
875     }
876     case GST_QUERY_CONVERT:{
877       GstFormat src_fmt, dest_fmt;
878       gint64 src_value, dest_value = 0;
879
880       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
881
882       res = gst_qtdemux_src_convert (qtdemux, pad,
883           src_fmt, src_value, dest_fmt, &dest_value);
884       if (res) {
885         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
886         res = TRUE;
887       }
888       break;
889     }
890     case GST_QUERY_FORMATS:
891       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
892       res = TRUE;
893       break;
894     case GST_QUERY_SEEKING:{
895       GstFormat fmt;
896       gboolean seekable;
897
898       /* try upstream first */
899       res = gst_pad_query_default (pad, parent, query);
900
901       if (!res) {
902         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
903         if (fmt == GST_FORMAT_TIME) {
904           GstClockTime duration;
905
906           gst_qtdemux_get_duration (qtdemux, &duration);
907           seekable = TRUE;
908           if (!qtdemux->pullbased) {
909             GstQuery *q;
910
911             /* we might be able with help from upstream */
912             seekable = FALSE;
913             q = gst_query_new_seeking (GST_FORMAT_BYTES);
914             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
915               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
916               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
917             }
918             gst_query_unref (q);
919           }
920           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
921           res = TRUE;
922         }
923       }
924       break;
925     }
926     case GST_QUERY_SEGMENT:
927     {
928       GstFormat format;
929       gint64 start, stop;
930
931       format = qtdemux->segment.format;
932
933       start =
934           gst_segment_to_stream_time (&qtdemux->segment, format,
935           qtdemux->segment.start);
936       if ((stop = qtdemux->segment.stop) == -1)
937         stop = qtdemux->segment.duration;
938       else
939         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
940
941       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
942       res = TRUE;
943       break;
944     }
945     default:
946       res = gst_pad_query_default (pad, parent, query);
947       break;
948   }
949
950   return res;
951 }
952
953 static void
954 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
955 {
956   if (G_LIKELY (stream->pad)) {
957     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
958         GST_DEBUG_PAD_NAME (stream->pad));
959
960     if (G_UNLIKELY (stream->pending_tags)) {
961       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
962           stream->pending_tags);
963       gst_pad_push_event (stream->pad,
964           gst_event_new_tag (stream->pending_tags));
965       stream->pending_tags = NULL;
966     }
967
968     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
969       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
970           qtdemux->tag_list);
971       gst_pad_push_event (stream->pad,
972           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
973       stream->send_global_tags = FALSE;
974     }
975   }
976 }
977
978 /* push event on all source pads; takes ownership of the event */
979 static void
980 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
981 {
982   guint n;
983   gboolean has_valid_stream = FALSE;
984   GstEventType etype = GST_EVENT_TYPE (event);
985
986   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
987       GST_EVENT_TYPE_NAME (event));
988
989   for (n = 0; n < qtdemux->n_streams; n++) {
990     GstPad *pad;
991     QtDemuxStream *stream = qtdemux->streams[n];
992     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
993
994     if ((pad = stream->pad)) {
995       has_valid_stream = TRUE;
996
997       if (etype == GST_EVENT_EOS) {
998         /* let's not send twice */
999         if (stream->sent_eos)
1000           continue;
1001         stream->sent_eos = TRUE;
1002       }
1003
1004       gst_pad_push_event (pad, gst_event_ref (event));
1005     }
1006   }
1007
1008   gst_event_unref (event);
1009
1010   /* if it is EOS and there are no pads, post an error */
1011   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1012     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1013   }
1014 }
1015
1016 /* push a pending newsegment event, if any from the streaming thread */
1017 static void
1018 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1019 {
1020   if (qtdemux->pending_newsegment) {
1021     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1022     qtdemux->pending_newsegment = NULL;
1023   }
1024 }
1025
1026 typedef struct
1027 {
1028   guint64 media_time;
1029 } FindData;
1030
1031 static gint
1032 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1033 {
1034   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1035     return 1;
1036   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1037     return 0;
1038
1039   return -1;
1040 }
1041
1042 /* find the index of the sample that includes the data for @media_time using a
1043  * binary search.  Only to be called in optimized cases of linear search below.
1044  *
1045  * Returns the index of the sample.
1046  */
1047 static guint32
1048 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1049     guint64 media_time)
1050 {
1051   QtDemuxSample *result;
1052   guint32 index;
1053
1054   /* convert media_time to mov format */
1055   media_time =
1056       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1057
1058   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1059       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1060       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1061
1062   if (G_LIKELY (result))
1063     index = result - str->samples;
1064   else
1065     index = 0;
1066
1067   return index;
1068 }
1069
1070
1071
1072 /* find the index of the sample that includes the data for @media_offset using a
1073  * linear search
1074  *
1075  * Returns the index of the sample.
1076  */
1077 static guint32
1078 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1079     QtDemuxStream * str, gint64 media_offset)
1080 {
1081   QtDemuxSample *result = str->samples;
1082   guint32 index = 0;
1083
1084   if (result == NULL || str->n_samples == 0)
1085     return -1;
1086
1087   if (media_offset == result->offset)
1088     return index;
1089
1090   result++;
1091   while (index < str->n_samples - 1) {
1092     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1093       goto parse_failed;
1094
1095     if (media_offset < result->offset)
1096       break;
1097
1098     index++;
1099     result++;
1100   }
1101   return index;
1102
1103   /* ERRORS */
1104 parse_failed:
1105   {
1106     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1107     return -1;
1108   }
1109 }
1110
1111 /* find the index of the sample that includes the data for @media_time using a
1112  * linear search, and keeping in mind that not all samples may have been parsed
1113  * yet.  If possible, it will delegate to binary search.
1114  *
1115  * Returns the index of the sample.
1116  */
1117 static guint32
1118 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1119     GstClockTime media_time)
1120 {
1121   guint32 index = 0;
1122   guint64 mov_time;
1123   QtDemuxSample *sample;
1124
1125   /* convert media_time to mov format */
1126   mov_time =
1127       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1128
1129   sample = str->samples;
1130   if (mov_time == sample->timestamp + sample->pts_offset)
1131     return index;
1132
1133   /* use faster search if requested time in already parsed range */
1134   sample = str->samples + str->stbl_index;
1135   if (str->stbl_index >= 0 &&
1136       mov_time <= (sample->timestamp + sample->pts_offset))
1137     return gst_qtdemux_find_index (qtdemux, str, media_time);
1138
1139   while (index < str->n_samples - 1) {
1140     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1141       goto parse_failed;
1142
1143     sample = str->samples + index + 1;
1144     if (mov_time < (sample->timestamp + sample->pts_offset))
1145       break;
1146
1147     index++;
1148   }
1149   return index;
1150
1151   /* ERRORS */
1152 parse_failed:
1153   {
1154     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1155     return -1;
1156   }
1157 }
1158
1159 /* find the index of the keyframe needed to decode the sample at @index
1160  * of stream @str, or of a subsequent keyframe (depending on @next)
1161  *
1162  * Returns the index of the keyframe.
1163  */
1164 static guint32
1165 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1166     guint32 index, gboolean next)
1167 {
1168   guint32 new_index = index;
1169
1170   if (index >= str->n_samples) {
1171     new_index = str->n_samples;
1172     goto beach;
1173   }
1174
1175   /* all keyframes, return index */
1176   if (str->all_keyframe) {
1177     new_index = index;
1178     goto beach;
1179   }
1180
1181   /* else search until we have a keyframe */
1182   while (new_index < str->n_samples) {
1183     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1184       goto parse_failed;
1185
1186     if (str->samples[new_index].keyframe)
1187       break;
1188
1189     if (new_index == 0)
1190       break;
1191
1192     if (next)
1193       new_index++;
1194     else
1195       new_index--;
1196   }
1197
1198   if (new_index == str->n_samples) {
1199     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1200     new_index = -1;
1201   }
1202
1203 beach:
1204   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1205       "gave %u", next ? "after" : "before", index, new_index);
1206
1207   return new_index;
1208
1209   /* ERRORS */
1210 parse_failed:
1211   {
1212     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1213     return -1;
1214   }
1215 }
1216
1217 /* find the segment for @time_position for @stream
1218  *
1219  * Returns the index of the segment containing @time_position.
1220  * Returns the last segment and sets the @eos variable to TRUE
1221  * if the time is beyond the end. @eos may be NULL
1222  */
1223 static guint32
1224 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1225     GstClockTime time_position)
1226 {
1227   gint i;
1228   guint32 seg_idx;
1229
1230   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1231       GST_TIME_ARGS (time_position));
1232
1233   seg_idx = -1;
1234   for (i = 0; i < stream->n_segments; i++) {
1235     QtDemuxSegment *segment = &stream->segments[i];
1236
1237     GST_LOG_OBJECT (stream->pad,
1238         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1239         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1240
1241     /* For the last segment we include stop_time in the last segment */
1242     if (i < stream->n_segments - 1) {
1243       if (segment->time <= time_position && time_position < segment->stop_time) {
1244         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1245         seg_idx = i;
1246         break;
1247       }
1248     } else {
1249       /* Last segment always matches */
1250       seg_idx = i;
1251       break;
1252     }
1253   }
1254   return seg_idx;
1255 }
1256
1257 /* move the stream @str to the sample position @index.
1258  *
1259  * Updates @str->sample_index and marks discontinuity if needed.
1260  */
1261 static void
1262 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1263     guint32 index)
1264 {
1265   /* no change needed */
1266   if (index == str->sample_index)
1267     return;
1268
1269   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1270       str->n_samples);
1271
1272   /* position changed, we have a discont */
1273   str->sample_index = index;
1274   str->offset_in_sample = 0;
1275   /* Each time we move in the stream we store the position where we are
1276    * starting from */
1277   str->from_sample = index;
1278   str->discont = TRUE;
1279 }
1280
1281 static void
1282 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1283     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1284 {
1285   guint64 min_offset;
1286   gint64 min_byte_offset = -1;
1287   gint n;
1288
1289   min_offset = desired_time;
1290
1291   /* for each stream, find the index of the sample in the segment
1292    * and move back to the previous keyframe. */
1293   for (n = 0; n < qtdemux->n_streams; n++) {
1294     QtDemuxStream *str;
1295     guint32 index, kindex;
1296     guint32 seg_idx;
1297     GstClockTime media_start;
1298     GstClockTime media_time;
1299     GstClockTime seg_time;
1300     QtDemuxSegment *seg;
1301     gboolean empty_segment = FALSE;
1302
1303     str = qtdemux->streams[n];
1304
1305     if (str->sparse && !use_sparse)
1306       continue;
1307
1308     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1309     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1310
1311     /* get segment and time in the segment */
1312     seg = &str->segments[seg_idx];
1313     seg_time = (desired_time - seg->time) * seg->rate;
1314
1315     while (QTSEGMENT_IS_EMPTY (seg)) {
1316       seg_time = 0;
1317       empty_segment = TRUE;
1318       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1319           seg_idx);
1320       seg_idx++;
1321       if (seg_idx == str->n_segments)
1322         break;
1323       seg = &str->segments[seg_idx];
1324     }
1325
1326     if (seg_idx == str->n_segments) {
1327       /* FIXME track shouldn't have the last segment as empty, but if it
1328        * happens we better handle it */
1329       continue;
1330     }
1331
1332     /* get the media time in the segment */
1333     media_start = seg->media_start + seg_time;
1334
1335     /* get the index of the sample with media time */
1336     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1337     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1338         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1339         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1340         empty_segment);
1341
1342     /* shift to next frame if we are looking for next keyframe */
1343     if (next && QTSAMPLE_PTS (str, &str->samples[index]) < media_start &&
1344         index < str->stbl_index)
1345       index++;
1346
1347     if (!empty_segment) {
1348       /* find previous keyframe */
1349       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1350
1351       /* we will settle for one before if none found after */
1352       if (next && kindex == -1)
1353         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1354
1355       /* if the keyframe is at a different position, we need to update the
1356        * requested seek time */
1357       if (index != kindex) {
1358         index = kindex;
1359
1360         /* get timestamp of keyframe */
1361         media_time = QTSAMPLE_PTS (str, &str->samples[kindex]);
1362         GST_DEBUG_OBJECT (qtdemux,
1363             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1364             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1365             str->samples[kindex].offset);
1366
1367         /* keyframes in the segment get a chance to change the
1368          * desired_offset. keyframes out of the segment are
1369          * ignored. */
1370         if (media_time >= seg->media_start) {
1371           GstClockTime seg_time;
1372
1373           /* this keyframe is inside the segment, convert back to
1374            * segment time */
1375           seg_time = (media_time - seg->media_start) + seg->time;
1376           if ((!next && (seg_time < min_offset)) ||
1377               (next && (seg_time > min_offset)))
1378             min_offset = seg_time;
1379         }
1380       }
1381     }
1382
1383     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1384       min_byte_offset = str->samples[index].offset;
1385   }
1386
1387   if (key_time)
1388     *key_time = min_offset;
1389   if (key_offset)
1390     *key_offset = min_byte_offset;
1391 }
1392
1393 static gboolean
1394 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1395     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1396 {
1397   gboolean res;
1398
1399   g_return_val_if_fail (format != NULL, FALSE);
1400   g_return_val_if_fail (cur != NULL, FALSE);
1401   g_return_val_if_fail (stop != NULL, FALSE);
1402
1403   if (*format == GST_FORMAT_TIME)
1404     return TRUE;
1405
1406   res = TRUE;
1407   if (cur_type != GST_SEEK_TYPE_NONE)
1408     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1409   if (res && stop_type != GST_SEEK_TYPE_NONE)
1410     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1411
1412   if (res)
1413     *format = GST_FORMAT_TIME;
1414
1415   return res;
1416 }
1417
1418 /* perform seek in push based mode:
1419    find BYTE position to move to based on time and delegate to upstream
1420 */
1421 static gboolean
1422 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1423 {
1424   gdouble rate;
1425   GstFormat format;
1426   GstSeekFlags flags;
1427   GstSeekType cur_type, stop_type;
1428   gint64 cur, stop, key_cur;
1429   gboolean res;
1430   gint64 byte_cur;
1431   gint64 original_stop;
1432   guint32 seqnum;
1433
1434   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1435
1436   gst_event_parse_seek (event, &rate, &format, &flags,
1437       &cur_type, &cur, &stop_type, &stop);
1438   seqnum = gst_event_get_seqnum (event);
1439
1440   /* only forward streaming and seeking is possible */
1441   if (rate <= 0)
1442     goto unsupported_seek;
1443
1444   /* convert to TIME if needed and possible */
1445   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1446           stop_type, &stop))
1447     goto no_format;
1448
1449   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1450    * the original stop position to use when upstream pushes the new segment
1451    * for this seek */
1452   original_stop = stop;
1453   stop = -1;
1454
1455   /* find reasonable corresponding BYTE position,
1456    * also try to mind about keyframes, since we can not go back a bit for them
1457    * later on */
1458   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1459    * mostly just work, but let's not yet boldly go there  ... */
1460   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1461
1462   if (byte_cur == -1)
1463     goto abort_seek;
1464
1465   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1466       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1467       stop);
1468
1469   GST_OBJECT_LOCK (qtdemux);
1470   qtdemux->seek_offset = byte_cur;
1471   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1472     qtdemux->push_seek_start = cur;
1473   } else {
1474     qtdemux->push_seek_start = key_cur;
1475   }
1476
1477   if (stop_type == GST_SEEK_TYPE_NONE) {
1478     qtdemux->push_seek_stop = qtdemux->segment.stop;
1479   } else {
1480     qtdemux->push_seek_stop = original_stop;
1481   }
1482   GST_OBJECT_UNLOCK (qtdemux);
1483
1484   /* BYTE seek event */
1485   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1486       stop_type, stop);
1487   gst_event_set_seqnum (event, seqnum);
1488   res = gst_pad_push_event (qtdemux->sinkpad, event);
1489
1490   return res;
1491
1492   /* ERRORS */
1493 abort_seek:
1494   {
1495     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1496         "seek aborted.");
1497     return FALSE;
1498   }
1499 unsupported_seek:
1500   {
1501     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1502     return FALSE;
1503   }
1504 no_format:
1505   {
1506     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1507     return FALSE;
1508   }
1509 }
1510
1511 /* perform the seek.
1512  *
1513  * We set all segment_indexes in the streams to unknown and
1514  * adjust the time_position to the desired position. this is enough
1515  * to trigger a segment switch in the streaming thread to start
1516  * streaming from the desired position.
1517  *
1518  * Keyframe seeking is a little more complicated when dealing with
1519  * segments. Ideally we want to move to the previous keyframe in
1520  * the segment but there might not be a keyframe in the segment. In
1521  * fact, none of the segments could contain a keyframe. We take a
1522  * practical approach: seek to the previous keyframe in the segment,
1523  * if there is none, seek to the beginning of the segment.
1524  *
1525  * Called with STREAM_LOCK
1526  */
1527 static gboolean
1528 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1529     guint32 seqnum, GstSeekFlags flags)
1530 {
1531   gint64 desired_offset;
1532   gint n;
1533
1534   desired_offset = segment->position;
1535
1536   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1537       GST_TIME_ARGS (desired_offset));
1538
1539   /* may not have enough fragmented info to do this adjustment,
1540    * and we can't scan (and probably should not) at this time with
1541    * possibly flushing upstream */
1542   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1543     gint64 min_offset;
1544     gboolean next, before, after;
1545
1546     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1547     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1548     next = after && !before;
1549     if (segment->rate < 0)
1550       next = !next;
1551
1552     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1553         NULL);
1554     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1555         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1556     desired_offset = min_offset;
1557   }
1558
1559   /* and set all streams to the final position */
1560   gst_flow_combiner_reset (qtdemux->flowcombiner);
1561   qtdemux->segment_seqnum = seqnum;
1562   for (n = 0; n < qtdemux->n_streams; n++) {
1563     QtDemuxStream *stream = qtdemux->streams[n];
1564
1565     stream->time_position = desired_offset;
1566     stream->accumulated_base = 0;
1567     stream->sample_index = -1;
1568     stream->offset_in_sample = 0;
1569     stream->segment_index = -1;
1570     stream->sent_eos = FALSE;
1571
1572     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1573       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1574   }
1575   segment->position = desired_offset;
1576   segment->time = desired_offset;
1577   if (segment->rate >= 0) {
1578     segment->start = desired_offset;
1579
1580     /* we stop at the end */
1581     if (segment->stop == -1)
1582       segment->stop = segment->duration;
1583   } else {
1584     segment->stop = desired_offset;
1585   }
1586
1587   if (qtdemux->fragmented)
1588     qtdemux->fragmented_seek_pending = TRUE;
1589
1590   return TRUE;
1591 }
1592
1593 /* do a seek in pull based mode */
1594 static gboolean
1595 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1596 {
1597   gdouble rate;
1598   GstFormat format;
1599   GstSeekFlags flags;
1600   GstSeekType cur_type, stop_type;
1601   gint64 cur, stop;
1602   gboolean flush;
1603   gboolean update;
1604   GstSegment seeksegment;
1605   guint32 seqnum = 0;
1606   GstEvent *flush_event;
1607
1608   if (event) {
1609     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1610
1611     gst_event_parse_seek (event, &rate, &format, &flags,
1612         &cur_type, &cur, &stop_type, &stop);
1613     seqnum = gst_event_get_seqnum (event);
1614
1615     /* we have to have a format as the segment format. Try to convert
1616      * if not. */
1617     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1618             stop_type, &stop))
1619       goto no_format;
1620
1621     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1622   } else {
1623     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1624     flags = 0;
1625   }
1626
1627   flush = flags & GST_SEEK_FLAG_FLUSH;
1628
1629   /* stop streaming, either by flushing or by pausing the task */
1630   if (flush) {
1631     flush_event = gst_event_new_flush_start ();
1632     if (seqnum)
1633       gst_event_set_seqnum (flush_event, seqnum);
1634     /* unlock upstream pull_range */
1635     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1636     /* make sure out loop function exits */
1637     gst_qtdemux_push_event (qtdemux, flush_event);
1638   } else {
1639     /* non flushing seek, pause the task */
1640     gst_pad_pause_task (qtdemux->sinkpad);
1641   }
1642
1643   /* wait for streaming to finish */
1644   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1645
1646   /* copy segment, we need this because we still need the old
1647    * segment when we close the current segment. */
1648   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1649
1650   if (event) {
1651     /* configure the segment with the seek variables */
1652     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1653     gst_segment_do_seek (&seeksegment, rate, format, flags,
1654         cur_type, cur, stop_type, stop, &update);
1655   }
1656
1657   /* now do the seek, this actually never returns FALSE */
1658   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1659
1660   /* prepare for streaming again */
1661   if (flush) {
1662     flush_event = gst_event_new_flush_stop (TRUE);
1663     if (seqnum)
1664       gst_event_set_seqnum (flush_event, seqnum);
1665
1666     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1667     gst_qtdemux_push_event (qtdemux, flush_event);
1668   }
1669
1670   /* commit the new segment */
1671   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1672
1673   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1674     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1675         qtdemux->segment.format, qtdemux->segment.position);
1676     if (seqnum)
1677       gst_message_set_seqnum (msg, seqnum);
1678     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1679   }
1680
1681   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1682   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1683       qtdemux->sinkpad, NULL);
1684
1685   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1686
1687   return TRUE;
1688
1689   /* ERRORS */
1690 no_format:
1691   {
1692     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1693     return FALSE;
1694   }
1695 }
1696
1697 static gboolean
1698 qtdemux_ensure_index (GstQTDemux * qtdemux)
1699 {
1700   guint i;
1701
1702   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1703
1704   /* Build complete index */
1705   for (i = 0; i < qtdemux->n_streams; i++) {
1706     QtDemuxStream *stream = qtdemux->streams[i];
1707
1708     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1709       goto parse_error;
1710   }
1711   return TRUE;
1712
1713   /* ERRORS */
1714 parse_error:
1715   {
1716     GST_LOG_OBJECT (qtdemux,
1717         "Building complete index of stream %u for seeking failed!", i);
1718     return FALSE;
1719   }
1720 }
1721
1722 static gboolean
1723 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1724     GstEvent * event)
1725 {
1726   gboolean res = TRUE;
1727   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1728
1729   switch (GST_EVENT_TYPE (event)) {
1730     case GST_EVENT_SEEK:
1731     {
1732 #ifndef GST_DISABLE_GST_DEBUG
1733       GstClockTime ts = gst_util_get_timestamp ();
1734 #endif
1735
1736       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1737         /* seek should be handled by upstream, we might need to re-download fragments */
1738         GST_DEBUG_OBJECT (qtdemux,
1739             "let upstream handle seek for fragmented playback");
1740         goto upstream;
1741       }
1742
1743       /* Build complete index for seeking;
1744        * if not a fragmented file at least */
1745       if (!qtdemux->fragmented)
1746         if (!qtdemux_ensure_index (qtdemux))
1747           goto index_failed;
1748 #ifndef GST_DISABLE_GST_DEBUG
1749       ts = gst_util_get_timestamp () - ts;
1750       GST_INFO_OBJECT (qtdemux,
1751           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1752 #endif
1753     }
1754       if (qtdemux->pullbased) {
1755         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1756       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1757         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1758         res = TRUE;
1759       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1760           && !qtdemux->fragmented) {
1761         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1762       } else {
1763         GST_DEBUG_OBJECT (qtdemux,
1764             "ignoring seek in push mode in current state");
1765         res = FALSE;
1766       }
1767       gst_event_unref (event);
1768       break;
1769     default:
1770     upstream:
1771       res = gst_pad_event_default (pad, parent, event);
1772       break;
1773   }
1774
1775 done:
1776   return res;
1777
1778   /* ERRORS */
1779 index_failed:
1780   {
1781     GST_ERROR_OBJECT (qtdemux, "Index failed");
1782     gst_event_unref (event);
1783     res = FALSE;
1784     goto done;
1785   }
1786 }
1787
1788 /* stream/index return sample that is min/max w.r.t. byte position,
1789  * time is min/max w.r.t. time of samples,
1790  * the latter need not be time of the former sample */
1791 static void
1792 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1793     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1794 {
1795   gint i, n, index;
1796   gint64 time, min_time;
1797   QtDemuxStream *stream;
1798
1799   min_time = -1;
1800   stream = NULL;
1801   index = -1;
1802
1803   for (n = 0; n < qtdemux->n_streams; ++n) {
1804     QtDemuxStream *str;
1805     gint inc;
1806     gboolean set_sample;
1807
1808     str = qtdemux->streams[n];
1809     set_sample = !set;
1810
1811     if (fw) {
1812       i = 0;
1813       inc = 1;
1814     } else {
1815       i = str->n_samples - 1;
1816       inc = -1;
1817     }
1818
1819     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1820       if (str->samples[i].size == 0)
1821         continue;
1822
1823       if (fw && (str->samples[i].offset < byte_pos))
1824         continue;
1825
1826       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1827         continue;
1828
1829       /* move stream to first available sample */
1830       if (set) {
1831         gst_qtdemux_move_stream (qtdemux, str, i);
1832         set_sample = TRUE;
1833       }
1834
1835       /* avoid index from sparse streams since they might be far away */
1836       if (!str->sparse) {
1837         /* determine min/max time */
1838         time = QTSAMPLE_PTS (str, &str->samples[i]);
1839         if (min_time == -1 || (!fw && time > min_time) ||
1840             (fw && time < min_time)) {
1841           min_time = time;
1842         }
1843
1844         /* determine stream with leading sample, to get its position */
1845         if (!stream ||
1846             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1847             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1848           stream = str;
1849           index = i;
1850         }
1851       }
1852       break;
1853     }
1854
1855     /* no sample for this stream, mark eos */
1856     if (!set_sample)
1857       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1858   }
1859
1860   if (_time)
1861     *_time = min_time;
1862   if (_stream)
1863     *_stream = stream;
1864   if (_index)
1865     *_index = index;
1866 }
1867
1868 static QtDemuxStream *
1869 _create_stream (void)
1870 {
1871   QtDemuxStream *stream;
1872
1873   stream = g_new0 (QtDemuxStream, 1);
1874   /* new streams always need a discont */
1875   stream->discont = TRUE;
1876   /* we enable clipping for raw audio/video streams */
1877   stream->need_clip = FALSE;
1878   stream->need_process = FALSE;
1879   stream->segment_index = -1;
1880   stream->time_position = 0;
1881   stream->sample_index = -1;
1882   stream->offset_in_sample = 0;
1883   stream->new_stream = TRUE;
1884   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1885   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1886   stream->protected = FALSE;
1887   stream->protection_scheme_type = 0;
1888   stream->protection_scheme_version = 0;
1889   stream->protection_scheme_info = NULL;
1890   stream->n_samples_moof = 0;
1891   stream->duration_moof = 0;
1892   stream->duration_last_moof = 0;
1893   stream->alignment = 1;
1894   g_queue_init (&stream->protection_scheme_event_queue);
1895   return stream;
1896 }
1897
1898 static gboolean
1899 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1900 {
1901   GstStructure *structure;
1902   const gchar *variant;
1903   const GstCaps *mediacaps = NULL;
1904
1905   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1906
1907   structure = gst_caps_get_structure (caps, 0);
1908   variant = gst_structure_get_string (structure, "variant");
1909
1910   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1911     QtDemuxStream *stream;
1912     const GValue *value;
1913
1914     demux->fragmented = TRUE;
1915     demux->mss_mode = TRUE;
1916
1917     if (demux->n_streams > 1) {
1918       /* can't do this, we can only renegotiate for another mss format */
1919       return FALSE;
1920     }
1921
1922     value = gst_structure_get_value (structure, "media-caps");
1923     /* create stream */
1924     if (value) {
1925       const GValue *timescale_v;
1926
1927       /* TODO update when stream changes during playback */
1928
1929       if (demux->n_streams == 0) {
1930         stream = _create_stream ();
1931         demux->streams[demux->n_streams] = stream;
1932         demux->n_streams = 1;
1933       } else {
1934         stream = demux->streams[0];
1935       }
1936
1937       timescale_v = gst_structure_get_value (structure, "timescale");
1938       if (timescale_v) {
1939         stream->timescale = g_value_get_uint64 (timescale_v);
1940       } else {
1941         /* default mss timescale */
1942         stream->timescale = 10000000;
1943       }
1944       demux->timescale = stream->timescale;
1945
1946       mediacaps = gst_value_get_caps (value);
1947       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1948         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1949             mediacaps);
1950         stream->new_caps = TRUE;
1951       }
1952       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1953       structure = gst_caps_get_structure (mediacaps, 0);
1954       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1955         stream->subtype = FOURCC_vide;
1956
1957         gst_structure_get_int (structure, "width", &stream->width);
1958         gst_structure_get_int (structure, "height", &stream->height);
1959         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1960             &stream->fps_d);
1961       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1962         gint rate = 0;
1963         stream->subtype = FOURCC_soun;
1964         gst_structure_get_int (structure, "channels", &stream->n_channels);
1965         gst_structure_get_int (structure, "rate", &rate);
1966         stream->rate = rate;
1967       }
1968     }
1969     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1970   } else {
1971     demux->mss_mode = FALSE;
1972   }
1973
1974   return TRUE;
1975 }
1976
1977 static void
1978 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1979 {
1980   gint n;
1981
1982   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1983   gst_pad_stop_task (qtdemux->sinkpad);
1984
1985   if (hard || qtdemux->upstream_format_is_time) {
1986     qtdemux->state = QTDEMUX_STATE_INITIAL;
1987     qtdemux->neededbytes = 16;
1988     qtdemux->todrop = 0;
1989     qtdemux->pullbased = FALSE;
1990     qtdemux->posted_redirect = FALSE;
1991     qtdemux->first_mdat = -1;
1992     qtdemux->header_size = 0;
1993     qtdemux->mdatoffset = -1;
1994     qtdemux->restoredata_offset = -1;
1995     if (qtdemux->mdatbuffer)
1996       gst_buffer_unref (qtdemux->mdatbuffer);
1997     if (qtdemux->restoredata_buffer)
1998       gst_buffer_unref (qtdemux->restoredata_buffer);
1999     qtdemux->mdatbuffer = NULL;
2000     qtdemux->restoredata_buffer = NULL;
2001     qtdemux->mdatleft = 0;
2002     if (qtdemux->comp_brands)
2003       gst_buffer_unref (qtdemux->comp_brands);
2004     qtdemux->comp_brands = NULL;
2005     qtdemux->last_moov_offset = -1;
2006     if (qtdemux->moov_node_compressed) {
2007       g_node_destroy (qtdemux->moov_node_compressed);
2008       if (qtdemux->moov_node)
2009         g_free (qtdemux->moov_node->data);
2010     }
2011     qtdemux->moov_node_compressed = NULL;
2012     if (qtdemux->moov_node)
2013       g_node_destroy (qtdemux->moov_node);
2014     qtdemux->moov_node = NULL;
2015     if (qtdemux->tag_list)
2016       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2017     qtdemux->tag_list = NULL;
2018 #if 0
2019     if (qtdemux->element_index)
2020       gst_object_unref (qtdemux->element_index);
2021     qtdemux->element_index = NULL;
2022 #endif
2023     qtdemux->major_brand = 0;
2024     if (qtdemux->pending_newsegment)
2025       gst_event_unref (qtdemux->pending_newsegment);
2026     qtdemux->pending_newsegment = NULL;
2027     qtdemux->upstream_format_is_time = FALSE;
2028     qtdemux->upstream_seekable = FALSE;
2029     qtdemux->upstream_size = 0;
2030
2031     qtdemux->fragment_start = -1;
2032     qtdemux->fragment_start_offset = -1;
2033     qtdemux->duration = 0;
2034     qtdemux->moof_offset = 0;
2035     qtdemux->chapters_track_id = 0;
2036     qtdemux->have_group_id = FALSE;
2037     qtdemux->group_id = G_MAXUINT;
2038
2039     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2040         NULL);
2041     g_queue_clear (&qtdemux->protection_event_queue);
2042   }
2043   qtdemux->offset = 0;
2044   gst_adapter_clear (qtdemux->adapter);
2045   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2046   qtdemux->segment_seqnum = 0;
2047
2048   if (hard) {
2049     for (n = 0; n < qtdemux->n_streams; n++) {
2050       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2051       qtdemux->streams[n] = NULL;
2052     }
2053     qtdemux->n_streams = 0;
2054     qtdemux->n_video_streams = 0;
2055     qtdemux->n_audio_streams = 0;
2056     qtdemux->n_sub_streams = 0;
2057     qtdemux->exposed = FALSE;
2058     qtdemux->fragmented = FALSE;
2059     qtdemux->mss_mode = FALSE;
2060     gst_caps_replace (&qtdemux->media_caps, NULL);
2061     qtdemux->timescale = 0;
2062     qtdemux->got_moov = FALSE;
2063     if (qtdemux->protection_system_ids) {
2064       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2065       qtdemux->protection_system_ids = NULL;
2066     }
2067   } else if (qtdemux->mss_mode) {
2068     gst_flow_combiner_reset (qtdemux->flowcombiner);
2069     for (n = 0; n < qtdemux->n_streams; n++)
2070       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2071   } else {
2072     gst_flow_combiner_reset (qtdemux->flowcombiner);
2073     for (n = 0; n < qtdemux->n_streams; n++) {
2074       qtdemux->streams[n]->sent_eos = FALSE;
2075       qtdemux->streams[n]->time_position = 0;
2076       qtdemux->streams[n]->accumulated_base = 0;
2077     }
2078     if (!qtdemux->pending_newsegment) {
2079       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2080       if (qtdemux->segment_seqnum)
2081         gst_event_set_seqnum (qtdemux->pending_newsegment,
2082             qtdemux->segment_seqnum);
2083     }
2084   }
2085 }
2086
2087
2088 /* Maps the @segment to the qt edts internal segments and pushes
2089  * the correspnding segment event.
2090  *
2091  * If it ends up being at a empty segment, a gap will be pushed and the next
2092  * edts segment will be activated in sequence.
2093  *
2094  * To be used in push-mode only */
2095 static void
2096 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2097 {
2098   gint n, i;
2099
2100   for (n = 0; n < qtdemux->n_streams; n++) {
2101     QtDemuxStream *stream = qtdemux->streams[n];
2102
2103     stream->time_position = segment->start;
2104
2105     /* in push mode we should be guaranteed that we will have empty segments
2106      * at the beginning and then one segment after, other scenarios are not
2107      * supported and are discarded when parsing the edts */
2108     for (i = 0; i < stream->n_segments; i++) {
2109       if (stream->segments[i].stop_time > segment->start) {
2110         gst_qtdemux_activate_segment (qtdemux, stream, i,
2111             stream->time_position);
2112         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2113           /* push the empty segment and move to the next one */
2114           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2115               stream->time_position);
2116           continue;
2117         }
2118
2119         g_assert (i == stream->n_segments - 1);
2120       }
2121     }
2122   }
2123 }
2124
2125 static gboolean
2126 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2127     GstEvent * event)
2128 {
2129   GstQTDemux *demux = GST_QTDEMUX (parent);
2130   gboolean res = TRUE;
2131
2132   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2133
2134   switch (GST_EVENT_TYPE (event)) {
2135     case GST_EVENT_SEGMENT:
2136     {
2137       gint64 offset = 0;
2138       QtDemuxStream *stream;
2139       gint idx;
2140       GstSegment segment;
2141
2142       /* some debug output */
2143       gst_event_copy_segment (event, &segment);
2144       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2145           &segment);
2146
2147       /* erase any previously set segment */
2148       gst_event_replace (&demux->pending_newsegment, NULL);
2149
2150       if (segment.format == GST_FORMAT_TIME) {
2151         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2152         gst_event_replace (&demux->pending_newsegment, event);
2153         demux->upstream_format_is_time = TRUE;
2154       } else {
2155         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2156             "not in time format");
2157
2158         /* chain will send initial newsegment after pads have been added */
2159         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2160           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2161           goto exit;
2162         }
2163       }
2164
2165       /* check if this matches a time seek we received previously
2166        * FIXME for backwards compatibility reasons we use the
2167        * seek_offset here to compare. In the future we might want to
2168        * change this to use the seqnum as it uniquely should identify
2169        * the segment that corresponds to the seek. */
2170       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2171           ", received segment offset %" G_GINT64_FORMAT,
2172           demux->seek_offset, segment.start);
2173       if (segment.format == GST_FORMAT_BYTES
2174           && demux->seek_offset == segment.start) {
2175         GST_OBJECT_LOCK (demux);
2176         offset = segment.start;
2177
2178         segment.format = GST_FORMAT_TIME;
2179         segment.start = demux->push_seek_start;
2180         segment.stop = demux->push_seek_stop;
2181         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2182             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2183             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2184         GST_OBJECT_UNLOCK (demux);
2185       }
2186
2187       /* we only expect a BYTE segment, e.g. following a seek */
2188       if (segment.format == GST_FORMAT_BYTES) {
2189         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2190           offset = segment.start;
2191
2192           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2193               NULL, (gint64 *) & segment.start);
2194           if ((gint64) segment.start < 0)
2195             segment.start = 0;
2196         }
2197         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2198           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2199               NULL, (gint64 *) & segment.stop);
2200           /* keyframe seeking should already arrange for start >= stop,
2201            * but make sure in other rare cases */
2202           segment.stop = MAX (segment.stop, segment.start);
2203         }
2204       } else if (segment.format == GST_FORMAT_TIME) {
2205         /* push all data on the adapter before starting this
2206          * new segment */
2207         gst_qtdemux_process_adapter (demux, TRUE);
2208       } else {
2209         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2210         goto exit;
2211       }
2212
2213       /* We shouldn't modify upstream driven TIME FORMAT segment */
2214       if (!demux->upstream_format_is_time) {
2215         /* accept upstream's notion of segment and distribute along */
2216         segment.format = GST_FORMAT_TIME;
2217         segment.position = segment.time = segment.start;
2218         segment.duration = demux->segment.duration;
2219         segment.base = gst_segment_to_running_time (&demux->segment,
2220             GST_FORMAT_TIME, demux->segment.position);
2221       }
2222
2223       gst_segment_copy_into (&segment, &demux->segment);
2224       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2225
2226       /* map segment to internal qt segments and push on each stream */
2227       if (demux->n_streams) {
2228         if (demux->fragmented) {
2229           GstEvent *segment_event = gst_event_new_segment (&segment);
2230
2231           gst_event_replace (&demux->pending_newsegment, NULL);
2232           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2233           gst_qtdemux_push_event (demux, segment_event);
2234         } else {
2235           gst_event_replace (&demux->pending_newsegment, NULL);
2236           gst_qtdemux_map_and_push_segments (demux, &segment);
2237         }
2238       }
2239
2240       /* clear leftover in current segment, if any */
2241       gst_adapter_clear (demux->adapter);
2242
2243       /* set up streaming thread */
2244       demux->offset = offset;
2245       if (demux->upstream_format_is_time) {
2246         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2247             "set values to restart reading from a new atom");
2248         demux->neededbytes = 16;
2249         demux->todrop = 0;
2250       } else {
2251         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2252             NULL);
2253         if (stream) {
2254           demux->todrop = stream->samples[idx].offset - offset;
2255           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2256         } else {
2257           /* set up for EOS */
2258           demux->neededbytes = -1;
2259           demux->todrop = 0;
2260         }
2261       }
2262     exit:
2263       gst_event_unref (event);
2264       res = TRUE;
2265       goto drop;
2266     }
2267     case GST_EVENT_FLUSH_START:
2268     {
2269       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2270         gst_event_unref (event);
2271         goto drop;
2272       }
2273       break;
2274     }
2275     case GST_EVENT_FLUSH_STOP:
2276     {
2277       guint64 dur;
2278
2279       dur = demux->segment.duration;
2280       gst_qtdemux_reset (demux, FALSE);
2281       demux->segment.duration = dur;
2282
2283       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2284         gst_event_unref (event);
2285         goto drop;
2286       }
2287       break;
2288     }
2289     case GST_EVENT_EOS:
2290       /* If we are in push mode, and get an EOS before we've seen any streams,
2291        * then error out - we have nowhere to send the EOS */
2292       if (!demux->pullbased) {
2293         gint i;
2294         gboolean has_valid_stream = FALSE;
2295         for (i = 0; i < demux->n_streams; i++) {
2296           if (demux->streams[i]->pad != NULL) {
2297             has_valid_stream = TRUE;
2298             break;
2299           }
2300         }
2301         if (!has_valid_stream)
2302           gst_qtdemux_post_no_playable_stream_error (demux);
2303         else {
2304           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2305               (guint) gst_adapter_available (demux->adapter));
2306           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2307             res = FALSE;
2308           }
2309         }
2310       }
2311       break;
2312     case GST_EVENT_CAPS:{
2313       GstCaps *caps = NULL;
2314
2315       gst_event_parse_caps (event, &caps);
2316       gst_qtdemux_setcaps (demux, caps);
2317       res = TRUE;
2318       gst_event_unref (event);
2319       goto drop;
2320     }
2321     case GST_EVENT_PROTECTION:
2322     {
2323       const gchar *system_id = NULL;
2324
2325       gst_event_parse_protection (event, &system_id, NULL, NULL);
2326       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2327           system_id);
2328       gst_qtdemux_append_protection_system_id (demux, system_id);
2329       /* save the event for later, for source pads that have not been created */
2330       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2331       /* send it to all pads that already exist */
2332       gst_qtdemux_push_event (demux, event);
2333       res = TRUE;
2334       goto drop;
2335     }
2336     default:
2337       break;
2338   }
2339
2340   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2341
2342 drop:
2343   return res;
2344 }
2345
2346 #if 0
2347 static void
2348 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2349 {
2350   GstQTDemux *demux = GST_QTDEMUX (element);
2351
2352   GST_OBJECT_LOCK (demux);
2353   if (demux->element_index)
2354     gst_object_unref (demux->element_index);
2355   if (index) {
2356     demux->element_index = gst_object_ref (index);
2357   } else {
2358     demux->element_index = NULL;
2359   }
2360   GST_OBJECT_UNLOCK (demux);
2361   /* object lock might be taken again */
2362   if (index)
2363     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2364   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2365       demux->element_index, demux->index_id);
2366 }
2367
2368 static GstIndex *
2369 gst_qtdemux_get_index (GstElement * element)
2370 {
2371   GstIndex *result = NULL;
2372   GstQTDemux *demux = GST_QTDEMUX (element);
2373
2374   GST_OBJECT_LOCK (demux);
2375   if (demux->element_index)
2376     result = gst_object_ref (demux->element_index);
2377   GST_OBJECT_UNLOCK (demux);
2378
2379   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2380
2381   return result;
2382 }
2383 #endif
2384
2385 static void
2386 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2387 {
2388   g_free ((gpointer) stream->stco.data);
2389   stream->stco.data = NULL;
2390   g_free ((gpointer) stream->stsz.data);
2391   stream->stsz.data = NULL;
2392   g_free ((gpointer) stream->stsc.data);
2393   stream->stsc.data = NULL;
2394   g_free ((gpointer) stream->stts.data);
2395   stream->stts.data = NULL;
2396   g_free ((gpointer) stream->stss.data);
2397   stream->stss.data = NULL;
2398   g_free ((gpointer) stream->stps.data);
2399   stream->stps.data = NULL;
2400   g_free ((gpointer) stream->ctts.data);
2401   stream->ctts.data = NULL;
2402 }
2403
2404 static void
2405 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2406     QtDemuxStream * stream)
2407 {
2408   g_free (stream->segments);
2409   stream->segments = NULL;
2410   stream->segment_index = -1;
2411   stream->accumulated_base = 0;
2412 }
2413
2414 static void
2415 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2416     QtDemuxStream * stream)
2417 {
2418   g_free (stream->samples);
2419   stream->samples = NULL;
2420   gst_qtdemux_stbl_free (stream);
2421
2422   /* fragments */
2423   g_free (stream->ra_entries);
2424   stream->ra_entries = NULL;
2425   stream->n_ra_entries = 0;
2426
2427   stream->sample_index = -1;
2428   stream->stbl_index = -1;
2429   stream->n_samples = 0;
2430   stream->time_position = 0;
2431
2432   stream->n_samples_moof = 0;
2433   stream->duration_moof = 0;
2434   stream->duration_last_moof = 0;
2435 }
2436
2437 static void
2438 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2439 {
2440   if (stream->allocator)
2441     gst_object_unref (stream->allocator);
2442   while (stream->buffers) {
2443     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2444     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2445   }
2446   if (stream->rgb8_palette) {
2447     gst_memory_unref (stream->rgb8_palette);
2448     stream->rgb8_palette = NULL;
2449   }
2450
2451   if (stream->pending_tags)
2452     gst_tag_list_unref (stream->pending_tags);
2453   stream->pending_tags = NULL;
2454   g_free (stream->redirect_uri);
2455   stream->redirect_uri = NULL;
2456   stream->sent_eos = FALSE;
2457   stream->sparse = FALSE;
2458   stream->protected = FALSE;
2459   if (stream->protection_scheme_info) {
2460     if (stream->protection_scheme_type == FOURCC_cenc) {
2461       QtDemuxCencSampleSetInfo *info =
2462           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2463       if (info->default_properties)
2464         gst_structure_free (info->default_properties);
2465       if (info->crypto_info)
2466         g_ptr_array_free (info->crypto_info, TRUE);
2467     }
2468     g_free (stream->protection_scheme_info);
2469     stream->protection_scheme_info = NULL;
2470   }
2471   stream->protection_scheme_type = 0;
2472   stream->protection_scheme_version = 0;
2473   g_queue_foreach (&stream->protection_scheme_event_queue,
2474       (GFunc) gst_event_unref, NULL);
2475   g_queue_clear (&stream->protection_scheme_event_queue);
2476   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2477   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2478 }
2479
2480 static void
2481 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2482 {
2483   gst_qtdemux_stream_clear (qtdemux, stream);
2484   if (stream->caps)
2485     gst_caps_unref (stream->caps);
2486   stream->caps = NULL;
2487   if (stream->pad) {
2488     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2489     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2490   }
2491   g_free (stream);
2492 }
2493
2494 static void
2495 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2496 {
2497   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2498
2499   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2500   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2501   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2502   qtdemux->n_streams--;
2503 }
2504
2505 static GstStateChangeReturn
2506 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2507 {
2508   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2509   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2510
2511   switch (transition) {
2512     case GST_STATE_CHANGE_PAUSED_TO_READY:
2513       break;
2514     default:
2515       break;
2516   }
2517
2518   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2519
2520   switch (transition) {
2521     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2522       gst_qtdemux_reset (qtdemux, TRUE);
2523       break;
2524     }
2525     default:
2526       break;
2527   }
2528
2529   return result;
2530 }
2531
2532 static void
2533 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2534 {
2535   /* counts as header data */
2536   qtdemux->header_size += length;
2537
2538   /* only consider at least a sufficiently complete ftyp atom */
2539   if (length >= 20) {
2540     GstBuffer *buf;
2541
2542     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2543     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2544         GST_FOURCC_ARGS (qtdemux->major_brand));
2545     if (qtdemux->comp_brands)
2546       gst_buffer_unref (qtdemux->comp_brands);
2547     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2548     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2549   }
2550 }
2551
2552 static void
2553 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2554     GstTagList * xmptaglist)
2555 {
2556   /* Strip out bogus fields */
2557   if (xmptaglist) {
2558     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2559       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2560       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2561     } else {
2562       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2563     }
2564
2565     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2566
2567     /* prioritize native tags using _KEEP mode */
2568     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2569     gst_tag_list_unref (xmptaglist);
2570   }
2571 }
2572
2573 static void
2574 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2575     guint offset)
2576 {
2577   GstByteReader br;
2578   guint8 version;
2579   guint32 flags = 0;
2580   guint i;
2581   guint8 iv_size = 8;
2582   QtDemuxStream *stream;
2583   GstStructure *structure;
2584   QtDemuxCencSampleSetInfo *ss_info = NULL;
2585   const gchar *system_id;
2586   gboolean uses_sub_sample_encryption = FALSE;
2587
2588   if (qtdemux->n_streams == 0)
2589     return;
2590
2591   stream = qtdemux->streams[0];
2592
2593   structure = gst_caps_get_structure (stream->caps, 0);
2594   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2595     GST_WARNING_OBJECT (qtdemux,
2596         "Attempting PIFF box parsing on an unencrypted stream.");
2597     return;
2598   }
2599
2600   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2601       G_TYPE_STRING, &system_id, NULL);
2602   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2603
2604   stream->protected = TRUE;
2605   stream->protection_scheme_type = FOURCC_cenc;
2606
2607   if (!stream->protection_scheme_info)
2608     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2609
2610   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2611
2612   if (ss_info->default_properties)
2613     gst_structure_free (ss_info->default_properties);
2614
2615   ss_info->default_properties =
2616       gst_structure_new ("application/x-cenc",
2617       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2618
2619   if (ss_info->crypto_info) {
2620     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2621     g_ptr_array_free (ss_info->crypto_info, TRUE);
2622     ss_info->crypto_info = NULL;
2623   }
2624
2625   /* skip UUID */
2626   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2627
2628   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2629     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2630     return;
2631   }
2632
2633   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2634     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2635     return;
2636   }
2637
2638   if ((flags & 0x000001)) {
2639     guint32 algorithm_id = 0;
2640     const guint8 *kid;
2641     GstBuffer *kid_buf;
2642     gboolean is_encrypted = TRUE;
2643
2644     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2645       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2646       return;
2647     }
2648
2649     algorithm_id >>= 8;
2650     if (algorithm_id == 0) {
2651       is_encrypted = FALSE;
2652     } else if (algorithm_id == 1) {
2653       /* FIXME: maybe store this in properties? */
2654       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2655     } else if (algorithm_id == 2) {
2656       /* FIXME: maybe store this in properties? */
2657       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2658     }
2659
2660     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2661       return;
2662
2663     if (!gst_byte_reader_get_data (&br, 16, &kid))
2664       return;
2665
2666     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2667     gst_buffer_fill (kid_buf, 0, kid, 16);
2668     if (ss_info->default_properties)
2669       gst_structure_free (ss_info->default_properties);
2670     ss_info->default_properties =
2671         gst_structure_new ("application/x-cenc",
2672         "iv_size", G_TYPE_UINT, iv_size,
2673         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2674         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2675     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2676         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2677     gst_buffer_unref (kid_buf);
2678   } else if ((flags & 0x000002)) {
2679     uses_sub_sample_encryption = TRUE;
2680   }
2681
2682   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2683     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2684     return;
2685   }
2686
2687   ss_info->crypto_info =
2688       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2689       (GDestroyNotify) qtdemux_gst_structure_free);
2690
2691   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2692     GstStructure *properties;
2693     guint8 *data;
2694     GstBuffer *buf;
2695
2696     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2697     if (properties == NULL) {
2698       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2699       return;
2700     }
2701
2702     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2703       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2704       gst_structure_free (properties);
2705       return;
2706     }
2707     buf = gst_buffer_new_wrapped (data, iv_size);
2708     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2709     gst_buffer_unref (buf);
2710
2711     if (uses_sub_sample_encryption) {
2712       guint16 n_subsamples;
2713
2714       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2715           || n_subsamples == 0) {
2716         GST_ERROR_OBJECT (qtdemux,
2717             "failed to get subsample count for sample %u", i);
2718         gst_structure_free (properties);
2719         return;
2720       }
2721       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2722       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2723         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2724             i);
2725         gst_structure_free (properties);
2726         return;
2727       }
2728       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2729       gst_structure_set (properties,
2730           "subsample_count", G_TYPE_UINT, n_subsamples,
2731           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2732       gst_buffer_unref (buf);
2733     } else {
2734       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2735     }
2736
2737     g_ptr_array_add (ss_info->crypto_info, properties);
2738   }
2739 }
2740
2741 static void
2742 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2743 {
2744   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2745     0x97, 0xA9, 0x42, 0xE8,
2746     0x9C, 0x71, 0x99, 0x94,
2747     0x91, 0xE3, 0xAF, 0xAC
2748   };
2749   static const guint8 playready_uuid[] = {
2750     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2751     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2752   };
2753
2754   static const guint8 piff_sample_encryption_uuid[] = {
2755     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2756     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2757   };
2758
2759   guint offset;
2760
2761   /* counts as header data */
2762   qtdemux->header_size += length;
2763
2764   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2765
2766   if (length <= offset + 16) {
2767     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2768     return;
2769   }
2770
2771   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2772     GstBuffer *buf;
2773     GstTagList *taglist;
2774
2775     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2776         length - offset - 16, NULL);
2777     taglist = gst_tag_list_from_xmp_buffer (buf);
2778     gst_buffer_unref (buf);
2779
2780     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2781
2782   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2783     int len;
2784     const gunichar2 *s_utf16;
2785     char *contents;
2786
2787     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2788     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2789     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2790     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2791
2792     g_free (contents);
2793
2794     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2795         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2796         (NULL));
2797   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2798     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2799   } else {
2800     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2801         GST_READ_UINT32_LE (buffer + offset),
2802         GST_READ_UINT32_LE (buffer + offset + 4),
2803         GST_READ_UINT32_LE (buffer + offset + 8),
2804         GST_READ_UINT32_LE (buffer + offset + 12));
2805   }
2806 }
2807
2808 static void
2809 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2810 {
2811   GstSidxParser sidx_parser;
2812   GstIsoffParserResult res;
2813   guint consumed;
2814
2815   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2816
2817   res =
2818       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2819       &consumed);
2820   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2821   if (res == GST_ISOFF_QT_PARSER_DONE) {
2822     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2823   }
2824   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2825 }
2826
2827 /* caller verifies at least 8 bytes in buf */
2828 static void
2829 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2830     guint64 * plength, guint32 * pfourcc)
2831 {
2832   guint64 length;
2833   guint32 fourcc;
2834
2835   length = QT_UINT32 (data);
2836   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2837   fourcc = QT_FOURCC (data + 4);
2838   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2839
2840   if (length == 0) {
2841     length = G_MAXUINT64;
2842   } else if (length == 1 && size >= 16) {
2843     /* this means we have an extended size, which is the 64 bit value of
2844      * the next 8 bytes */
2845     length = QT_UINT64 (data + 8);
2846     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2847   }
2848
2849   if (plength)
2850     *plength = length;
2851   if (pfourcc)
2852     *pfourcc = fourcc;
2853 }
2854
2855 static gboolean
2856 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2857 {
2858   guint32 version = 0;
2859   GstClockTime duration = 0;
2860
2861   if (!gst_byte_reader_get_uint32_be (br, &version))
2862     goto failed;
2863
2864   version >>= 24;
2865   if (version == 1) {
2866     if (!gst_byte_reader_get_uint64_be (br, &duration))
2867       goto failed;
2868   } else {
2869     guint32 dur = 0;
2870
2871     if (!gst_byte_reader_get_uint32_be (br, &dur))
2872       goto failed;
2873     duration = dur;
2874   }
2875
2876   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2877   qtdemux->duration = duration;
2878
2879   return TRUE;
2880
2881 failed:
2882   {
2883     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2884     return FALSE;
2885   }
2886 }
2887
2888 static gboolean
2889 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2890     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2891 {
2892   if (!stream->parsed_trex && qtdemux->moov_node) {
2893     GNode *mvex, *trex;
2894     GstByteReader trex_data;
2895
2896     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2897     if (mvex) {
2898       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2899           &trex_data);
2900       while (trex) {
2901         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2902
2903         /* skip version/flags */
2904         if (!gst_byte_reader_skip (&trex_data, 4))
2905           goto next;
2906         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2907           goto next;
2908         if (id != stream->track_id)
2909           goto next;
2910         /* sample description index; ignore */
2911         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2912           goto next;
2913         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2914           goto next;
2915         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2916           goto next;
2917         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2918           goto next;
2919
2920         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2921             "duration %d,  size %d, flags 0x%x", stream->track_id,
2922             dur, size, flags);
2923
2924         stream->parsed_trex = TRUE;
2925         stream->def_sample_duration = dur;
2926         stream->def_sample_size = size;
2927         stream->def_sample_flags = flags;
2928
2929       next:
2930         /* iterate all siblings */
2931         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2932             &trex_data);
2933       }
2934     }
2935   }
2936
2937   *ds_duration = stream->def_sample_duration;
2938   *ds_size = stream->def_sample_size;
2939   *ds_flags = stream->def_sample_flags;
2940
2941   /* even then, above values are better than random ... */
2942   if (G_UNLIKELY (!stream->parsed_trex)) {
2943     GST_WARNING_OBJECT (qtdemux,
2944         "failed to find fragment defaults for stream %d", stream->track_id);
2945     return FALSE;
2946   }
2947
2948   return TRUE;
2949 }
2950
2951 /* This method should be called whenever a more accurate duration might
2952  * have been found. It will update all relevant variables if/where needed
2953  */
2954 static void
2955 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2956 {
2957   guint i;
2958   guint64 movdur;
2959   GstClockTime prevdur;
2960
2961   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2962
2963   if (movdur > qtdemux->duration) {
2964     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2965     GST_DEBUG_OBJECT (qtdemux,
2966         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2967         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2968     qtdemux->duration = movdur;
2969     GST_DEBUG_OBJECT (qtdemux,
2970         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2971         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2972         GST_TIME_ARGS (qtdemux->segment.stop));
2973     if (qtdemux->segment.duration == prevdur) {
2974       /* If the current segment has duration/stop identical to previous duration
2975        * update them also (because they were set at that point in time with
2976        * the wrong duration */
2977       /* We convert the value *from* the timescale version to avoid rounding errors */
2978       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2979       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2980       qtdemux->segment.duration = fixeddur;
2981       qtdemux->segment.stop = fixeddur;
2982     }
2983   }
2984   for (i = 0; i < qtdemux->n_streams; i++) {
2985     QtDemuxStream *stream = qtdemux->streams[i];
2986     if (stream) {
2987       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2988       if (movdur > stream->duration) {
2989         GST_DEBUG_OBJECT (qtdemux,
2990             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2991             GST_TIME_ARGS (duration));
2992         stream->duration = movdur;
2993         if (stream->dummy_segment) {
2994           /* Update all dummy values to new duration */
2995           stream->segments[0].stop_time = duration;
2996           stream->segments[0].duration = duration;
2997           stream->segments[0].media_stop = duration;
2998
2999           /* let downstream know we possibly have a new stop time */
3000           if (stream->segment_index != -1) {
3001             GstClockTime pos;
3002
3003             if (qtdemux->segment.rate >= 0) {
3004               pos = stream->segment.start;
3005             } else {
3006               pos = stream->segment.stop;
3007             }
3008
3009             gst_qtdemux_stream_update_segment (qtdemux, stream,
3010                 stream->segment_index, pos, NULL, NULL);
3011           }
3012         }
3013       }
3014     }
3015   }
3016 }
3017
3018 static gboolean
3019 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3020     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3021     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3022     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
3023 {
3024   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3025   guint64 timestamp;
3026   gint32 data_offset = 0;
3027   guint32 flags = 0, first_flags = 0, samples_count = 0;
3028   gint i;
3029   guint8 *data;
3030   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3031   QtDemuxSample *sample;
3032   gboolean ismv = FALSE;
3033   gint64 initial_offset;
3034
3035   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3036       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3037       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3038       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3039
3040   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3041     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3042     return TRUE;
3043   }
3044
3045   /* presence of stss or not can't really tell us much,
3046    * and flags and so on tend to be marginally reliable in these files */
3047   if (stream->subtype == FOURCC_soun) {
3048     GST_DEBUG_OBJECT (qtdemux,
3049         "sound track in fragmented file; marking all keyframes");
3050     stream->all_keyframe = TRUE;
3051   }
3052
3053   if (!gst_byte_reader_skip (trun, 1) ||
3054       !gst_byte_reader_get_uint24_be (trun, &flags))
3055     goto fail;
3056
3057   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3058     goto fail;
3059
3060   if (flags & TR_DATA_OFFSET) {
3061     /* note this is really signed */
3062     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3063       goto fail;
3064     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3065     /* default base offset = first byte of moof */
3066     if (*base_offset == -1) {
3067       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3068       *base_offset = moof_offset;
3069     }
3070     *running_offset = *base_offset + data_offset;
3071   } else {
3072     /* if no offset at all, that would mean data starts at moof start,
3073      * which is a bit wrong and is ismv crappy way, so compensate
3074      * assuming data is in mdat following moof */
3075     if (*base_offset == -1) {
3076       *base_offset = moof_offset + moof_length + 8;
3077       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3078       ismv = TRUE;
3079     }
3080     if (*running_offset == -1)
3081       *running_offset = *base_offset;
3082   }
3083
3084   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3085       *running_offset);
3086   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3087       data_offset, flags, samples_count);
3088
3089   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3090     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3091       GST_DEBUG_OBJECT (qtdemux,
3092           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3093       flags ^= TR_FIRST_SAMPLE_FLAGS;
3094     } else {
3095       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3096         goto fail;
3097       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3098     }
3099   }
3100
3101   /* FIXME ? spec says other bits should also be checked to determine
3102    * entry size (and prefix size for that matter) */
3103   entry_size = 0;
3104   dur_offset = size_offset = 0;
3105   if (flags & TR_SAMPLE_DURATION) {
3106     GST_LOG_OBJECT (qtdemux, "entry duration present");
3107     dur_offset = entry_size;
3108     entry_size += 4;
3109   }
3110   if (flags & TR_SAMPLE_SIZE) {
3111     GST_LOG_OBJECT (qtdemux, "entry size present");
3112     size_offset = entry_size;
3113     entry_size += 4;
3114   }
3115   if (flags & TR_SAMPLE_FLAGS) {
3116     GST_LOG_OBJECT (qtdemux, "entry flags present");
3117     flags_offset = entry_size;
3118     entry_size += 4;
3119   }
3120   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3121     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3122     ct_offset = entry_size;
3123     entry_size += 4;
3124   }
3125
3126   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3127     goto fail;
3128   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3129
3130   if (stream->n_samples + samples_count >=
3131       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3132     goto index_too_big;
3133
3134   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3135       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3136       (stream->n_samples + samples_count) *
3137       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3138
3139   /* create a new array of samples if it's the first sample parsed */
3140   if (stream->n_samples == 0) {
3141     g_assert (stream->samples == NULL);
3142     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3143     /* or try to reallocate it with space enough to insert the new samples */
3144   } else
3145     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3146         stream->n_samples + samples_count);
3147   if (stream->samples == NULL)
3148     goto out_of_memory;
3149
3150   if (qtdemux->fragment_start != -1) {
3151     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3152     qtdemux->fragment_start = -1;
3153   } else {
3154     if (stream->n_samples == 0) {
3155       if (decode_ts > 0) {
3156         timestamp = decode_ts;
3157       } else if (stream->pending_seek != NULL) {
3158         /* if we don't have a timestamp from a tfdt box, we'll use the one
3159          * from the mfra seek table */
3160         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3161             GST_TIME_ARGS (stream->pending_seek->ts));
3162
3163         /* FIXME: this is not fully correct, the timestamp refers to the random
3164          * access sample refered to in the tfra entry, which may not necessarily
3165          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3166         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3167       } else {
3168         timestamp = 0;
3169       }
3170
3171       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3172       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3173           GST_TIME_ARGS (gst_ts));
3174     } else {
3175       /* subsequent fragments extend stream */
3176       timestamp =
3177           stream->samples[stream->n_samples - 1].timestamp +
3178           stream->samples[stream->n_samples - 1].duration;
3179
3180       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3181        * difference (1 sec.) between decode_ts and timestamp, prefer the
3182        * former */
3183       if (!qtdemux->upstream_format_is_time
3184           && ABSDIFF (decode_ts, timestamp) >
3185           MAX (stream->duration_last_moof / 2,
3186               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3187         GST_INFO_OBJECT (qtdemux,
3188             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3189             ") are significantly different (more than %" GST_TIME_FORMAT
3190             "), using decode_ts",
3191             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3192             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3193             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3194                     MAX (stream->duration_last_moof / 2,
3195                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3196         timestamp = decode_ts;
3197       }
3198
3199       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3200       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3201           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3202     }
3203   }
3204
3205   initial_offset = *running_offset;
3206
3207   sample = stream->samples + stream->n_samples;
3208   for (i = 0; i < samples_count; i++) {
3209     guint32 dur, size, sflags, ct;
3210
3211     /* first read sample data */
3212     if (flags & TR_SAMPLE_DURATION) {
3213       dur = QT_UINT32 (data + dur_offset);
3214     } else {
3215       dur = d_sample_duration;
3216     }
3217     if (flags & TR_SAMPLE_SIZE) {
3218       size = QT_UINT32 (data + size_offset);
3219     } else {
3220       size = d_sample_size;
3221     }
3222     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3223       if (i == 0) {
3224         sflags = first_flags;
3225       } else {
3226         sflags = d_sample_flags;
3227       }
3228     } else if (flags & TR_SAMPLE_FLAGS) {
3229       sflags = QT_UINT32 (data + flags_offset);
3230     } else {
3231       sflags = d_sample_flags;
3232     }
3233     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3234       ct = QT_UINT32 (data + ct_offset);
3235     } else {
3236       ct = 0;
3237     }
3238     data += entry_size;
3239
3240     /* fill the sample information */
3241     sample->offset = *running_offset;
3242     sample->pts_offset = ct;
3243     sample->size = size;
3244     sample->timestamp = timestamp;
3245     sample->duration = dur;
3246     /* sample-is-difference-sample */
3247     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3248      * now idea how it relates to bitfield other than massive LE/BE confusion */
3249     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3250     *running_offset += size;
3251     timestamp += dur;
3252     stream->duration_moof += dur;
3253     sample++;
3254   }
3255
3256   /* Update total duration if needed */
3257   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3258
3259   /* Pre-emptively figure out size of mdat based on trun information.
3260    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3261    * size, else we will still be able to use this when dealing with gap'ed
3262    * input */
3263   qtdemux->mdatleft = *running_offset - initial_offset;
3264
3265   stream->n_samples += samples_count;
3266   stream->n_samples_moof += samples_count;
3267
3268   if (stream->pending_seek != NULL)
3269     stream->pending_seek = NULL;
3270
3271   return TRUE;
3272
3273 fail:
3274   {
3275     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3276     return FALSE;
3277   }
3278 out_of_memory:
3279   {
3280     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3281         stream->n_samples);
3282     return FALSE;
3283   }
3284 index_too_big:
3285   {
3286     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3287         "be larger than %uMB (broken file?)", stream->n_samples,
3288         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3289     return FALSE;
3290   }
3291 }
3292
3293 /* find stream with @id */
3294 static inline QtDemuxStream *
3295 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3296 {
3297   QtDemuxStream *stream;
3298   gint i;
3299
3300   /* check */
3301   if (G_UNLIKELY (!id)) {
3302     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3303     return NULL;
3304   }
3305
3306   /* try to get it fast and simple */
3307   if (G_LIKELY (id <= qtdemux->n_streams)) {
3308     stream = qtdemux->streams[id - 1];
3309     if (G_LIKELY (stream->track_id == id))
3310       return stream;
3311   }
3312
3313   /* linear search otherwise */
3314   for (i = 0; i < qtdemux->n_streams; i++) {
3315     stream = qtdemux->streams[i];
3316     if (stream->track_id == id)
3317       return stream;
3318   }
3319   if (qtdemux->mss_mode) {
3320     /* mss should have only 1 stream anyway */
3321     return qtdemux->streams[0];
3322   }
3323
3324   return NULL;
3325 }
3326
3327 static gboolean
3328 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3329     guint32 * fragment_number)
3330 {
3331   if (!gst_byte_reader_skip (mfhd, 4))
3332     goto fail;
3333   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3334     goto fail;
3335   return TRUE;
3336 fail:
3337   {
3338     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3339     return FALSE;
3340   }
3341 }
3342
3343 static gboolean
3344 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3345     QtDemuxStream ** stream, guint32 * default_sample_duration,
3346     guint32 * default_sample_size, guint32 * default_sample_flags,
3347     gint64 * base_offset)
3348 {
3349   guint32 flags = 0;
3350   guint32 track_id = 0;
3351
3352   if (!gst_byte_reader_skip (tfhd, 1) ||
3353       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3354     goto invalid_track;
3355
3356   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3357     goto invalid_track;
3358
3359   *stream = qtdemux_find_stream (qtdemux, track_id);
3360   if (G_UNLIKELY (!*stream))
3361     goto unknown_stream;
3362
3363   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3364     *base_offset = qtdemux->moof_offset;
3365
3366   if (flags & TF_BASE_DATA_OFFSET)
3367     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3368       goto invalid_track;
3369
3370   /* obtain stream defaults */
3371   qtdemux_parse_trex (qtdemux, *stream,
3372       default_sample_duration, default_sample_size, default_sample_flags);
3373
3374   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3375   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3376     if (!gst_byte_reader_skip (tfhd, 4))
3377       goto invalid_track;
3378
3379   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3380     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3381       goto invalid_track;
3382
3383   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3384     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3385       goto invalid_track;
3386
3387   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3388     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3389       goto invalid_track;
3390
3391   return TRUE;
3392
3393 invalid_track:
3394   {
3395     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3396     return FALSE;
3397   }
3398 unknown_stream:
3399   {
3400     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3401     return TRUE;
3402   }
3403 }
3404
3405 static gboolean
3406 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3407     guint64 * decode_time)
3408 {
3409   guint32 version = 0;
3410
3411   if (!gst_byte_reader_get_uint32_be (br, &version))
3412     return FALSE;
3413
3414   version >>= 24;
3415   if (version == 1) {
3416     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3417       goto failed;
3418   } else {
3419     guint32 dec_time = 0;
3420     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3421       goto failed;
3422     *decode_time = dec_time;
3423   }
3424
3425   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3426       *decode_time);
3427
3428   return TRUE;
3429
3430 failed:
3431   {
3432     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3433     return FALSE;
3434   }
3435 }
3436
3437 /* Returns a pointer to a GstStructure containing the properties of
3438  * the stream sample identified by @sample_index. The caller must unref
3439  * the returned object after use. Returns NULL if unsuccessful. */
3440 static GstStructure *
3441 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3442     QtDemuxStream * stream, guint sample_index)
3443 {
3444   QtDemuxCencSampleSetInfo *info = NULL;
3445
3446   g_return_val_if_fail (stream != NULL, NULL);
3447   g_return_val_if_fail (stream->protected, NULL);
3448   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3449
3450   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3451
3452   /* Currently, cenc properties for groups of samples are not supported, so
3453    * simply return a copy of the default sample properties */
3454   return gst_structure_copy (info->default_properties);
3455 }
3456
3457 /* Parses the sizes of sample auxiliary information contained within a stream,
3458  * as given in a saiz box. Returns array of sample_count guint8 size values,
3459  * or NULL on failure */
3460 static guint8 *
3461 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3462     GstByteReader * br, guint32 * sample_count)
3463 {
3464   guint32 flags = 0;
3465   guint8 *info_sizes;
3466   guint8 default_info_size;
3467
3468   g_return_val_if_fail (qtdemux != NULL, NULL);
3469   g_return_val_if_fail (stream != NULL, NULL);
3470   g_return_val_if_fail (br != NULL, NULL);
3471   g_return_val_if_fail (sample_count != NULL, NULL);
3472
3473   if (!gst_byte_reader_get_uint32_be (br, &flags))
3474     return NULL;
3475
3476   if (flags & 0x1) {
3477     /* aux_info_type and aux_info_type_parameter are ignored */
3478     if (!gst_byte_reader_skip (br, 8))
3479       return NULL;
3480   }
3481
3482   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3483     return NULL;
3484   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3485
3486   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3487     return NULL;
3488   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3489
3490
3491   if (default_info_size == 0) {
3492     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3493       return NULL;
3494     }
3495   } else {
3496     info_sizes = g_new (guint8, *sample_count);
3497     memset (info_sizes, default_info_size, *sample_count);
3498   }
3499
3500   return info_sizes;
3501 }
3502
3503 /* Parses the offset of sample auxiliary information contained within a stream,
3504  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3505 static gboolean
3506 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3507     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3508     guint64 * offset)
3509 {
3510   guint8 version = 0;
3511   guint32 flags = 0;
3512   guint32 aux_info_type = 0;
3513   guint32 aux_info_type_parameter = 0;
3514   guint32 entry_count;
3515   guint32 off_32;
3516   guint64 off_64;
3517   const guint8 *aux_info_type_data = NULL;
3518
3519   g_return_val_if_fail (qtdemux != NULL, FALSE);
3520   g_return_val_if_fail (stream != NULL, FALSE);
3521   g_return_val_if_fail (br != NULL, FALSE);
3522   g_return_val_if_fail (offset != NULL, FALSE);
3523
3524   if (!gst_byte_reader_get_uint8 (br, &version))
3525     return FALSE;
3526
3527   if (!gst_byte_reader_get_uint24_be (br, &flags))
3528     return FALSE;
3529
3530   if (flags & 0x1) {
3531
3532     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3533       return FALSE;
3534     aux_info_type = QT_FOURCC (aux_info_type_data);
3535
3536     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3537       return FALSE;
3538   } else if (stream->protected) {
3539     aux_info_type = stream->protection_scheme_type;
3540   } else {
3541     aux_info_type = stream->fourcc;
3542   }
3543
3544   if (info_type)
3545     *info_type = aux_info_type;
3546   if (info_type_parameter)
3547     *info_type_parameter = aux_info_type_parameter;
3548
3549   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3550       "aux_info_type_parameter:  %#06x",
3551       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3552
3553   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3554     return FALSE;
3555
3556   if (entry_count != 1) {
3557     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3558     return FALSE;
3559   }
3560
3561   if (version == 0) {
3562     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3563       return FALSE;
3564     *offset = (guint64) off_32;
3565   } else {
3566     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3567       return FALSE;
3568     *offset = off_64;
3569   }
3570
3571   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3572   return TRUE;
3573 }
3574
3575 static void
3576 qtdemux_gst_structure_free (GstStructure * gststructure)
3577 {
3578   if (gststructure) {
3579     gst_structure_free (gststructure);
3580   }
3581 }
3582
3583 /* Parses auxiliary information relating to samples protected using Common
3584  * Encryption (cenc); the format of this information is defined in
3585  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3586 static gboolean
3587 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3588     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3589 {
3590   QtDemuxCencSampleSetInfo *ss_info = NULL;
3591   guint8 size;
3592   gint i;
3593
3594   g_return_val_if_fail (qtdemux != NULL, FALSE);
3595   g_return_val_if_fail (stream != NULL, FALSE);
3596   g_return_val_if_fail (br != NULL, FALSE);
3597   g_return_val_if_fail (stream->protected, FALSE);
3598   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3599
3600   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3601
3602   if (ss_info->crypto_info) {
3603     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3604     g_ptr_array_free (ss_info->crypto_info, TRUE);
3605   }
3606
3607   ss_info->crypto_info =
3608       g_ptr_array_new_full (sample_count,
3609       (GDestroyNotify) qtdemux_gst_structure_free);
3610
3611   for (i = 0; i < sample_count; ++i) {
3612     GstStructure *properties;
3613     guint16 n_subsamples = 0;
3614     guint8 *data;
3615     guint iv_size;
3616     GstBuffer *buf;
3617
3618     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3619     if (properties == NULL) {
3620       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3621       return FALSE;
3622     }
3623     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3624       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3625       gst_structure_free (properties);
3626       return FALSE;
3627     }
3628     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3629       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3630       gst_structure_free (properties);
3631       return FALSE;
3632     }
3633     buf = gst_buffer_new_wrapped (data, iv_size);
3634     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3635     gst_buffer_unref (buf);
3636     size = info_sizes[i];
3637     if (size > iv_size) {
3638       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3639           || !(n_subsamples > 0)) {
3640         gst_structure_free (properties);
3641         GST_ERROR_OBJECT (qtdemux,
3642             "failed to get subsample count for sample %u", i);
3643         return FALSE;
3644       }
3645       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3646       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3647         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3648             i);
3649         gst_structure_free (properties);
3650         return FALSE;
3651       }
3652       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3653       if (!buf) {
3654         gst_structure_free (properties);
3655         return FALSE;
3656       }
3657       gst_structure_set (properties,
3658           "subsample_count", G_TYPE_UINT, n_subsamples,
3659           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3660       gst_buffer_unref (buf);
3661     } else {
3662       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3663     }
3664     g_ptr_array_add (ss_info->crypto_info, properties);
3665   }
3666   return TRUE;
3667 }
3668
3669 /* Converts a UUID in raw byte form to a string representation, as defined in
3670  * RFC 4122. The caller takes ownership of the returned string and is
3671  * responsible for freeing it after use. */
3672 static gchar *
3673 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3674 {
3675   const guint8 *uuid = (const guint8 *) uuid_bytes;
3676
3677   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3678       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3679       uuid[0], uuid[1], uuid[2], uuid[3],
3680       uuid[4], uuid[5], uuid[6], uuid[7],
3681       uuid[8], uuid[9], uuid[10], uuid[11],
3682       uuid[12], uuid[13], uuid[14], uuid[15]);
3683 }
3684
3685 /* Parses a Protection System Specific Header box (pssh), as defined in the
3686  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3687  * information needed by a specific content protection system in order to
3688  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3689  * otherwise. */
3690 static gboolean
3691 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3692 {
3693   gchar *sysid_string;
3694   guint32 pssh_size = QT_UINT32 (node->data);
3695   GstBuffer *pssh = NULL;
3696   GstEvent *event = NULL;
3697   guint32 parent_box_type;
3698   gint i;
3699
3700   if (G_UNLIKELY (pssh_size < 32U)) {
3701     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3702     return FALSE;
3703   }
3704
3705   sysid_string =
3706       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3707
3708   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3709
3710   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3711   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3712       gst_buffer_get_size (pssh));
3713
3714   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3715
3716   /* Push an event containing the pssh box onto the queues of all streams. */
3717   event = gst_event_new_protection (sysid_string, pssh,
3718       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3719   for (i = 0; i < qtdemux->n_streams; ++i) {
3720     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3721         gst_event_ref (event));
3722   }
3723   g_free (sysid_string);
3724   gst_event_unref (event);
3725   gst_buffer_unref (pssh);
3726   return TRUE;
3727 }
3728
3729 static gboolean
3730 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3731     guint64 moof_offset, QtDemuxStream * stream)
3732 {
3733   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3734   GNode *uuid_node;
3735   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3736   GNode *saiz_node, *saio_node, *pssh_node;
3737   GstByteReader saiz_data, saio_data;
3738   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3739   gint64 base_offset, running_offset;
3740   guint32 frag_num;
3741
3742   /* NOTE @stream ignored */
3743
3744   moof_node = g_node_new ((guint8 *) buffer);
3745   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3746   qtdemux_node_dump (qtdemux, moof_node);
3747
3748   /* Get fragment number from mfhd and check it's valid */
3749   mfhd_node =
3750       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3751   if (mfhd_node == NULL)
3752     goto missing_mfhd;
3753   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3754     goto fail;
3755   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3756
3757   /* unknown base_offset to start with */
3758   base_offset = running_offset = -1;
3759   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3760   while (traf_node) {
3761     guint64 decode_time = 0;
3762
3763     /* Fragment Header node */
3764     tfhd_node =
3765         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3766         &tfhd_data);
3767     if (!tfhd_node)
3768       goto missing_tfhd;
3769     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3770             &ds_size, &ds_flags, &base_offset))
3771       goto missing_tfhd;
3772
3773     /* The following code assumes at most a single set of sample auxiliary
3774      * data in the fragment (consisting of a saiz box and a corresponding saio
3775      * box); in theory, however, there could be multiple sets of sample
3776      * auxiliary data in a fragment. */
3777     saiz_node =
3778         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3779         &saiz_data);
3780     if (saiz_node) {
3781       guint32 info_type = 0;
3782       guint64 offset = 0;
3783       guint32 info_type_parameter = 0;
3784
3785       g_free (qtdemux->cenc_aux_info_sizes);
3786
3787       qtdemux->cenc_aux_info_sizes =
3788           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3789           &qtdemux->cenc_aux_sample_count);
3790       if (qtdemux->cenc_aux_info_sizes == NULL) {
3791         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3792         goto fail;
3793       }
3794       saio_node =
3795           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3796           &saio_data);
3797       if (!saio_node) {
3798         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3799         g_free (qtdemux->cenc_aux_info_sizes);
3800         qtdemux->cenc_aux_info_sizes = NULL;
3801         goto fail;
3802       }
3803
3804       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3805                   &info_type, &info_type_parameter, &offset))) {
3806         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3807         g_free (qtdemux->cenc_aux_info_sizes);
3808         qtdemux->cenc_aux_info_sizes = NULL;
3809         goto fail;
3810       }
3811       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3812         offset += (guint64) (base_offset - qtdemux->moof_offset);
3813       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3814         GstByteReader br;
3815         if (offset > length) {
3816           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3817           qtdemux->cenc_aux_info_offset = offset;
3818         } else {
3819           gst_byte_reader_init (&br, buffer + offset, length - offset);
3820           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3821                   qtdemux->cenc_aux_info_sizes,
3822                   qtdemux->cenc_aux_sample_count)) {
3823             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3824             g_free (qtdemux->cenc_aux_info_sizes);
3825             qtdemux->cenc_aux_info_sizes = NULL;
3826             goto fail;
3827           }
3828         }
3829       }
3830     }
3831
3832     tfdt_node =
3833         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3834         &tfdt_data);
3835     if (tfdt_node) {
3836       /* We'll use decode_time to interpolate timestamps
3837        * in case the input timestamps are missing */
3838       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3839
3840       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3841           " (%" GST_TIME_FORMAT ")", decode_time,
3842           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3843
3844       /* Discard the fragment buffer timestamp info to avoid using it.
3845        * Rely on tfdt instead as it is more accurate than the timestamp
3846        * that is fetched from a manifest/playlist and is usually
3847        * less accurate. */
3848       qtdemux->fragment_start = -1;
3849     }
3850
3851     if (G_UNLIKELY (!stream)) {
3852       /* we lost track of offset, we'll need to regain it,
3853        * but can delay complaining until later or avoid doing so altogether */
3854       base_offset = -2;
3855       goto next;
3856     }
3857     if (G_UNLIKELY (base_offset < -1))
3858       goto lost_offset;
3859
3860     if (qtdemux->upstream_format_is_time)
3861       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3862
3863     /* initialise moof sample data */
3864     stream->n_samples_moof = 0;
3865     stream->duration_last_moof = stream->duration_moof;
3866     stream->duration_moof = 0;
3867
3868     /* Track Run node */
3869     trun_node =
3870         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3871         &trun_data);
3872     while (trun_node) {
3873       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3874           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3875           &running_offset, decode_time);
3876       /* iterate all siblings */
3877       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3878           &trun_data);
3879     }
3880
3881     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3882     if (uuid_node) {
3883       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3884       guint32 box_length = QT_UINT32 (uuid_buffer);
3885
3886       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3887     }
3888
3889     /* if no new base_offset provided for next traf,
3890      * base is end of current traf */
3891     base_offset = running_offset;
3892     running_offset = -1;
3893
3894     if (stream->n_samples_moof && stream->duration_moof)
3895       stream->new_caps = TRUE;
3896
3897   next:
3898     /* iterate all siblings */
3899     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3900   }
3901
3902   /* parse any protection system info */
3903   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3904   while (pssh_node) {
3905     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3906     qtdemux_parse_pssh (qtdemux, pssh_node);
3907     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3908   }
3909
3910   g_node_destroy (moof_node);
3911   return TRUE;
3912
3913 missing_tfhd:
3914   {
3915     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3916     goto fail;
3917   }
3918 missing_mfhd:
3919   {
3920     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3921     goto fail;
3922   }
3923 lost_offset:
3924   {
3925     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3926     goto fail;
3927   }
3928 fail:
3929   {
3930     g_node_destroy (moof_node);
3931     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3932         (_("This file is corrupt and cannot be played.")), (NULL));
3933     return FALSE;
3934   }
3935 }
3936
3937 #if 0
3938 /* might be used if some day we actually use mfra & co
3939  * for random access to fragments,
3940  * but that will require quite some modifications and much less relying
3941  * on a sample array */
3942 #endif
3943
3944 static gboolean
3945 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3946 {
3947   QtDemuxStream *stream;
3948   guint32 ver_flags, track_id, len, num_entries, i;
3949   guint value_size, traf_size, trun_size, sample_size;
3950   guint64 time = 0, moof_offset = 0;
3951 #if 0
3952   GstBuffer *buf = NULL;
3953   GstFlowReturn ret;
3954 #endif
3955   GstByteReader tfra;
3956
3957   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3958
3959   if (!gst_byte_reader_skip (&tfra, 8))
3960     return FALSE;
3961
3962   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3963     return FALSE;
3964
3965   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3966       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3967       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3968     return FALSE;
3969
3970   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3971
3972   stream = qtdemux_find_stream (qtdemux, track_id);
3973   if (stream == NULL)
3974     goto unknown_trackid;
3975
3976   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3977   sample_size = (len & 3) + 1;
3978   trun_size = ((len & 12) >> 2) + 1;
3979   traf_size = ((len & 48) >> 4) + 1;
3980
3981   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3982       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3983
3984   if (num_entries == 0)
3985     goto no_samples;
3986
3987   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3988           value_size + value_size + traf_size + trun_size + sample_size))
3989     goto corrupt_file;
3990
3991   g_free (stream->ra_entries);
3992   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3993   stream->n_ra_entries = num_entries;
3994
3995   for (i = 0; i < num_entries; i++) {
3996     qt_atom_parser_get_offset (&tfra, value_size, &time);
3997     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3998     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3999     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4000     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4001
4002     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4003
4004     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4005         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4006
4007     stream->ra_entries[i].ts = time;
4008     stream->ra_entries[i].moof_offset = moof_offset;
4009
4010     /* don't want to go through the entire file and read all moofs at startup */
4011 #if 0
4012     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4013     if (ret != GST_FLOW_OK)
4014       goto corrupt_file;
4015     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4016         moof_offset, stream);
4017     gst_buffer_unref (buf);
4018 #endif
4019   }
4020
4021   check_update_duration (qtdemux, time);
4022
4023   return TRUE;
4024
4025 /* ERRORS */
4026 unknown_trackid:
4027   {
4028     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4029     return FALSE;
4030   }
4031 corrupt_file:
4032   {
4033     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4034     return FALSE;
4035   }
4036 no_samples:
4037   {
4038     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4039     return FALSE;
4040   }
4041 }
4042
4043 static gboolean
4044 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4045 {
4046   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4047   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4048   GstBuffer *mfro = NULL, *mfra = NULL;
4049   GstFlowReturn flow;
4050   gboolean ret = FALSE;
4051   GNode *mfra_node, *tfra_node;
4052   guint64 mfra_offset = 0;
4053   guint32 fourcc, mfra_size;
4054   gint64 len;
4055
4056   /* query upstream size in bytes */
4057   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4058     goto size_query_failed;
4059
4060   /* mfro box should be at the very end of the file */
4061   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4062   if (flow != GST_FLOW_OK)
4063     goto exit;
4064
4065   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4066
4067   fourcc = QT_FOURCC (mfro_map.data + 4);
4068   if (fourcc != FOURCC_mfro)
4069     goto exit;
4070
4071   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4072   if (mfro_map.size < 16)
4073     goto invalid_mfro_size;
4074
4075   mfra_size = QT_UINT32 (mfro_map.data + 12);
4076   if (mfra_size >= len)
4077     goto invalid_mfra_size;
4078
4079   mfra_offset = len - mfra_size;
4080
4081   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4082       mfra_offset, mfra_size);
4083
4084   /* now get and parse mfra box */
4085   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4086   if (flow != GST_FLOW_OK)
4087     goto broken_file;
4088
4089   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4090
4091   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4092   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4093
4094   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4095
4096   while (tfra_node) {
4097     qtdemux_parse_tfra (qtdemux, tfra_node);
4098     /* iterate all siblings */
4099     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4100   }
4101   g_node_destroy (mfra_node);
4102
4103   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4104   ret = TRUE;
4105
4106 exit:
4107
4108   if (mfro) {
4109     if (mfro_map.memory != NULL)
4110       gst_buffer_unmap (mfro, &mfro_map);
4111     gst_buffer_unref (mfro);
4112   }
4113   if (mfra) {
4114     if (mfra_map.memory != NULL)
4115       gst_buffer_unmap (mfra, &mfra_map);
4116     gst_buffer_unref (mfra);
4117   }
4118   return ret;
4119
4120 /* ERRORS */
4121 size_query_failed:
4122   {
4123     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4124     goto exit;
4125   }
4126 invalid_mfro_size:
4127   {
4128     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4129     goto exit;
4130   }
4131 invalid_mfra_size:
4132   {
4133     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4134     goto exit;
4135   }
4136 broken_file:
4137   {
4138     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4139     goto exit;
4140   }
4141 }
4142
4143 static guint64
4144 add_offset (guint64 offset, guint64 advance)
4145 {
4146   /* Avoid 64-bit overflow by clamping */
4147   if (offset > G_MAXUINT64 - advance)
4148     return G_MAXUINT64;
4149   return offset + advance;
4150 }
4151
4152 static GstFlowReturn
4153 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4154 {
4155   guint64 length = 0;
4156   guint32 fourcc = 0;
4157   GstBuffer *buf = NULL;
4158   GstFlowReturn ret = GST_FLOW_OK;
4159   guint64 cur_offset = qtdemux->offset;
4160   GstMapInfo map;
4161
4162   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4163   if (G_UNLIKELY (ret != GST_FLOW_OK))
4164     goto beach;
4165   gst_buffer_map (buf, &map, GST_MAP_READ);
4166   if (G_LIKELY (map.size >= 8))
4167     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4168   gst_buffer_unmap (buf, &map);
4169   gst_buffer_unref (buf);
4170
4171   /* maybe we already got most we needed, so only consider this eof */
4172   if (G_UNLIKELY (length == 0)) {
4173     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4174         (_("Invalid atom size.")),
4175         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4176             GST_FOURCC_ARGS (fourcc)));
4177     ret = GST_FLOW_EOS;
4178     goto beach;
4179   }
4180
4181   switch (fourcc) {
4182     case FOURCC_moof:
4183       /* record for later parsing when needed */
4184       if (!qtdemux->moof_offset) {
4185         qtdemux->moof_offset = qtdemux->offset;
4186       }
4187       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4188         /* FIXME */
4189       } else {
4190         qtdemux->offset += length;      /* skip moof and keep going */
4191       }
4192       if (qtdemux->got_moov) {
4193         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4194         ret = GST_FLOW_EOS;
4195         goto beach;
4196       }
4197       break;
4198     case FOURCC_mdat:
4199     case FOURCC_free:
4200     case FOURCC_wide:
4201     case FOURCC_PICT:
4202     case FOURCC_pnot:
4203     {
4204       GST_LOG_OBJECT (qtdemux,
4205           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4206           GST_FOURCC_ARGS (fourcc), cur_offset);
4207       qtdemux->offset = add_offset (qtdemux->offset, length);
4208       break;
4209     }
4210     case FOURCC_moov:
4211     {
4212       GstBuffer *moov = NULL;
4213
4214       if (qtdemux->got_moov) {
4215         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4216         qtdemux->offset = add_offset (qtdemux->offset, length);
4217         goto beach;
4218       }
4219
4220       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4221       if (ret != GST_FLOW_OK)
4222         goto beach;
4223       gst_buffer_map (moov, &map, GST_MAP_READ);
4224
4225       if (length != map.size) {
4226         /* Some files have a 'moov' atom at the end of the file which contains
4227          * a terminal 'free' atom where the body of the atom is missing.
4228          * Check for, and permit, this special case.
4229          */
4230         if (map.size >= 8) {
4231           guint8 *final_data = map.data + (map.size - 8);
4232           guint32 final_length = QT_UINT32 (final_data);
4233           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4234
4235           if (final_fourcc == FOURCC_free
4236               && map.size + final_length - 8 == length) {
4237             /* Ok, we've found that special case. Allocate a new buffer with
4238              * that free atom actually present. */
4239             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4240             gst_buffer_fill (newmoov, 0, map.data, map.size);
4241             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4242             gst_buffer_unmap (moov, &map);
4243             gst_buffer_unref (moov);
4244             moov = newmoov;
4245             gst_buffer_map (moov, &map, GST_MAP_READ);
4246           }
4247         }
4248       }
4249
4250       if (length != map.size) {
4251         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4252             (_("This file is incomplete and cannot be played.")),
4253             ("We got less than expected (received %" G_GSIZE_FORMAT
4254                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4255                 (guint) length, cur_offset));
4256         gst_buffer_unmap (moov, &map);
4257         gst_buffer_unref (moov);
4258         ret = GST_FLOW_ERROR;
4259         goto beach;
4260       }
4261       qtdemux->offset += length;
4262
4263       qtdemux_parse_moov (qtdemux, map.data, length);
4264       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4265
4266       qtdemux_parse_tree (qtdemux);
4267       if (qtdemux->moov_node_compressed) {
4268         g_node_destroy (qtdemux->moov_node_compressed);
4269         g_free (qtdemux->moov_node->data);
4270       }
4271       qtdemux->moov_node_compressed = NULL;
4272       g_node_destroy (qtdemux->moov_node);
4273       qtdemux->moov_node = NULL;
4274       gst_buffer_unmap (moov, &map);
4275       gst_buffer_unref (moov);
4276       qtdemux->got_moov = TRUE;
4277
4278       break;
4279     }
4280     case FOURCC_ftyp:
4281     {
4282       GstBuffer *ftyp = NULL;
4283
4284       /* extract major brand; might come in handy for ISO vs QT issues */
4285       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4286       if (ret != GST_FLOW_OK)
4287         goto beach;
4288       qtdemux->offset += length;
4289       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4290       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4291       gst_buffer_unmap (ftyp, &map);
4292       gst_buffer_unref (ftyp);
4293       break;
4294     }
4295     case FOURCC_uuid:
4296     {
4297       GstBuffer *uuid = NULL;
4298
4299       /* uuid are extension atoms */
4300       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4301       if (ret != GST_FLOW_OK)
4302         goto beach;
4303       qtdemux->offset += length;
4304       gst_buffer_map (uuid, &map, GST_MAP_READ);
4305       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4306       gst_buffer_unmap (uuid, &map);
4307       gst_buffer_unref (uuid);
4308       break;
4309     }
4310     case FOURCC_sidx:
4311     {
4312       GstBuffer *sidx = NULL;
4313       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4314       if (ret != GST_FLOW_OK)
4315         goto beach;
4316       qtdemux->offset += length;
4317       gst_buffer_map (sidx, &map, GST_MAP_READ);
4318       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4319       gst_buffer_unmap (sidx, &map);
4320       gst_buffer_unref (sidx);
4321       break;
4322     }
4323     default:
4324     {
4325       GstBuffer *unknown = NULL;
4326
4327       GST_LOG_OBJECT (qtdemux,
4328           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4329           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4330           cur_offset);
4331       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4332       if (ret != GST_FLOW_OK)
4333         goto beach;
4334       gst_buffer_map (unknown, &map, GST_MAP_READ);
4335       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4336       gst_buffer_unmap (unknown, &map);
4337       gst_buffer_unref (unknown);
4338       qtdemux->offset += length;
4339       break;
4340     }
4341   }
4342
4343 beach:
4344   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4345     /* digested all data, show what we have */
4346     qtdemux_prepare_streams (qtdemux);
4347     ret = qtdemux_expose_streams (qtdemux);
4348
4349     qtdemux->state = QTDEMUX_STATE_MOVIE;
4350     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4351         qtdemux->state);
4352     return ret;
4353   }
4354   return ret;
4355 }
4356
4357 /* Seeks to the previous keyframe of the indexed stream and
4358  * aligns other streams with respect to the keyframe timestamp
4359  * of indexed stream. Only called in case of Reverse Playback
4360  */
4361 static GstFlowReturn
4362 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4363 {
4364   guint8 n = 0;
4365   guint32 seg_idx = 0, k_index = 0;
4366   guint32 ref_seg_idx, ref_k_index;
4367   GstClockTime k_pos = 0, last_stop = 0;
4368   QtDemuxSegment *seg = NULL;
4369   QtDemuxStream *ref_str = NULL;
4370   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4371   guint64 target_ts;
4372
4373   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4374    * and finally align all the other streams on that timestamp with their
4375    * respective keyframes */
4376   for (n = 0; n < qtdemux->n_streams; n++) {
4377     QtDemuxStream *str = qtdemux->streams[n];
4378
4379     /* No candidate yet, take the first stream */
4380     if (!ref_str) {
4381       ref_str = str;
4382       continue;
4383     }
4384
4385     /* So that stream has a segment, we prefer video streams */
4386     if (str->subtype == FOURCC_vide) {
4387       ref_str = str;
4388       break;
4389     }
4390   }
4391
4392   if (G_UNLIKELY (!ref_str)) {
4393     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4394     goto eos;
4395   }
4396
4397   if (G_UNLIKELY (!ref_str->from_sample)) {
4398     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4399     goto eos;
4400   }
4401
4402   /* So that stream has been playing from from_sample to to_sample. We will
4403    * get the timestamp of the previous sample and search for a keyframe before
4404    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4405   if (ref_str->subtype == FOURCC_vide) {
4406     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4407         ref_str->from_sample - 1, FALSE);
4408   } else {
4409     if (ref_str->from_sample >= 10)
4410       k_index = ref_str->from_sample - 10;
4411     else
4412       k_index = 0;
4413   }
4414
4415   target_ts =
4416       ref_str->samples[k_index].timestamp +
4417       ref_str->samples[k_index].pts_offset;
4418
4419   /* get current segment for that stream */
4420   seg = &ref_str->segments[ref_str->segment_index];
4421   /* Use segment start in original timescale for comparisons */
4422   seg_media_start_mov = seg->trak_media_start;
4423
4424   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4425       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4426       k_index, target_ts, seg_media_start_mov,
4427       GST_TIME_ARGS (seg->media_start));
4428
4429   /* Crawl back through segments to find the one containing this I frame */
4430   while (target_ts < seg_media_start_mov) {
4431     GST_DEBUG_OBJECT (qtdemux,
4432         "keyframe position (sample %u) is out of segment %u " " target %"
4433         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4434         ref_str->segment_index, target_ts, seg_media_start_mov);
4435
4436     if (G_UNLIKELY (!ref_str->segment_index)) {
4437       /* Reached first segment, let's consider it's EOS */
4438       goto eos;
4439     }
4440     ref_str->segment_index--;
4441     seg = &ref_str->segments[ref_str->segment_index];
4442     /* Use segment start in original timescale for comparisons */
4443     seg_media_start_mov = seg->trak_media_start;
4444   }
4445   /* Calculate time position of the keyframe and where we should stop */
4446   k_pos =
4447       QTSTREAMTIME_TO_GSTTIME (ref_str,
4448       target_ts - seg->trak_media_start) + seg->time;
4449   last_stop =
4450       QTSTREAMTIME_TO_GSTTIME (ref_str,
4451       ref_str->samples[ref_str->from_sample].timestamp -
4452       seg->trak_media_start) + seg->time;
4453
4454   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4455       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4456       k_index, GST_TIME_ARGS (k_pos));
4457
4458   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4459   qtdemux->segment.position = last_stop;
4460   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4461       GST_TIME_ARGS (last_stop));
4462
4463   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4464     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4465     goto eos;
4466   }
4467
4468   ref_seg_idx = ref_str->segment_index;
4469   ref_k_index = k_index;
4470
4471   /* Align them all on this */
4472   for (n = 0; n < qtdemux->n_streams; n++) {
4473     guint32 index = 0;
4474     GstClockTime seg_time = 0;
4475     QtDemuxStream *str = qtdemux->streams[n];
4476
4477     /* aligning reference stream again might lead to backing up to yet another
4478      * keyframe (due to timestamp rounding issues),
4479      * potentially putting more load on downstream; so let's try to avoid */
4480     if (str == ref_str) {
4481       seg_idx = ref_seg_idx;
4482       seg = &str->segments[seg_idx];
4483       k_index = ref_k_index;
4484       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4485           "sample at index %d", n, ref_str->segment_index, k_index);
4486     } else {
4487       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4488       GST_DEBUG_OBJECT (qtdemux,
4489           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4490           seg_idx, GST_TIME_ARGS (k_pos));
4491
4492       /* get segment and time in the segment */
4493       seg = &str->segments[seg_idx];
4494       seg_time = k_pos - seg->time;
4495
4496       /* get the media time in the segment.
4497        * No adjustment for empty "filler" segments */
4498       if (seg->media_start != GST_CLOCK_TIME_NONE)
4499         seg_time += seg->media_start;
4500
4501       /* get the index of the sample with media time */
4502       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4503       GST_DEBUG_OBJECT (qtdemux,
4504           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4505           GST_TIME_ARGS (seg_time), index);
4506
4507       /* find previous keyframe */
4508       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4509     }
4510
4511     /* Remember until where we want to go */
4512     str->to_sample = str->from_sample - 1;
4513     /* Define our time position */
4514     target_ts =
4515         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4516     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4517     if (seg->media_start != GST_CLOCK_TIME_NONE)
4518       str->time_position -= seg->media_start;
4519
4520     /* Now seek back in time */
4521     gst_qtdemux_move_stream (qtdemux, str, k_index);
4522     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4523         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4524         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4525   }
4526
4527   return GST_FLOW_OK;
4528
4529 eos:
4530   return GST_FLOW_EOS;
4531 }
4532
4533 /*
4534  * Gets the current qt segment start, stop and position for the
4535  * given time offset. This is used in update_segment()
4536  */
4537 static void
4538 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4539     QtDemuxStream * stream, GstClockTime offset,
4540     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4541 {
4542   GstClockTime seg_time;
4543   GstClockTime start, stop, time;
4544   QtDemuxSegment *segment;
4545
4546   segment = &stream->segments[stream->segment_index];
4547
4548   /* get time in this segment */
4549   seg_time = (offset - segment->time) * segment->rate;
4550
4551   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4552       GST_TIME_ARGS (seg_time));
4553
4554   if (G_UNLIKELY (seg_time > segment->duration)) {
4555     GST_LOG_OBJECT (stream->pad,
4556         "seg_time > segment->duration %" GST_TIME_FORMAT,
4557         GST_TIME_ARGS (segment->duration));
4558     seg_time = segment->duration;
4559   }
4560
4561   /* qtdemux->segment.stop is in outside-time-realm, whereas
4562    * segment->media_stop is in track-time-realm.
4563    *
4564    * In order to compare the two, we need to bring segment.stop
4565    * into the track-time-realm
4566    *
4567    * FIXME - does this comment still hold? Don't see any conversion here */
4568
4569   stop = qtdemux->segment.stop;
4570   if (stop == GST_CLOCK_TIME_NONE)
4571     stop = qtdemux->segment.duration;
4572   if (stop == GST_CLOCK_TIME_NONE)
4573     stop = segment->media_stop;
4574   else
4575     stop =
4576         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4577
4578   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4579     start = segment->time + seg_time;
4580     time = offset;
4581     stop = start - seg_time + segment->duration;
4582   } else if (qtdemux->segment.rate >= 0) {
4583     start = MIN (segment->media_start + seg_time, stop);
4584     time = offset;
4585   } else {
4586     if (segment->media_start >= qtdemux->segment.start) {
4587       time = segment->time;
4588     } else {
4589       time = segment->time + (qtdemux->segment.start - segment->media_start);
4590     }
4591
4592     start = MAX (segment->media_start, qtdemux->segment.start);
4593     stop = MIN (segment->media_start + seg_time, stop);
4594   }
4595
4596   *_start = start;
4597   *_stop = stop;
4598   *_time = time;
4599 }
4600
4601 /*
4602  * Updates the qt segment used for the stream and pushes a new segment event
4603  * downstream on this stream's pad.
4604  */
4605 static gboolean
4606 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4607     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4608     GstClockTime * _stop)
4609 {
4610   QtDemuxSegment *segment;
4611   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4612   gdouble rate;
4613   GstEvent *event;
4614
4615   /* update the current segment */
4616   stream->segment_index = seg_idx;
4617
4618   /* get the segment */
4619   segment = &stream->segments[seg_idx];
4620
4621   if (G_UNLIKELY (offset < segment->time)) {
4622     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4623         GST_TIME_ARGS (segment->time));
4624     return FALSE;
4625   }
4626
4627   /* segment lies beyond total indicated duration */
4628   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4629           segment->time > qtdemux->segment.duration)) {
4630     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4631         " < segment->time %" GST_TIME_FORMAT,
4632         GST_TIME_ARGS (qtdemux->segment.duration),
4633         GST_TIME_ARGS (segment->time));
4634     return FALSE;
4635   }
4636
4637   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4638       &start, &stop, &time);
4639
4640   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4641       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4642       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4643
4644   /* combine global rate with that of the segment */
4645   rate = segment->rate * qtdemux->segment.rate;
4646
4647   /* Copy flags from main segment */
4648   stream->segment.flags = qtdemux->segment.flags;
4649
4650   /* update the segment values used for clipping */
4651   stream->segment.offset = qtdemux->segment.offset;
4652   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4653   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4654   stream->segment.rate = rate;
4655   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4656       stream->cslg_shift);
4657   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4658       stream->cslg_shift);
4659   stream->segment.time = time;
4660   stream->segment.position = stream->segment.start;
4661
4662   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4663       &stream->segment);
4664
4665   /* now prepare and send the segment */
4666   if (stream->pad) {
4667     event = gst_event_new_segment (&stream->segment);
4668     if (qtdemux->segment_seqnum) {
4669       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4670     }
4671     gst_pad_push_event (stream->pad, event);
4672     /* assume we can send more data now */
4673     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4674     /* clear to send tags on this pad now */
4675     gst_qtdemux_push_tags (qtdemux, stream);
4676   }
4677
4678   if (_start)
4679     *_start = start;
4680   if (_stop)
4681     *_stop = stop;
4682
4683   return TRUE;
4684 }
4685
4686 /* activate the given segment number @seg_idx of @stream at time @offset.
4687  * @offset is an absolute global position over all the segments.
4688  *
4689  * This will push out a NEWSEGMENT event with the right values and
4690  * position the stream index to the first decodable sample before
4691  * @offset.
4692  */
4693 static gboolean
4694 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4695     guint32 seg_idx, GstClockTime offset)
4696 {
4697   QtDemuxSegment *segment;
4698   guint32 index, kf_index;
4699   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4700
4701   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4702       seg_idx, GST_TIME_ARGS (offset));
4703
4704   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4705           &start, &stop))
4706     return FALSE;
4707
4708   segment = &stream->segments[stream->segment_index];
4709
4710   /* in the fragmented case, we pick a fragment that starts before our
4711    * desired position and rely on downstream to wait for a keyframe
4712    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4713    * tfra entries tells us which trun/sample the key unit is in, but we don't
4714    * make use of this additional information at the moment) */
4715   if (qtdemux->fragmented) {
4716     stream->to_sample = G_MAXUINT32;
4717     return TRUE;
4718   }
4719
4720   /* We don't need to look for a sample in push-based */
4721   if (!qtdemux->pullbased)
4722     return TRUE;
4723
4724   /* and move to the keyframe before the indicated media time of the
4725    * segment */
4726   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4727     if (qtdemux->segment.rate >= 0) {
4728       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4729       stream->to_sample = G_MAXUINT32;
4730       GST_DEBUG_OBJECT (stream->pad,
4731           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4732           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4733           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4734     } else {
4735       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4736       stream->to_sample = index;
4737       GST_DEBUG_OBJECT (stream->pad,
4738           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4739           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4740           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4741     }
4742   } else {
4743     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4744         "this is an empty segment");
4745     return TRUE;
4746   }
4747
4748   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4749    * encountered an error and printed a message so we return appropriately */
4750   if (index == -1)
4751     return FALSE;
4752
4753   /* we're at the right spot */
4754   if (index == stream->sample_index) {
4755     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4756     return TRUE;
4757   }
4758
4759   /* find keyframe of the target index */
4760   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4761
4762 /* *INDENT-OFF* */
4763 /* indent does stupid stuff with stream->samples[].timestamp */
4764
4765   /* if we move forwards, we don't have to go back to the previous
4766    * keyframe since we already sent that. We can also just jump to
4767    * the keyframe right before the target index if there is one. */
4768   if (index > stream->sample_index) {
4769     /* moving forwards check if we move past a keyframe */
4770     if (kf_index > stream->sample_index) {
4771       GST_DEBUG_OBJECT (stream->pad,
4772            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4773            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4774            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4775       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4776     } else {
4777       GST_DEBUG_OBJECT (stream->pad,
4778           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4779           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4780           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4781     }
4782   } else {
4783     GST_DEBUG_OBJECT (stream->pad,
4784         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4785         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4786         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4787     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4788   }
4789
4790 /* *INDENT-ON* */
4791
4792   return TRUE;
4793 }
4794
4795 /* prepare to get the current sample of @stream, getting essential values.
4796  *
4797  * This function will also prepare and send the segment when needed.
4798  *
4799  * Return FALSE if the stream is EOS.
4800  *
4801  * PULL-BASED
4802  */
4803 static gboolean
4804 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4805     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4806     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4807     gboolean * keyframe)
4808 {
4809   QtDemuxSample *sample;
4810   GstClockTime time_position;
4811   guint32 seg_idx;
4812
4813   g_return_val_if_fail (stream != NULL, FALSE);
4814
4815   time_position = stream->time_position;
4816   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4817     goto eos;
4818
4819   seg_idx = stream->segment_index;
4820   if (G_UNLIKELY (seg_idx == -1)) {
4821     /* find segment corresponding to time_position if we are looking
4822      * for a segment. */
4823     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4824   }
4825
4826   /* different segment, activate it, sample_index will be set. */
4827   if (G_UNLIKELY (stream->segment_index != seg_idx))
4828     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4829
4830   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4831                   segment_index]))) {
4832     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4833
4834     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4835         " prepare empty sample");
4836
4837     *empty = TRUE;
4838     *pts = *dts = time_position;
4839     *duration = seg->duration - (time_position - seg->time);
4840
4841     return TRUE;
4842   }
4843
4844   *empty = FALSE;
4845
4846   if (stream->sample_index == -1)
4847     stream->sample_index = 0;
4848
4849   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4850       stream->sample_index, stream->n_samples);
4851
4852   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4853     if (!qtdemux->fragmented)
4854       goto eos;
4855
4856     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4857     do {
4858       GstFlowReturn flow;
4859
4860       GST_OBJECT_LOCK (qtdemux);
4861       flow = qtdemux_add_fragmented_samples (qtdemux);
4862       GST_OBJECT_UNLOCK (qtdemux);
4863
4864       if (flow != GST_FLOW_OK)
4865         goto eos;
4866     }
4867     while (stream->sample_index >= stream->n_samples);
4868   }
4869
4870   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4871     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4872         stream->sample_index);
4873     return FALSE;
4874   }
4875
4876   /* now get the info for the sample we're at */
4877   sample = &stream->samples[stream->sample_index];
4878
4879   *dts = QTSAMPLE_DTS (stream, sample);
4880   *pts = QTSAMPLE_PTS (stream, sample);
4881   *offset = sample->offset;
4882   *size = sample->size;
4883   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4884   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4885
4886   return TRUE;
4887
4888   /* special cases */
4889 eos:
4890   {
4891     stream->time_position = GST_CLOCK_TIME_NONE;
4892     return FALSE;
4893   }
4894 }
4895
4896 /* move to the next sample in @stream.
4897  *
4898  * Moves to the next segment when needed.
4899  */
4900 static void
4901 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4902 {
4903   QtDemuxSample *sample;
4904   QtDemuxSegment *segment;
4905
4906   /* get current segment */
4907   segment = &stream->segments[stream->segment_index];
4908
4909   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4910     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4911     goto next_segment;
4912   }
4913
4914   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4915     /* Mark the stream as EOS */
4916     GST_DEBUG_OBJECT (qtdemux,
4917         "reached max allowed sample %u, mark EOS", stream->to_sample);
4918     stream->time_position = GST_CLOCK_TIME_NONE;
4919     return;
4920   }
4921
4922   /* move to next sample */
4923   stream->sample_index++;
4924   stream->offset_in_sample = 0;
4925
4926   /* reached the last sample, we need the next segment */
4927   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4928     goto next_segment;
4929
4930   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4931     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4932         stream->sample_index);
4933     return;
4934   }
4935
4936   /* get next sample */
4937   sample = &stream->samples[stream->sample_index];
4938
4939   /* see if we are past the segment */
4940   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4941     goto next_segment;
4942
4943   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4944     /* inside the segment, update time_position, looks very familiar to
4945      * GStreamer segments, doesn't it? */
4946     stream->time_position =
4947         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4948   } else {
4949     /* not yet in segment, time does not yet increment. This means
4950      * that we are still prerolling keyframes to the decoder so it can
4951      * decode the first sample of the segment. */
4952     stream->time_position = segment->time;
4953   }
4954   return;
4955
4956   /* move to the next segment */
4957 next_segment:
4958   {
4959     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4960
4961     if (stream->segment_index == stream->n_segments - 1) {
4962       /* are we at the end of the last segment, we're EOS */
4963       stream->time_position = GST_CLOCK_TIME_NONE;
4964     } else {
4965       /* else we're only at the end of the current segment */
4966       stream->time_position = segment->stop_time;
4967     }
4968     /* make sure we select a new segment */
4969
4970     /* accumulate previous segments */
4971     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4972       stream->accumulated_base +=
4973           (stream->segment.stop -
4974           stream->segment.start) / ABS (stream->segment.rate);
4975
4976     stream->segment_index = -1;
4977   }
4978 }
4979
4980 static void
4981 gst_qtdemux_sync_streams (GstQTDemux * demux)
4982 {
4983   gint i;
4984
4985   if (demux->n_streams <= 1)
4986     return;
4987
4988   for (i = 0; i < demux->n_streams; i++) {
4989     QtDemuxStream *stream;
4990     GstClockTime end_time;
4991
4992     stream = demux->streams[i];
4993
4994     if (!stream->pad)
4995       continue;
4996
4997     /* TODO advance time on subtitle streams here, if any some day */
4998
4999     /* some clips/trailers may have unbalanced streams at the end,
5000      * so send EOS on shorter stream to prevent stalling others */
5001
5002     /* do not mess with EOS if SEGMENT seeking */
5003     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5004       continue;
5005
5006     if (demux->pullbased) {
5007       /* loop mode is sample time based */
5008       if (!STREAM_IS_EOS (stream))
5009         continue;
5010     } else {
5011       /* push mode is byte position based */
5012       if (stream->n_samples &&
5013           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5014         continue;
5015     }
5016
5017     if (stream->sent_eos)
5018       continue;
5019
5020     /* only act if some gap */
5021     end_time = stream->segments[stream->n_segments - 1].stop_time;
5022     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5023         ", stream end: %" GST_TIME_FORMAT,
5024         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5025     if (GST_CLOCK_TIME_IS_VALID (end_time)
5026         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5027       GstEvent *event;
5028
5029       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5030           GST_PAD_NAME (stream->pad));
5031       stream->sent_eos = TRUE;
5032       event = gst_event_new_eos ();
5033       if (demux->segment_seqnum)
5034         gst_event_set_seqnum (event, demux->segment_seqnum);
5035       gst_pad_push_event (stream->pad, event);
5036     }
5037   }
5038 }
5039
5040 /* EOS and NOT_LINKED need to be combined. This means that we return:
5041  *
5042  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5043  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5044  */
5045 static GstFlowReturn
5046 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5047     GstFlowReturn ret)
5048 {
5049   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5050
5051   if (stream->pad)
5052     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5053         ret);
5054   else
5055     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5056
5057   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5058   return ret;
5059 }
5060
5061 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5062  * completely clipped
5063  *
5064  * Should be used only with raw buffers */
5065 static GstBuffer *
5066 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5067     GstBuffer * buf)
5068 {
5069   guint64 start, stop, cstart, cstop, diff;
5070   GstClockTime pts, duration;
5071   gsize size, osize;
5072   gint num_rate, denom_rate;
5073   gint frame_size;
5074   gboolean clip_data;
5075   guint offset;
5076
5077   osize = size = gst_buffer_get_size (buf);
5078   offset = 0;
5079
5080   /* depending on the type, setup the clip parameters */
5081   if (stream->subtype == FOURCC_soun) {
5082     frame_size = stream->bytes_per_frame;
5083     num_rate = GST_SECOND;
5084     denom_rate = (gint) stream->rate;
5085     clip_data = TRUE;
5086   } else if (stream->subtype == FOURCC_vide) {
5087     frame_size = size;
5088     num_rate = stream->fps_n;
5089     denom_rate = stream->fps_d;
5090     clip_data = FALSE;
5091   } else
5092     goto wrong_type;
5093
5094   if (frame_size <= 0)
5095     goto bad_frame_size;
5096
5097   /* we can only clip if we have a valid pts */
5098   pts = GST_BUFFER_PTS (buf);
5099   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5100     goto no_pts;
5101
5102   duration = GST_BUFFER_DURATION (buf);
5103
5104   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5105     duration =
5106         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5107   }
5108
5109   start = pts;
5110   stop = start + duration;
5111
5112   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5113               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5114     goto clipped;
5115
5116   /* see if some clipping happened */
5117   diff = cstart - start;
5118   if (diff > 0) {
5119     pts += diff;
5120     duration -= diff;
5121
5122     if (clip_data) {
5123       /* bring clipped time to samples and to bytes */
5124       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5125       diff *= frame_size;
5126
5127       GST_DEBUG_OBJECT (qtdemux,
5128           "clipping start to %" GST_TIME_FORMAT " %"
5129           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5130
5131       offset = diff;
5132       size -= diff;
5133     }
5134   }
5135   diff = stop - cstop;
5136   if (diff > 0) {
5137     duration -= diff;
5138
5139     if (clip_data) {
5140       /* bring clipped time to samples and then to bytes */
5141       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5142       diff *= frame_size;
5143       GST_DEBUG_OBJECT (qtdemux,
5144           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5145           " bytes", GST_TIME_ARGS (cstop), diff);
5146       size -= diff;
5147     }
5148   }
5149
5150   if (offset != 0 || size != osize)
5151     gst_buffer_resize (buf, offset, size);
5152
5153   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5154   GST_BUFFER_PTS (buf) = pts;
5155   GST_BUFFER_DURATION (buf) = duration;
5156
5157   return buf;
5158
5159   /* dropped buffer */
5160 wrong_type:
5161   {
5162     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5163     return buf;
5164   }
5165 bad_frame_size:
5166   {
5167     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5168     return buf;
5169   }
5170 no_pts:
5171   {
5172     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5173     return buf;
5174   }
5175 clipped:
5176   {
5177     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5178     gst_buffer_unref (buf);
5179     return NULL;
5180   }
5181 }
5182
5183 static GstBuffer *
5184 gst_qtdemux_align_buffer (GstQTDemux * demux,
5185     GstBuffer * buffer, gsize alignment)
5186 {
5187   GstMapInfo map;
5188
5189   gst_buffer_map (buffer, &map, GST_MAP_READ);
5190
5191   if (map.size < sizeof (guintptr)) {
5192     gst_buffer_unmap (buffer, &map);
5193     return buffer;
5194   }
5195
5196   if (((guintptr) map.data) & (alignment - 1)) {
5197     GstBuffer *new_buffer;
5198     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5199
5200     new_buffer = gst_buffer_new_allocate (NULL,
5201         gst_buffer_get_size (buffer), &params);
5202
5203     /* Copy data "by hand", so ensure alignment is kept: */
5204     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5205
5206     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5207     GST_DEBUG_OBJECT (demux,
5208         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5209         alignment);
5210
5211     gst_buffer_unmap (buffer, &map);
5212     gst_buffer_unref (buffer);
5213
5214     return new_buffer;
5215   }
5216
5217   gst_buffer_unmap (buffer, &map);
5218   return buffer;
5219 }
5220
5221 /* the input buffer metadata must be writable,
5222  * but time/duration etc not yet set and need not be preserved */
5223 static GstBuffer *
5224 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5225     GstBuffer * buf)
5226 {
5227   GstMapInfo map;
5228   guint nsize = 0;
5229   gchar *str;
5230
5231   /* not many cases for now */
5232   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5233     /* send a one time dvd clut event */
5234     if (stream->pending_event && stream->pad)
5235       gst_pad_push_event (stream->pad, stream->pending_event);
5236     stream->pending_event = NULL;
5237   }
5238
5239   if (G_UNLIKELY (stream->subtype != FOURCC_text
5240           && stream->subtype != FOURCC_sbtl &&
5241           stream->subtype != FOURCC_subp)) {
5242     return buf;
5243   }
5244
5245   gst_buffer_map (buf, &map, GST_MAP_READ);
5246
5247   /* empty buffer is sent to terminate previous subtitle */
5248   if (map.size <= 2) {
5249     gst_buffer_unmap (buf, &map);
5250     gst_buffer_unref (buf);
5251     return NULL;
5252   }
5253   if (stream->subtype == FOURCC_subp) {
5254     /* That's all the processing needed for subpictures */
5255     gst_buffer_unmap (buf, &map);
5256     return buf;
5257   }
5258
5259   nsize = GST_READ_UINT16_BE (map.data);
5260   nsize = MIN (nsize, map.size - 2);
5261
5262   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5263       nsize, map.size);
5264
5265   /* takes care of UTF-8 validation or UTF-16 recognition,
5266    * no other encoding expected */
5267   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5268   gst_buffer_unmap (buf, &map);
5269   if (str) {
5270     gst_buffer_unref (buf);
5271     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5272   } else {
5273     /* this should not really happen unless the subtitle is corrupted */
5274     gst_buffer_unref (buf);
5275     buf = NULL;
5276   }
5277
5278   /* FIXME ? convert optional subsequent style info to markup */
5279
5280   return buf;
5281 }
5282
5283 /* Sets a buffer's attributes properly and pushes it downstream.
5284  * Also checks for additional actions and custom processing that may
5285  * need to be done first.
5286  */
5287 static GstFlowReturn
5288 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5289     QtDemuxStream * stream, GstBuffer * buf,
5290     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5291     gboolean keyframe, GstClockTime position, guint64 byte_position)
5292 {
5293   GstFlowReturn ret = GST_FLOW_OK;
5294
5295   /* offset the timestamps according to the edit list */
5296
5297   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5298     gchar *url;
5299     GstMapInfo map;
5300
5301     gst_buffer_map (buf, &map, GST_MAP_READ);
5302     url = g_strndup ((gchar *) map.data, map.size);
5303     gst_buffer_unmap (buf, &map);
5304     if (url != NULL && strlen (url) != 0) {
5305       /* we have RTSP redirect now */
5306       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5307           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5308               gst_structure_new ("redirect",
5309                   "new-location", G_TYPE_STRING, url, NULL)));
5310       qtdemux->posted_redirect = TRUE;
5311     } else {
5312       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5313           "posting");
5314     }
5315     g_free (url);
5316   }
5317
5318   /* position reporting */
5319   if (qtdemux->segment.rate >= 0) {
5320     qtdemux->segment.position = position;
5321     gst_qtdemux_sync_streams (qtdemux);
5322   }
5323
5324   if (G_UNLIKELY (!stream->pad)) {
5325     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5326     gst_buffer_unref (buf);
5327     goto exit;
5328   }
5329
5330   /* send out pending buffers */
5331   while (stream->buffers) {
5332     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5333
5334     if (G_UNLIKELY (stream->discont)) {
5335       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5336       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5337       stream->discont = FALSE;
5338     } else {
5339       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5340     }
5341
5342     if (stream->alignment > 1)
5343       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5344     gst_pad_push (stream->pad, buffer);
5345
5346     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5347   }
5348
5349   /* we're going to modify the metadata */
5350   buf = gst_buffer_make_writable (buf);
5351
5352   if (G_UNLIKELY (stream->need_process))
5353     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5354
5355   if (!buf) {
5356     goto exit;
5357   }
5358
5359   GST_BUFFER_DTS (buf) = dts;
5360   GST_BUFFER_PTS (buf) = pts;
5361   GST_BUFFER_DURATION (buf) = duration;
5362   GST_BUFFER_OFFSET (buf) = -1;
5363   GST_BUFFER_OFFSET_END (buf) = -1;
5364
5365   if (G_UNLIKELY (stream->rgb8_palette))
5366     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5367
5368   if (G_UNLIKELY (stream->padding)) {
5369     gst_buffer_resize (buf, stream->padding, -1);
5370   }
5371 #if 0
5372   if (G_UNLIKELY (qtdemux->element_index)) {
5373     GstClockTime stream_time;
5374
5375     stream_time =
5376         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5377         timestamp);
5378     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5379       GST_LOG_OBJECT (qtdemux,
5380           "adding association %" GST_TIME_FORMAT "-> %"
5381           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5382       gst_index_add_association (qtdemux->element_index,
5383           qtdemux->index_id,
5384           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5385           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5386           GST_FORMAT_BYTES, byte_position, NULL);
5387     }
5388   }
5389 #endif
5390
5391   if (stream->need_clip)
5392     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5393
5394   if (G_UNLIKELY (buf == NULL))
5395     goto exit;
5396
5397   if (G_UNLIKELY (stream->discont)) {
5398     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5399     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5400     stream->discont = FALSE;
5401   } else {
5402     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5403   }
5404
5405   if (!keyframe) {
5406     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5407     stream->on_keyframe = FALSE;
5408   } else {
5409     stream->on_keyframe = TRUE;
5410   }
5411
5412
5413   GST_LOG_OBJECT (qtdemux,
5414       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5415       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5416       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5417       GST_PAD_NAME (stream->pad));
5418
5419   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5420     GstStructure *crypto_info;
5421     QtDemuxCencSampleSetInfo *info =
5422         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5423     gint index;
5424     GstEvent *event;
5425
5426     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5427       gst_pad_push_event (stream->pad, event);
5428     }
5429
5430     if (info->crypto_info == NULL) {
5431       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5432       gst_buffer_unref (buf);
5433       goto exit;
5434     }
5435
5436     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
5437     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5438       /* steal structure from array */
5439       crypto_info = g_ptr_array_index (info->crypto_info, index);
5440       g_ptr_array_index (info->crypto_info, index) = NULL;
5441       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
5442       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5443         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5444     }
5445   }
5446
5447   if (stream->alignment > 1)
5448     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5449
5450   ret = gst_pad_push (stream->pad, buf);
5451
5452   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5453     /* mark position in stream, we'll need this to know when to send GAP event */
5454     stream->segment.position = pts + duration;
5455   }
5456
5457 exit:
5458   return ret;
5459 }
5460
5461 static const QtDemuxRandomAccessEntry *
5462 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5463     GstClockTime pos, gboolean after)
5464 {
5465   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5466   guint n_entries = stream->n_ra_entries;
5467   guint i;
5468
5469   /* we assume the table is sorted */
5470   for (i = 0; i < n_entries; ++i) {
5471     if (entries[i].ts > pos)
5472       break;
5473   }
5474
5475   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5476    * probably okay to assume that the index lists the very first fragment */
5477   if (i == 0)
5478     return &entries[0];
5479
5480   if (after)
5481     return &entries[i];
5482   else
5483     return &entries[i - 1];
5484 }
5485
5486 static gboolean
5487 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5488 {
5489   const QtDemuxRandomAccessEntry *best_entry = NULL;
5490   guint i;
5491
5492   GST_OBJECT_LOCK (qtdemux);
5493
5494   g_assert (qtdemux->n_streams > 0);
5495
5496   for (i = 0; i < qtdemux->n_streams; i++) {
5497     const QtDemuxRandomAccessEntry *entry;
5498     QtDemuxStream *stream;
5499     gboolean is_audio_or_video;
5500
5501     stream = qtdemux->streams[i];
5502
5503     g_free (stream->samples);
5504     stream->samples = NULL;
5505     stream->n_samples = 0;
5506     stream->stbl_index = -1;    /* no samples have yet been parsed */
5507     stream->sample_index = -1;
5508
5509     if (stream->ra_entries == NULL)
5510       continue;
5511
5512     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5513       is_audio_or_video = TRUE;
5514     else
5515       is_audio_or_video = FALSE;
5516
5517     entry =
5518         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5519         stream->time_position, !is_audio_or_video);
5520
5521     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5522         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5523
5524     stream->pending_seek = entry;
5525
5526     /* decide position to jump to just based on audio/video tracks, not subs */
5527     if (!is_audio_or_video)
5528       continue;
5529
5530     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5531       best_entry = entry;
5532   }
5533
5534   if (best_entry == NULL) {
5535     GST_OBJECT_UNLOCK (qtdemux);
5536     return FALSE;
5537   }
5538
5539   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5540       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5541       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5542       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5543
5544   qtdemux->moof_offset = best_entry->moof_offset;
5545
5546   qtdemux_add_fragmented_samples (qtdemux);
5547
5548   GST_OBJECT_UNLOCK (qtdemux);
5549   return TRUE;
5550 }
5551
5552 static GstFlowReturn
5553 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5554 {
5555   GstFlowReturn ret = GST_FLOW_OK;
5556   GstBuffer *buf = NULL;
5557   QtDemuxStream *stream;
5558   GstClockTime min_time;
5559   guint64 offset = 0;
5560   GstClockTime dts = GST_CLOCK_TIME_NONE;
5561   GstClockTime pts = GST_CLOCK_TIME_NONE;
5562   GstClockTime duration = 0;
5563   gboolean keyframe = FALSE;
5564   guint sample_size = 0;
5565   gboolean empty = 0;
5566   guint size;
5567   gint index;
5568   gint i;
5569
5570   gst_qtdemux_push_pending_newsegment (qtdemux);
5571
5572   if (qtdemux->fragmented_seek_pending) {
5573     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5574     gst_qtdemux_do_fragmented_seek (qtdemux);
5575     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5576     qtdemux->fragmented_seek_pending = FALSE;
5577   }
5578
5579   /* Figure out the next stream sample to output, min_time is expressed in
5580    * global time and runs over the edit list segments. */
5581   min_time = G_MAXUINT64;
5582   index = -1;
5583   for (i = 0; i < qtdemux->n_streams; i++) {
5584     GstClockTime position;
5585
5586     stream = qtdemux->streams[i];
5587     position = stream->time_position;
5588
5589     /* position of -1 is EOS */
5590     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5591       min_time = position;
5592       index = i;
5593     }
5594   }
5595   /* all are EOS */
5596   if (G_UNLIKELY (index == -1)) {
5597     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5598     goto eos;
5599   }
5600
5601   /* check for segment end */
5602   if (G_UNLIKELY (qtdemux->segment.stop != -1
5603           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5604               || (qtdemux->segment.rate < 0
5605                   && qtdemux->segment.start > min_time))
5606           && qtdemux->streams[index]->on_keyframe)) {
5607     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5608     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5609     goto eos_stream;
5610   }
5611
5612   /* gap events for subtitle streams */
5613   for (i = 0; i < qtdemux->n_streams; i++) {
5614     stream = qtdemux->streams[i];
5615     if (stream->pad && (stream->subtype == FOURCC_subp
5616             || stream->subtype == FOURCC_text
5617             || stream->subtype == FOURCC_sbtl)) {
5618       /* send one second gap events until the stream catches up */
5619       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5620       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5621           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5622           stream->segment.position + GST_SECOND < min_time) {
5623         GstEvent *gap =
5624             gst_event_new_gap (stream->segment.position, GST_SECOND);
5625         gst_pad_push_event (stream->pad, gap);
5626         stream->segment.position += GST_SECOND;
5627       }
5628     }
5629   }
5630
5631   stream = qtdemux->streams[index];
5632   if (stream->new_caps) {
5633     gst_qtdemux_configure_stream (qtdemux, stream);
5634     qtdemux_do_allocation (qtdemux, stream);
5635   }
5636
5637   /* fetch info for the current sample of this stream */
5638   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5639               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5640     goto eos_stream;
5641
5642   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5643   if (G_UNLIKELY (qtdemux->
5644           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5645     if (stream->subtype == FOURCC_vide && !keyframe) {
5646       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5647       goto next;
5648     }
5649   }
5650
5651   GST_DEBUG_OBJECT (qtdemux,
5652       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5653       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5654       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5655       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5656
5657   if (G_UNLIKELY (empty)) {
5658     /* empty segment, push a gap and move to the next one */
5659     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5660     stream->segment.position = pts + duration;
5661     goto next;
5662   }
5663
5664   /* hmm, empty sample, skip and move to next sample */
5665   if (G_UNLIKELY (sample_size <= 0))
5666     goto next;
5667
5668   /* last pushed sample was out of boundary, goto next sample */
5669   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5670     goto next;
5671
5672   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5673     size = sample_size;
5674   } else {
5675     GST_DEBUG_OBJECT (qtdemux,
5676         "size %d larger than stream max_buffer_size %d, trimming",
5677         sample_size, stream->max_buffer_size);
5678     size =
5679         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5680   }
5681
5682   if (qtdemux->cenc_aux_info_offset > 0) {
5683     GstMapInfo map;
5684     GstByteReader br;
5685     GstBuffer *aux_info = NULL;
5686
5687     /* pull the data stored before the sample */
5688     ret =
5689         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5690         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5691     if (G_UNLIKELY (ret != GST_FLOW_OK))
5692       goto beach;
5693     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5694     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5695     gst_byte_reader_init (&br, map.data + 8, map.size);
5696     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5697             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5698       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5699       gst_buffer_unmap (aux_info, &map);
5700       gst_buffer_unref (aux_info);
5701       ret = GST_FLOW_ERROR;
5702       goto beach;
5703     }
5704     gst_buffer_unmap (aux_info, &map);
5705     gst_buffer_unref (aux_info);
5706   }
5707
5708   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5709       offset);
5710
5711   if (stream->use_allocator) {
5712     /* if we have a per-stream allocator, use it */
5713     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5714   }
5715
5716   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5717       size, &buf);
5718   if (G_UNLIKELY (ret != GST_FLOW_OK))
5719     goto beach;
5720
5721   if (size != sample_size) {
5722     pts += gst_util_uint64_scale_int (GST_SECOND,
5723         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5724     dts += gst_util_uint64_scale_int (GST_SECOND,
5725         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5726     duration = gst_util_uint64_scale_int (GST_SECOND,
5727         size / stream->bytes_per_frame, stream->timescale);
5728   }
5729
5730   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5731       dts, pts, duration, keyframe, min_time, offset);
5732
5733   if (size != sample_size) {
5734     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5735     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5736
5737     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5738         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5739     if (time_position >= segment->media_start) {
5740       /* inside the segment, update time_position, looks very familiar to
5741        * GStreamer segments, doesn't it? */
5742       stream->time_position = (time_position - segment->media_start) +
5743           segment->time;
5744     } else {
5745       /* not yet in segment, time does not yet increment. This means
5746        * that we are still prerolling keyframes to the decoder so it can
5747        * decode the first sample of the segment. */
5748       stream->time_position = segment->time;
5749     }
5750   }
5751
5752   /* combine flows */
5753   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5754   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5755    * we have no more data for the pad to push */
5756   if (ret == GST_FLOW_EOS)
5757     ret = GST_FLOW_OK;
5758
5759   stream->offset_in_sample += size;
5760   if (stream->offset_in_sample >= sample_size) {
5761     gst_qtdemux_advance_sample (qtdemux, stream);
5762   }
5763   goto beach;
5764
5765 next:
5766   gst_qtdemux_advance_sample (qtdemux, stream);
5767
5768 beach:
5769   return ret;
5770
5771   /* special cases */
5772 eos:
5773   {
5774     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5775     ret = GST_FLOW_EOS;
5776     goto beach;
5777   }
5778 eos_stream:
5779   {
5780     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5781     /* EOS will be raised if all are EOS */
5782     ret = GST_FLOW_OK;
5783     goto beach;
5784   }
5785 }
5786
5787 static void
5788 gst_qtdemux_loop (GstPad * pad)
5789 {
5790   GstQTDemux *qtdemux;
5791   guint64 cur_offset;
5792   GstFlowReturn ret;
5793
5794   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5795
5796   cur_offset = qtdemux->offset;
5797   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5798       cur_offset, qt_demux_state_string (qtdemux->state));
5799
5800   switch (qtdemux->state) {
5801     case QTDEMUX_STATE_INITIAL:
5802     case QTDEMUX_STATE_HEADER:
5803       ret = gst_qtdemux_loop_state_header (qtdemux);
5804       break;
5805     case QTDEMUX_STATE_MOVIE:
5806       ret = gst_qtdemux_loop_state_movie (qtdemux);
5807       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5808         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5809       }
5810       break;
5811     default:
5812       /* ouch */
5813       goto invalid_state;
5814   }
5815
5816   /* if something went wrong, pause */
5817   if (ret != GST_FLOW_OK)
5818     goto pause;
5819
5820 done:
5821   gst_object_unref (qtdemux);
5822   return;
5823
5824   /* ERRORS */
5825 invalid_state:
5826   {
5827     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5828         (NULL), ("streaming stopped, invalid state"));
5829     gst_pad_pause_task (pad);
5830     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5831     goto done;
5832   }
5833 pause:
5834   {
5835     const gchar *reason = gst_flow_get_name (ret);
5836
5837     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5838
5839     gst_pad_pause_task (pad);
5840
5841     /* fatal errors need special actions */
5842     /* check EOS */
5843     if (ret == GST_FLOW_EOS) {
5844       if (qtdemux->n_streams == 0) {
5845         /* we have no streams, post an error */
5846         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5847       }
5848       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5849         gint64 stop;
5850
5851         if ((stop = qtdemux->segment.stop) == -1)
5852           stop = qtdemux->segment.duration;
5853
5854         if (qtdemux->segment.rate >= 0) {
5855           GstMessage *message;
5856           GstEvent *event;
5857
5858           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5859           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5860               GST_FORMAT_TIME, stop);
5861           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5862           if (qtdemux->segment_seqnum) {
5863             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5864             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5865           }
5866           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5867           gst_qtdemux_push_event (qtdemux, event);
5868         } else {
5869           GstMessage *message;
5870           GstEvent *event;
5871
5872           /*  For Reverse Playback */
5873           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5874           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5875               GST_FORMAT_TIME, qtdemux->segment.start);
5876           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5877               qtdemux->segment.start);
5878           if (qtdemux->segment_seqnum) {
5879             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5880             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5881           }
5882           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5883           gst_qtdemux_push_event (qtdemux, event);
5884         }
5885       } else {
5886         GstEvent *event;
5887
5888         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5889         event = gst_event_new_eos ();
5890         if (qtdemux->segment_seqnum)
5891           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5892         gst_qtdemux_push_event (qtdemux, event);
5893       }
5894     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5895       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
5896       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5897     }
5898     goto done;
5899   }
5900 }
5901
5902 /*
5903  * has_next_entry
5904  *
5905  * Returns if there are samples to be played.
5906  */
5907 static gboolean
5908 has_next_entry (GstQTDemux * demux)
5909 {
5910   QtDemuxStream *stream;
5911   int i;
5912
5913   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5914
5915   for (i = 0; i < demux->n_streams; i++) {
5916     stream = demux->streams[i];
5917
5918     if (stream->sample_index == -1) {
5919       stream->sample_index = 0;
5920       stream->offset_in_sample = 0;
5921     }
5922
5923     if (stream->sample_index >= stream->n_samples) {
5924       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5925       continue;
5926     }
5927     GST_DEBUG_OBJECT (demux, "Found a sample");
5928     return TRUE;
5929   }
5930
5931   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5932   return FALSE;
5933 }
5934
5935 /*
5936  * next_entry_size
5937  *
5938  * Returns the size of the first entry at the current offset.
5939  * If -1, there are none (which means EOS or empty file).
5940  */
5941 static guint64
5942 next_entry_size (GstQTDemux * demux)
5943 {
5944   QtDemuxStream *stream;
5945   int i;
5946   int smallidx = -1;
5947   guint64 smalloffs = (guint64) - 1;
5948   QtDemuxSample *sample;
5949
5950   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5951       demux->offset);
5952
5953   for (i = 0; i < demux->n_streams; i++) {
5954     stream = demux->streams[i];
5955
5956     if (stream->sample_index == -1) {
5957       stream->sample_index = 0;
5958       stream->offset_in_sample = 0;
5959     }
5960
5961     if (stream->sample_index >= stream->n_samples) {
5962       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5963       continue;
5964     }
5965
5966     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5967       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5968           stream->sample_index);
5969       return -1;
5970     }
5971
5972     sample = &stream->samples[stream->sample_index];
5973
5974     GST_LOG_OBJECT (demux,
5975         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5976         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5977         sample->offset, sample->size);
5978
5979     if (((smalloffs == -1)
5980             || (sample->offset < smalloffs)) && (sample->size)) {
5981       smallidx = i;
5982       smalloffs = sample->offset;
5983     }
5984   }
5985
5986   GST_LOG_OBJECT (demux,
5987       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5988       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5989
5990   if (smallidx == -1)
5991     return -1;
5992
5993   stream = demux->streams[smallidx];
5994   sample = &stream->samples[stream->sample_index];
5995
5996   if (sample->offset >= demux->offset) {
5997     demux->todrop = sample->offset - demux->offset;
5998     return sample->size + demux->todrop;
5999   }
6000
6001   GST_DEBUG_OBJECT (demux,
6002       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6003   return -1;
6004 }
6005
6006 static void
6007 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6008 {
6009   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6010
6011   gst_element_post_message (GST_ELEMENT_CAST (demux),
6012       gst_message_new_element (GST_OBJECT_CAST (demux),
6013           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6014 }
6015
6016 static gboolean
6017 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6018 {
6019   GstEvent *event;
6020   gboolean res = 0;
6021
6022   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6023
6024   event =
6025       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6026       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6027       GST_SEEK_TYPE_NONE, -1);
6028
6029   /* store seqnum to drop flush events, they don't need to reach downstream */
6030   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6031   res = gst_pad_push_event (demux->sinkpad, event);
6032   demux->offset_seek_seqnum = 0;
6033
6034   return res;
6035 }
6036
6037 /* check for seekable upstream, above and beyond a mere query */
6038 static void
6039 gst_qtdemux_check_seekability (GstQTDemux * demux)
6040 {
6041   GstQuery *query;
6042   gboolean seekable = FALSE;
6043   gint64 start = -1, stop = -1;
6044
6045   if (demux->upstream_size)
6046     return;
6047
6048   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6049   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6050     GST_DEBUG_OBJECT (demux, "seeking query failed");
6051     goto done;
6052   }
6053
6054   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6055
6056   /* try harder to query upstream size if we didn't get it the first time */
6057   if (seekable && stop == -1) {
6058     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6059     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6060   }
6061
6062   /* if upstream doesn't know the size, it's likely that it's not seekable in
6063    * practice even if it technically may be seekable */
6064   if (seekable && (start != 0 || stop <= start)) {
6065     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6066     seekable = FALSE;
6067   }
6068
6069 done:
6070   gst_query_unref (query);
6071
6072   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6073       G_GUINT64_FORMAT ")", seekable, start, stop);
6074   demux->upstream_seekable = seekable;
6075   demux->upstream_size = seekable ? stop : -1;
6076 }
6077
6078 static void
6079 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6080 {
6081   g_return_if_fail (bytes <= demux->todrop);
6082
6083   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6084   gst_adapter_flush (demux->adapter, bytes);
6085   demux->neededbytes -= bytes;
6086   demux->offset += bytes;
6087   demux->todrop -= bytes;
6088 }
6089
6090 static void
6091 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6092 {
6093   if (G_UNLIKELY (demux->pending_newsegment)) {
6094     gint i;
6095
6096     gst_qtdemux_push_pending_newsegment (demux);
6097     /* clear to send tags on all streams */
6098     for (i = 0; i < demux->n_streams; i++) {
6099       QtDemuxStream *stream;
6100       stream = demux->streams[i];
6101       gst_qtdemux_push_tags (demux, stream);
6102       if (stream->sparse) {
6103         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6104         gst_pad_push_event (stream->pad,
6105             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6106       }
6107     }
6108   }
6109 }
6110
6111 static void
6112 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6113     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6114 {
6115   GstClockTime ts, dur;
6116   GstEvent *gap;
6117
6118   ts = pos;
6119   dur =
6120       stream->segments[segment_index].duration - (pos -
6121       stream->segments[segment_index].time);
6122   gap = gst_event_new_gap (ts, dur);
6123   stream->time_position += dur;
6124
6125   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6126       "segment: %" GST_PTR_FORMAT, gap);
6127   gst_pad_push_event (stream->pad, gap);
6128 }
6129
6130 static void
6131 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6132     QtDemuxStream * stream)
6133 {
6134   gint i;
6135
6136   /* Push any initial gap segments before proceeding to the
6137    * 'real' data */
6138   for (i = 0; i < stream->n_segments; i++) {
6139     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6140
6141     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6142       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6143           stream->time_position);
6144     } else {
6145       /* Only support empty segment at the beginning followed by
6146        * one non-empty segment, this was checked when parsing the
6147        * edts atom, arriving here is unexpected */
6148       g_assert (i + 1 == stream->n_segments);
6149       break;
6150     }
6151   }
6152 }
6153
6154 static GstFlowReturn
6155 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6156 {
6157   GstQTDemux *demux;
6158
6159   demux = GST_QTDEMUX (parent);
6160
6161   GST_DEBUG_OBJECT (demux,
6162       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6163       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6164       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6165       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6166       gst_buffer_get_size (inbuf), demux->offset);
6167
6168   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6169     gboolean is_gap_input = FALSE;
6170     gint i;
6171
6172     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6173
6174     for (i = 0; i < demux->n_streams; i++) {
6175       demux->streams[i]->discont = TRUE;
6176     }
6177
6178     /* Check if we can land back on our feet in the case where upstream is
6179      * handling the seeking/pushing of samples with gaps in between (like
6180      * in the case of trick-mode DASH for example) */
6181     if (demux->upstream_format_is_time
6182         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6183       gint i;
6184       for (i = 0; i < demux->n_streams; i++) {
6185         guint32 res;
6186         GST_LOG_OBJECT (demux,
6187             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6188             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6189         res =
6190             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6191             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6192         if (res != -1) {
6193           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6194           GST_LOG_OBJECT (demux,
6195               "Checking if sample %d from stream %d is valid (offset:%"
6196               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6197               sample->offset, sample->size);
6198           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6199             GST_LOG_OBJECT (demux,
6200                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6201                 res);
6202             is_gap_input = TRUE;
6203             /* We can go back to standard playback mode */
6204             demux->state = QTDEMUX_STATE_MOVIE;
6205             /* Remember which sample this stream is at */
6206             demux->streams[i]->sample_index = res;
6207             /* Finally update all push-based values to the expected values */
6208             demux->neededbytes = demux->streams[i]->samples[res].size;
6209             demux->todrop = 0;
6210             demux->offset = GST_BUFFER_OFFSET (inbuf);
6211           }
6212         }
6213       }
6214       if (!is_gap_input) {
6215         /* Reset state if it's a real discont */
6216         demux->neededbytes = 16;
6217         demux->state = QTDEMUX_STATE_INITIAL;
6218         demux->offset = GST_BUFFER_OFFSET (inbuf);
6219       }
6220     }
6221     /* Reverse fragmented playback, need to flush all we have before
6222      * consuming a new fragment.
6223      * The samples array have the timestamps calculated by accumulating the
6224      * durations but this won't work for reverse playback of fragments as
6225      * the timestamps of a subsequent fragment should be smaller than the
6226      * previously received one. */
6227     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6228       gst_qtdemux_process_adapter (demux, TRUE);
6229       for (i = 0; i < demux->n_streams; i++)
6230         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6231     }
6232   }
6233
6234   gst_adapter_push (demux->adapter, inbuf);
6235
6236   GST_DEBUG_OBJECT (demux,
6237       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6238       demux->neededbytes, gst_adapter_available (demux->adapter));
6239
6240   return gst_qtdemux_process_adapter (demux, FALSE);
6241 }
6242
6243 static GstFlowReturn
6244 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6245 {
6246   GstFlowReturn ret = GST_FLOW_OK;
6247
6248   /* we never really mean to buffer that much */
6249   if (demux->neededbytes == -1) {
6250     goto eos;
6251   }
6252
6253   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6254       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6255
6256 #ifndef GST_DISABLE_GST_DEBUG
6257     {
6258       guint64 discont_offset, distance_from_discont;
6259
6260       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6261       distance_from_discont =
6262           gst_adapter_distance_from_discont (demux->adapter);
6263
6264       GST_DEBUG_OBJECT (demux,
6265           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6266           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6267           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6268           demux->offset, discont_offset, distance_from_discont);
6269     }
6270 #endif
6271
6272     switch (demux->state) {
6273       case QTDEMUX_STATE_INITIAL:{
6274         const guint8 *data;
6275         guint32 fourcc;
6276         guint64 size;
6277
6278         gst_qtdemux_check_seekability (demux);
6279
6280         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6281
6282         /* get fourcc/length, set neededbytes */
6283         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6284             &size, &fourcc);
6285         gst_adapter_unmap (demux->adapter);
6286         data = NULL;
6287         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6288             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6289         if (size == 0) {
6290           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6291               (_("This file is invalid and cannot be played.")),
6292               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6293                   GST_FOURCC_ARGS (fourcc)));
6294           ret = GST_FLOW_ERROR;
6295           break;
6296         }
6297         if (fourcc == FOURCC_mdat) {
6298           gint next_entry = next_entry_size (demux);
6299           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6300             /* we have the headers, start playback */
6301             demux->state = QTDEMUX_STATE_MOVIE;
6302             demux->neededbytes = next_entry;
6303             demux->mdatleft = size;
6304           } else {
6305             /* no headers yet, try to get them */
6306             guint bs;
6307             gboolean res;
6308             guint64 old, target;
6309
6310           buffer_data:
6311             old = demux->offset;
6312             target = old + size;
6313
6314             /* try to jump over the atom with a seek */
6315             /* only bother if it seems worth doing so,
6316              * and avoids possible upstream/server problems */
6317             if (demux->upstream_seekable &&
6318                 demux->upstream_size > 4 * (1 << 20)) {
6319               res = qtdemux_seek_offset (demux, target);
6320             } else {
6321               GST_DEBUG_OBJECT (demux, "skipping seek");
6322               res = FALSE;
6323             }
6324
6325             if (res) {
6326               GST_DEBUG_OBJECT (demux, "seek success");
6327               /* remember the offset fo the first mdat so we can seek back to it
6328                * after we have the headers */
6329               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6330                 demux->first_mdat = old;
6331                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6332                     demux->first_mdat);
6333               }
6334               /* seek worked, continue reading */
6335               demux->offset = target;
6336               demux->neededbytes = 16;
6337               demux->state = QTDEMUX_STATE_INITIAL;
6338             } else {
6339               /* seek failed, need to buffer */
6340               demux->offset = old;
6341               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6342               /* there may be multiple mdat (or alike) buffers */
6343               /* sanity check */
6344               if (demux->mdatbuffer)
6345                 bs = gst_buffer_get_size (demux->mdatbuffer);
6346               else
6347                 bs = 0;
6348               if (size + bs > 10 * (1 << 20))
6349                 goto no_moov;
6350               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6351               demux->neededbytes = size;
6352               if (!demux->mdatbuffer)
6353                 demux->mdatoffset = demux->offset;
6354             }
6355           }
6356         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6357           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6358               (_("This file is invalid and cannot be played.")),
6359               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6360                   GST_FOURCC_ARGS (fourcc), size));
6361           ret = GST_FLOW_ERROR;
6362           break;
6363         } else {
6364           /* this means we already started buffering and still no moov header,
6365            * let's continue buffering everything till we get moov */
6366           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6367                   || fourcc == FOURCC_moof))
6368             goto buffer_data;
6369           demux->neededbytes = size;
6370           demux->state = QTDEMUX_STATE_HEADER;
6371         }
6372         break;
6373       }
6374       case QTDEMUX_STATE_HEADER:{
6375         const guint8 *data;
6376         guint32 fourcc;
6377
6378         GST_DEBUG_OBJECT (demux, "In header");
6379
6380         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6381
6382         /* parse the header */
6383         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6384             &fourcc);
6385         if (fourcc == FOURCC_moov) {
6386           gint n;
6387
6388           /* in usual fragmented setup we could try to scan for more
6389            * and end up at the the moov (after mdat) again */
6390           if (demux->got_moov && demux->n_streams > 0 &&
6391               (!demux->fragmented
6392                   || demux->last_moov_offset == demux->offset)) {
6393             GST_DEBUG_OBJECT (demux,
6394                 "Skipping moov atom as we have (this) one already");
6395           } else {
6396             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6397
6398             if (demux->got_moov && demux->fragmented) {
6399               GST_DEBUG_OBJECT (demux,
6400                   "Got a second moov, clean up data from old one");
6401               if (demux->moov_node_compressed) {
6402                 g_node_destroy (demux->moov_node_compressed);
6403                 if (demux->moov_node)
6404                   g_free (demux->moov_node->data);
6405               }
6406               demux->moov_node_compressed = NULL;
6407               if (demux->moov_node)
6408                 g_node_destroy (demux->moov_node);
6409               demux->moov_node = NULL;
6410             } else {
6411               /* prepare newsegment to send when streaming actually starts */
6412               if (!demux->pending_newsegment) {
6413                 demux->pending_newsegment =
6414                     gst_event_new_segment (&demux->segment);
6415                 if (demux->segment_seqnum)
6416                   gst_event_set_seqnum (demux->pending_newsegment,
6417                       demux->segment_seqnum);
6418               }
6419             }
6420
6421             demux->last_moov_offset = demux->offset;
6422
6423             qtdemux_parse_moov (demux, data, demux->neededbytes);
6424             qtdemux_node_dump (demux, demux->moov_node);
6425             qtdemux_parse_tree (demux);
6426             qtdemux_prepare_streams (demux);
6427             if (!demux->got_moov)
6428               qtdemux_expose_streams (demux);
6429             else {
6430
6431               for (n = 0; n < demux->n_streams; n++) {
6432                 QtDemuxStream *stream = demux->streams[n];
6433
6434                 gst_qtdemux_configure_stream (demux, stream);
6435               }
6436             }
6437
6438             demux->got_moov = TRUE;
6439             gst_qtdemux_check_send_pending_segment (demux);
6440
6441             /* fragmented streams headers shouldn't contain edts atoms */
6442             if (!demux->fragmented) {
6443               for (n = 0; n < demux->n_streams; n++) {
6444                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6445                     demux->streams[n]);
6446               }
6447             }
6448
6449             if (demux->moov_node_compressed) {
6450               g_node_destroy (demux->moov_node_compressed);
6451               g_free (demux->moov_node->data);
6452             }
6453             demux->moov_node_compressed = NULL;
6454             g_node_destroy (demux->moov_node);
6455             demux->moov_node = NULL;
6456             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6457           }
6458         } else if (fourcc == FOURCC_moof) {
6459           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6460             guint64 dist = 0;
6461             GstClockTime prev_pts;
6462             guint64 prev_offset;
6463             guint64 adapter_discont_offset, adapter_discont_dist;
6464
6465             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6466
6467             /*
6468              * The timestamp of the moof buffer is relevant as some scenarios
6469              * won't have the initial timestamp in the atoms. Whenever a new
6470              * buffer has started, we get that buffer's PTS and use it as a base
6471              * timestamp for the trun entries.
6472              *
6473              * To keep track of the current buffer timestamp and starting point
6474              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6475              * from the beggining of the buffer, with the distance and demux->offset
6476              * we know if it is still the same buffer or not.
6477              */
6478             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6479             prev_offset = demux->offset - dist;
6480             if (demux->fragment_start_offset == -1
6481                 || prev_offset > demux->fragment_start_offset) {
6482               demux->fragment_start_offset = prev_offset;
6483               demux->fragment_start = prev_pts;
6484               GST_DEBUG_OBJECT (demux,
6485                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6486                   GST_TIME_FORMAT, demux->fragment_start_offset,
6487                   GST_TIME_ARGS (demux->fragment_start));
6488             }
6489
6490             /* We can't use prev_offset() here because this would require
6491              * upstream to set consistent and correct offsets on all buffers
6492              * since the discont. Nothing ever did that in the past and we
6493              * would break backwards compatibility here then.
6494              * Instead take the offset we had at the last discont and count
6495              * the bytes from there. This works with old code as there would
6496              * be no discont between moov and moof, and also works with
6497              * adaptivedemux which correctly sets offset and will set the
6498              * DISCONT flag accordingly when needed.
6499              *
6500              * We also only do this for upstream TIME segments as otherwise
6501              * there are potential backwards compatibility problems with
6502              * seeking in PUSH mode and upstream providing inconsistent
6503              * timestamps. */
6504             adapter_discont_offset =
6505                 gst_adapter_offset_at_discont (demux->adapter);
6506             adapter_discont_dist =
6507                 gst_adapter_distance_from_discont (demux->adapter);
6508
6509             GST_DEBUG_OBJECT (demux,
6510                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6511                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6512                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6513
6514             if (demux->upstream_format_is_time) {
6515               demux->moof_offset = adapter_discont_offset;
6516               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6517                 demux->moof_offset += adapter_discont_dist;
6518               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6519                 demux->moof_offset = demux->offset;
6520             } else {
6521               demux->moof_offset = demux->offset;
6522             }
6523
6524             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6525                     demux->moof_offset, NULL)) {
6526               gst_adapter_unmap (demux->adapter);
6527               ret = GST_FLOW_ERROR;
6528               goto done;
6529             }
6530             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6531             if (demux->mss_mode && !demux->exposed) {
6532               if (!demux->pending_newsegment) {
6533                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6534                 demux->pending_newsegment =
6535                     gst_event_new_segment (&demux->segment);
6536                 if (demux->segment_seqnum)
6537                   gst_event_set_seqnum (demux->pending_newsegment,
6538                       demux->segment_seqnum);
6539               }
6540               qtdemux_expose_streams (demux);
6541             }
6542           } else {
6543             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6544           }
6545         } else if (fourcc == FOURCC_ftyp) {
6546           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6547           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6548         } else if (fourcc == FOURCC_uuid) {
6549           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6550           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6551         } else if (fourcc == FOURCC_sidx) {
6552           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6553           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6554         } else {
6555           GST_WARNING_OBJECT (demux,
6556               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6557               GST_FOURCC_ARGS (fourcc));
6558           /* Let's jump that one and go back to initial state */
6559         }
6560         gst_adapter_unmap (demux->adapter);
6561         data = NULL;
6562
6563         if (demux->mdatbuffer && demux->n_streams) {
6564           gsize remaining_data_size = 0;
6565
6566           /* the mdat was before the header */
6567           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6568               demux->n_streams, demux->mdatbuffer);
6569           /* restore our adapter/offset view of things with upstream;
6570            * put preceding buffered data ahead of current moov data.
6571            * This should also handle evil mdat, moov, mdat cases and alike */
6572           gst_adapter_flush (demux->adapter, demux->neededbytes);
6573
6574           /* Store any remaining data after the mdat for later usage */
6575           remaining_data_size = gst_adapter_available (demux->adapter);
6576           if (remaining_data_size > 0) {
6577             g_assert (demux->restoredata_buffer == NULL);
6578             demux->restoredata_buffer =
6579                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6580             demux->restoredata_offset = demux->offset + demux->neededbytes;
6581             GST_DEBUG_OBJECT (demux,
6582                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6583                 G_GUINT64_FORMAT, remaining_data_size,
6584                 demux->restoredata_offset);
6585           }
6586
6587           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6588           demux->mdatbuffer = NULL;
6589           demux->offset = demux->mdatoffset;
6590           demux->neededbytes = next_entry_size (demux);
6591           demux->state = QTDEMUX_STATE_MOVIE;
6592           demux->mdatleft = gst_adapter_available (demux->adapter);
6593         } else {
6594           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6595           gst_adapter_flush (demux->adapter, demux->neededbytes);
6596
6597           /* only go back to the mdat if there are samples to play */
6598           if (demux->got_moov && demux->first_mdat != -1
6599               && has_next_entry (demux)) {
6600             gboolean res;
6601
6602             /* we need to seek back */
6603             res = qtdemux_seek_offset (demux, demux->first_mdat);
6604             if (res) {
6605               demux->offset = demux->first_mdat;
6606             } else {
6607               GST_DEBUG_OBJECT (demux, "Seek back failed");
6608             }
6609           } else {
6610             demux->offset += demux->neededbytes;
6611           }
6612           demux->neededbytes = 16;
6613           demux->state = QTDEMUX_STATE_INITIAL;
6614         }
6615
6616         break;
6617       }
6618       case QTDEMUX_STATE_BUFFER_MDAT:{
6619         GstBuffer *buf;
6620         guint8 fourcc[4];
6621
6622         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6623             demux->offset);
6624         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6625         gst_buffer_extract (buf, 0, fourcc, 4);
6626         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6627             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6628         if (demux->mdatbuffer)
6629           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6630         else
6631           demux->mdatbuffer = buf;
6632         demux->offset += demux->neededbytes;
6633         demux->neededbytes = 16;
6634         demux->state = QTDEMUX_STATE_INITIAL;
6635         gst_qtdemux_post_progress (demux, 1, 1);
6636
6637         break;
6638       }
6639       case QTDEMUX_STATE_MOVIE:{
6640         QtDemuxStream *stream = NULL;
6641         QtDemuxSample *sample;
6642         int i = -1;
6643         GstClockTime dts, pts, duration;
6644         gboolean keyframe;
6645
6646         GST_DEBUG_OBJECT (demux,
6647             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6648
6649         if (demux->fragmented) {
6650           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6651               demux->mdatleft);
6652           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6653             /* if needed data starts within this atom,
6654              * then it should not exceed this atom */
6655             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6656               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6657                   (_("This file is invalid and cannot be played.")),
6658                   ("sample data crosses atom boundary"));
6659               ret = GST_FLOW_ERROR;
6660               break;
6661             }
6662             demux->mdatleft -= demux->neededbytes;
6663           } else {
6664             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6665             /* so we are dropping more than left in this atom */
6666             gst_qtdemux_drop_data (demux, demux->mdatleft);
6667             demux->mdatleft = 0;
6668
6669             /* need to resume atom parsing so we do not miss any other pieces */
6670             demux->state = QTDEMUX_STATE_INITIAL;
6671             demux->neededbytes = 16;
6672
6673             /* check if there was any stored post mdat data from previous buffers */
6674             if (demux->restoredata_buffer) {
6675               g_assert (gst_adapter_available (demux->adapter) == 0);
6676
6677               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6678               demux->restoredata_buffer = NULL;
6679               demux->offset = demux->restoredata_offset;
6680             }
6681
6682             break;
6683           }
6684         }
6685
6686         if (demux->todrop) {
6687           if (demux->cenc_aux_info_offset > 0) {
6688             GstByteReader br;
6689             const guint8 *data;
6690
6691             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6692             data = gst_adapter_map (demux->adapter, demux->todrop);
6693             gst_byte_reader_init (&br, data + 8, demux->todrop);
6694             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6695                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6696               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6697               ret = GST_FLOW_ERROR;
6698               gst_adapter_unmap (demux->adapter);
6699               g_free (demux->cenc_aux_info_sizes);
6700               demux->cenc_aux_info_sizes = NULL;
6701               goto done;
6702             }
6703             demux->cenc_aux_info_offset = 0;
6704             g_free (demux->cenc_aux_info_sizes);
6705             demux->cenc_aux_info_sizes = NULL;
6706             gst_adapter_unmap (demux->adapter);
6707           }
6708           gst_qtdemux_drop_data (demux, demux->todrop);
6709         }
6710
6711         /* first buffer? */
6712         /* initial newsegment sent here after having added pads,
6713          * possible others in sink_event */
6714         gst_qtdemux_check_send_pending_segment (demux);
6715
6716         /* Figure out which stream this packet belongs to */
6717         for (i = 0; i < demux->n_streams; i++) {
6718           stream = demux->streams[i];
6719           if (stream->sample_index >= stream->n_samples)
6720             continue;
6721           GST_LOG_OBJECT (demux,
6722               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6723               " / size:%d)", i, stream->sample_index,
6724               stream->samples[stream->sample_index].offset,
6725               stream->samples[stream->sample_index].size);
6726
6727           if (stream->samples[stream->sample_index].offset == demux->offset)
6728             break;
6729         }
6730
6731         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6732           goto unknown_stream;
6733
6734         if (stream->new_caps) {
6735           gst_qtdemux_configure_stream (demux, stream);
6736         }
6737
6738         /* Put data in a buffer, set timestamps, caps, ... */
6739         sample = &stream->samples[stream->sample_index];
6740
6741         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6742           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6743               GST_FOURCC_ARGS (stream->fourcc));
6744
6745           dts = QTSAMPLE_DTS (stream, sample);
6746           pts = QTSAMPLE_PTS (stream, sample);
6747           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6748           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6749
6750           /* check for segment end */
6751           if (G_UNLIKELY (demux->segment.stop != -1
6752                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6753             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6754             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6755
6756             /* skip this data, stream is EOS */
6757             gst_adapter_flush (demux->adapter, demux->neededbytes);
6758
6759             /* check if all streams are eos */
6760             ret = GST_FLOW_EOS;
6761             for (i = 0; i < demux->n_streams; i++) {
6762               if (!STREAM_IS_EOS (demux->streams[i])) {
6763                 ret = GST_FLOW_OK;
6764                 break;
6765               }
6766             }
6767
6768             if (ret == GST_FLOW_EOS) {
6769               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6770               goto eos;
6771             }
6772           } else {
6773             GstBuffer *outbuf;
6774
6775             outbuf =
6776                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6777
6778             /* FIXME: should either be an assert or a plain check */
6779             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6780
6781             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6782                 dts, pts, duration, keyframe, dts, demux->offset);
6783           }
6784
6785           /* combine flows */
6786           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6787           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6788             goto non_ok_unlinked_flow;
6789         } else {
6790           /* skip this data, stream is EOS */
6791           gst_adapter_flush (demux->adapter, demux->neededbytes);
6792         }
6793
6794         stream->sample_index++;
6795         stream->offset_in_sample = 0;
6796
6797         /* update current offset and figure out size of next buffer */
6798         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6799             demux->offset, demux->neededbytes);
6800         demux->offset += demux->neededbytes;
6801         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6802             demux->offset);
6803
6804         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6805           if (demux->fragmented) {
6806             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6807             /* there may be more to follow, only finish this atom */
6808             demux->todrop = demux->mdatleft;
6809             demux->neededbytes = demux->todrop;
6810             break;
6811           }
6812           goto eos;
6813         }
6814         break;
6815       }
6816       default:
6817         goto invalid_state;
6818     }
6819   }
6820
6821   /* when buffering movie data, at least show user something is happening */
6822   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6823       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6824     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6825         demux->neededbytes);
6826   }
6827 done:
6828
6829   return ret;
6830
6831   /* ERRORS */
6832 non_ok_unlinked_flow:
6833   {
6834     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6835         gst_flow_get_name (ret));
6836     return ret;
6837   }
6838 unknown_stream:
6839   {
6840     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6841     ret = GST_FLOW_ERROR;
6842     goto done;
6843   }
6844 eos:
6845   {
6846     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6847     ret = GST_FLOW_EOS;
6848     goto done;
6849   }
6850 invalid_state:
6851   {
6852     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6853         (NULL), ("qtdemuxer invalid state %d", demux->state));
6854     ret = GST_FLOW_ERROR;
6855     goto done;
6856   }
6857 no_moov:
6858   {
6859     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6860         (NULL), ("no 'moov' atom within the first 10 MB"));
6861     ret = GST_FLOW_ERROR;
6862     goto done;
6863   }
6864 }
6865
6866 static gboolean
6867 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6868 {
6869   GstQuery *query;
6870   gboolean pull_mode;
6871
6872   query = gst_query_new_scheduling ();
6873
6874   if (!gst_pad_peer_query (sinkpad, query)) {
6875     gst_query_unref (query);
6876     goto activate_push;
6877   }
6878
6879   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6880       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6881   gst_query_unref (query);
6882
6883   if (!pull_mode)
6884     goto activate_push;
6885
6886   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6887   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6888
6889 activate_push:
6890   {
6891     GST_DEBUG_OBJECT (sinkpad, "activating push");
6892     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6893   }
6894 }
6895
6896 static gboolean
6897 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6898     GstPadMode mode, gboolean active)
6899 {
6900   gboolean res;
6901   GstQTDemux *demux = GST_QTDEMUX (parent);
6902
6903   switch (mode) {
6904     case GST_PAD_MODE_PUSH:
6905       demux->pullbased = FALSE;
6906       res = TRUE;
6907       break;
6908     case GST_PAD_MODE_PULL:
6909       if (active) {
6910         demux->pullbased = TRUE;
6911         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6912             sinkpad, NULL);
6913       } else {
6914         res = gst_pad_stop_task (sinkpad);
6915       }
6916       break;
6917     default:
6918       res = FALSE;
6919       break;
6920   }
6921   return res;
6922 }
6923
6924 #ifdef HAVE_ZLIB
6925 static void *
6926 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
6927 {
6928   guint8 *buffer;
6929   z_stream z;
6930   int ret;
6931
6932   memset (&z, 0, sizeof (z));
6933   z.zalloc = NULL;
6934   z.zfree = NULL;
6935   z.opaque = NULL;
6936
6937   if ((ret = inflateInit (&z)) != Z_OK) {
6938     GST_ERROR ("inflateInit() returned %d", ret);
6939     return NULL;
6940   }
6941
6942   z.next_in = z_buffer;
6943   z.avail_in = z_length;
6944
6945   buffer = (guint8 *) g_malloc (*length);
6946   z.avail_out = *length;
6947   z.next_out = (Bytef *) buffer;
6948   do {
6949     ret = inflate (&z, Z_NO_FLUSH);
6950     if (ret == Z_STREAM_END) {
6951       break;
6952     } else if (ret != Z_OK) {
6953       GST_WARNING ("inflate() returned %d", ret);
6954       break;
6955     }
6956
6957     *length += 4096;
6958     buffer = (guint8 *) g_realloc (buffer, *length);
6959     z.next_out = (Bytef *) (buffer + z.total_out);
6960     z.avail_out += 4096;
6961   } while (z.avail_in > 0);
6962
6963   if (ret != Z_STREAM_END) {
6964     g_free (buffer);
6965     buffer = NULL;
6966     *length = 0;
6967   } else {
6968     *length = z.total_out;
6969   }
6970
6971   inflateEnd (&z);
6972
6973   return buffer;
6974 }
6975 #endif /* HAVE_ZLIB */
6976
6977 static gboolean
6978 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6979 {
6980   GNode *cmov;
6981
6982   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6983
6984   /* counts as header data */
6985   qtdemux->header_size += length;
6986
6987   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6988   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6989
6990   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6991   if (cmov) {
6992     guint32 method;
6993     GNode *dcom;
6994     GNode *cmvd;
6995     guint32 dcom_len;
6996
6997     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6998     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6999     if (dcom == NULL || cmvd == NULL)
7000       goto invalid_compression;
7001
7002     dcom_len = QT_UINT32 (dcom->data);
7003     if (dcom_len < 12)
7004       goto invalid_compression;
7005
7006     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7007     switch (method) {
7008 #ifdef HAVE_ZLIB
7009       case FOURCC_zlib:{
7010         guint uncompressed_length;
7011         guint compressed_length;
7012         guint8 *buf;
7013         guint32 cmvd_len;
7014
7015         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7016         if (cmvd_len < 12)
7017           goto invalid_compression;
7018
7019         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7020         compressed_length = cmvd_len - 12;
7021         GST_LOG ("length = %u", uncompressed_length);
7022
7023         buf =
7024             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7025             compressed_length, &uncompressed_length);
7026
7027         if (buf) {
7028           qtdemux->moov_node_compressed = qtdemux->moov_node;
7029           qtdemux->moov_node = g_node_new (buf);
7030
7031           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7032               uncompressed_length);
7033         }
7034         break;
7035       }
7036 #endif /* HAVE_ZLIB */
7037       default:
7038         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7039             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7040         break;
7041     }
7042   }
7043   return TRUE;
7044
7045   /* ERRORS */
7046 invalid_compression:
7047   {
7048     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7049     return FALSE;
7050   }
7051 }
7052
7053 static gboolean
7054 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7055     const guint8 * end)
7056 {
7057   while (G_UNLIKELY (buf < end)) {
7058     GNode *child;
7059     guint32 len;
7060
7061     if (G_UNLIKELY (buf + 4 > end)) {
7062       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7063       break;
7064     }
7065     len = QT_UINT32 (buf);
7066     if (G_UNLIKELY (len == 0)) {
7067       GST_LOG_OBJECT (qtdemux, "empty container");
7068       break;
7069     }
7070     if (G_UNLIKELY (len < 8)) {
7071       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7072       break;
7073     }
7074     if (G_UNLIKELY (len > (end - buf))) {
7075       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7076           (gint) (end - buf));
7077       break;
7078     }
7079
7080     child = g_node_new ((guint8 *) buf);
7081     g_node_append (node, child);
7082     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7083     qtdemux_parse_node (qtdemux, child, buf, len);
7084
7085     buf += len;
7086   }
7087   return TRUE;
7088 }
7089
7090 static gboolean
7091 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7092     GNode * xdxt)
7093 {
7094   int len = QT_UINT32 (xdxt->data);
7095   guint8 *buf = xdxt->data;
7096   guint8 *end = buf + len;
7097   GstBuffer *buffer;
7098
7099   /* skip size and type */
7100   buf += 8;
7101   end -= 8;
7102
7103   while (buf < end) {
7104     gint size;
7105     guint32 type;
7106
7107     size = QT_UINT32 (buf);
7108     type = QT_FOURCC (buf + 4);
7109
7110     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7111
7112     if (buf + size > end || size <= 0)
7113       break;
7114
7115     buf += 8;
7116     size -= 8;
7117
7118     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7119         GST_FOURCC_ARGS (type));
7120
7121     switch (type) {
7122       case FOURCC_tCtH:
7123         buffer = gst_buffer_new_and_alloc (size);
7124         gst_buffer_fill (buffer, 0, buf, size);
7125         stream->buffers = g_slist_append (stream->buffers, buffer);
7126         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7127         break;
7128       case FOURCC_tCt_:
7129         buffer = gst_buffer_new_and_alloc (size);
7130         gst_buffer_fill (buffer, 0, buf, size);
7131         stream->buffers = g_slist_append (stream->buffers, buffer);
7132         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7133         break;
7134       case FOURCC_tCtC:
7135         buffer = gst_buffer_new_and_alloc (size);
7136         gst_buffer_fill (buffer, 0, buf, size);
7137         stream->buffers = g_slist_append (stream->buffers, buffer);
7138         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7139         break;
7140       default:
7141         GST_WARNING_OBJECT (qtdemux,
7142             "unknown theora cookie %" GST_FOURCC_FORMAT,
7143             GST_FOURCC_ARGS (type));
7144         break;
7145     }
7146     buf += size;
7147   }
7148   return TRUE;
7149 }
7150
7151 static gboolean
7152 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7153     guint length)
7154 {
7155   guint32 fourcc = 0;
7156   guint32 node_length = 0;
7157   const QtNodeType *type;
7158   const guint8 *end;
7159
7160   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7161
7162   if (G_UNLIKELY (length < 8))
7163     goto not_enough_data;
7164
7165   node_length = QT_UINT32 (buffer);
7166   fourcc = QT_FOURCC (buffer + 4);
7167
7168   /* ignore empty nodes */
7169   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7170     return TRUE;
7171
7172   type = qtdemux_type_get (fourcc);
7173
7174   end = buffer + length;
7175
7176   GST_LOG_OBJECT (qtdemux,
7177       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7178       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7179
7180   if (node_length > length)
7181     goto broken_atom_size;
7182
7183   if (type->flags & QT_FLAG_CONTAINER) {
7184     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7185   } else {
7186     switch (fourcc) {
7187       case FOURCC_stsd:
7188       {
7189         if (node_length < 20) {
7190           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7191           break;
7192         }
7193         GST_DEBUG_OBJECT (qtdemux,
7194             "parsing stsd (sample table, sample description) atom");
7195         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7196         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7197         break;
7198       }
7199       case FOURCC_mp4a:
7200       case FOURCC_alac:
7201       case FOURCC_fLaC:
7202       {
7203         guint32 version;
7204         guint32 offset;
7205         guint min_size;
7206
7207         /* also read alac (or whatever) in stead of mp4a in the following,
7208          * since a similar layout is used in other cases as well */
7209         if (fourcc == FOURCC_mp4a)
7210           min_size = 20;
7211         else if (fourcc == FOURCC_fLaC)
7212           min_size = 86;
7213         else
7214           min_size = 40;
7215
7216         /* There are two things we might encounter here: a true mp4a atom, and
7217            an mp4a entry in an stsd atom. The latter is what we're interested
7218            in, and it looks like an atom, but isn't really one. The true mp4a
7219            atom is short, so we detect it based on length here. */
7220         if (length < min_size) {
7221           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7222               GST_FOURCC_ARGS (fourcc));
7223           break;
7224         }
7225
7226         /* 'version' here is the sound sample description version. Types 0 and
7227            1 are documented in the QTFF reference, but type 2 is not: it's
7228            described in Apple header files instead (struct SoundDescriptionV2
7229            in Movies.h) */
7230         version = QT_UINT16 (buffer + 16);
7231
7232         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7233             GST_FOURCC_ARGS (fourcc), version);
7234
7235         /* parse any esds descriptors */
7236         switch (version) {
7237           case 0:
7238             offset = 0x24;
7239             break;
7240           case 1:
7241             offset = 0x34;
7242             break;
7243           case 2:
7244             offset = 0x48;
7245             break;
7246           default:
7247             GST_WARNING_OBJECT (qtdemux,
7248                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7249                 GST_FOURCC_ARGS (fourcc), version);
7250             offset = 0;
7251             break;
7252         }
7253         if (offset)
7254           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7255         break;
7256       }
7257       case FOURCC_mp4v:
7258       case FOURCC_MP4V:
7259       case FOURCC_fmp4:
7260       case FOURCC_FMP4:
7261       case FOURCC_apcs:
7262       case FOURCC_apch:
7263       case FOURCC_apcn:
7264       case FOURCC_apco:
7265       case FOURCC_ap4h:
7266       case FOURCC_xvid:
7267       case FOURCC_XVID:
7268       case FOURCC_H264:
7269       case FOURCC_avc1:
7270       case FOURCC_avc3:
7271       case FOURCC_H265:
7272       case FOURCC_hvc1:
7273       case FOURCC_hev1:
7274       case FOURCC_mjp2:
7275       case FOURCC_encv:
7276       {
7277         guint32 version;
7278         guint32 str_len;
7279
7280         /* codec_data is contained inside these atoms, which all have
7281          * the same format. */
7282         /* video sample description size is 86 bytes without extension.
7283          * node_length have to be bigger than 86 bytes because video sample
7284          * description can include extenstions such as esds, fiel, glbl, etc. */
7285         if (node_length < 86) {
7286           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7287               " sample description length too short (%u < 86)",
7288               GST_FOURCC_ARGS (fourcc), node_length);
7289           break;
7290         }
7291
7292         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7293             GST_FOURCC_ARGS (fourcc));
7294
7295         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7296          *              its data format.
7297          * revision level (2 bytes) : must be set to 0. */
7298         version = QT_UINT32 (buffer + 16);
7299         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7300
7301         /* compressor name : PASCAL string and informative purposes
7302          * first byte : the number of bytes to be displayed.
7303          *              it has to be less than 32 because it is reserved
7304          *              space of 32 bytes total including itself. */
7305         str_len = QT_UINT8 (buffer + 50);
7306         if (str_len < 32)
7307           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7308               (char *) buffer + 51);
7309         else
7310           GST_WARNING_OBJECT (qtdemux,
7311               "compressorname length too big (%u > 31)", str_len);
7312
7313         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7314             end - buffer);
7315         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7316         break;
7317       }
7318       case FOURCC_meta:
7319       {
7320         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7321         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7322         break;
7323       }
7324       case FOURCC_mp4s:
7325       {
7326         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7327         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7328         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7329         break;
7330       }
7331       case FOURCC_XiTh:
7332       {
7333         guint32 version;
7334         guint32 offset;
7335
7336         if (length < 16) {
7337           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7338               GST_FOURCC_ARGS (fourcc));
7339           break;
7340         }
7341
7342         version = QT_UINT32 (buffer + 12);
7343         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7344
7345         switch (version) {
7346           case 0x00000001:
7347             offset = 0x62;
7348             break;
7349           default:
7350             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7351             offset = 0;
7352             break;
7353         }
7354         if (offset) {
7355           if (length < offset) {
7356             GST_WARNING_OBJECT (qtdemux,
7357                 "skipping too small %" GST_FOURCC_FORMAT " box",
7358                 GST_FOURCC_ARGS (fourcc));
7359             break;
7360           }
7361           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7362         }
7363         break;
7364       }
7365       case FOURCC_in24:
7366       {
7367         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7368         break;
7369       }
7370       case FOURCC_uuid:
7371       {
7372         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7373         break;
7374       }
7375       case FOURCC_enca:
7376       {
7377         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7378         break;
7379       }
7380       default:
7381         if (!strcmp (type->name, "unknown"))
7382           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7383         break;
7384     }
7385   }
7386   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7387       GST_FOURCC_ARGS (fourcc));
7388   return TRUE;
7389
7390 /* ERRORS */
7391 not_enough_data:
7392   {
7393     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7394         (_("This file is corrupt and cannot be played.")),
7395         ("Not enough data for an atom header, got only %u bytes", length));
7396     return FALSE;
7397   }
7398 broken_atom_size:
7399   {
7400     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7401         (_("This file is corrupt and cannot be played.")),
7402         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7403             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7404             length));
7405     return FALSE;
7406   }
7407 }
7408
7409 static GNode *
7410 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7411 {
7412   GNode *child;
7413   guint8 *buffer;
7414   guint32 child_fourcc;
7415
7416   for (child = g_node_first_child (node); child;
7417       child = g_node_next_sibling (child)) {
7418     buffer = (guint8 *) child->data;
7419
7420     child_fourcc = QT_FOURCC (buffer + 4);
7421
7422     if (G_UNLIKELY (child_fourcc == fourcc)) {
7423       return child;
7424     }
7425   }
7426   return NULL;
7427 }
7428
7429 static GNode *
7430 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7431     GstByteReader * parser)
7432 {
7433   GNode *child;
7434   guint8 *buffer;
7435   guint32 child_fourcc, child_len;
7436
7437   for (child = g_node_first_child (node); child;
7438       child = g_node_next_sibling (child)) {
7439     buffer = (guint8 *) child->data;
7440
7441     child_len = QT_UINT32 (buffer);
7442     child_fourcc = QT_FOURCC (buffer + 4);
7443
7444     if (G_UNLIKELY (child_fourcc == fourcc)) {
7445       if (G_UNLIKELY (child_len < (4 + 4)))
7446         return NULL;
7447       /* FIXME: must verify if atom length < parent atom length */
7448       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7449       return child;
7450     }
7451   }
7452   return NULL;
7453 }
7454
7455 static GNode *
7456 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7457     GstByteReader * parser)
7458 {
7459   GNode *child;
7460   guint8 *buffer;
7461   guint32 child_fourcc, child_len;
7462
7463   for (child = g_node_next_sibling (node); child;
7464       child = g_node_next_sibling (child)) {
7465     buffer = (guint8 *) child->data;
7466
7467     child_fourcc = QT_FOURCC (buffer + 4);
7468
7469     if (child_fourcc == fourcc) {
7470       if (parser) {
7471         child_len = QT_UINT32 (buffer);
7472         if (G_UNLIKELY (child_len < (4 + 4)))
7473           return NULL;
7474         /* FIXME: must verify if atom length < parent atom length */
7475         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7476       }
7477       return child;
7478     }
7479   }
7480   return NULL;
7481 }
7482
7483 static GNode *
7484 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7485 {
7486   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7487 }
7488
7489 static void
7490 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7491 {
7492 /* FIXME: This can only reliably work if demuxers have a
7493  * separate streaming thread per srcpad. This should be
7494  * done in a demuxer base class, which integrates parts
7495  * of multiqueue
7496  *
7497  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7498  */
7499 #if 0
7500   GstQuery *query;
7501
7502   query = gst_query_new_allocation (stream->caps, FALSE);
7503
7504   if (!gst_pad_peer_query (stream->pad, query)) {
7505     /* not a problem, just debug a little */
7506     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7507   }
7508
7509   if (stream->allocator)
7510     gst_object_unref (stream->allocator);
7511
7512   if (gst_query_get_n_allocation_params (query) > 0) {
7513     /* try the allocator */
7514     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7515         &stream->params);
7516     stream->use_allocator = TRUE;
7517   } else {
7518     stream->allocator = NULL;
7519     gst_allocation_params_init (&stream->params);
7520     stream->use_allocator = FALSE;
7521   }
7522   gst_query_unref (query);
7523 #endif
7524 }
7525
7526 static gboolean
7527 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7528     QtDemuxStream * stream)
7529 {
7530   GstStructure *s;
7531   const gchar *selected_system;
7532
7533   g_return_val_if_fail (qtdemux != NULL, FALSE);
7534   g_return_val_if_fail (stream != NULL, FALSE);
7535   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7536
7537   if (stream->protection_scheme_type != FOURCC_cenc) {
7538     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7539     return FALSE;
7540   }
7541   if (qtdemux->protection_system_ids == NULL) {
7542     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7543         "cenc protection system information has been found");
7544     return FALSE;
7545   }
7546   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7547   selected_system = gst_protection_select_system ((const gchar **)
7548       qtdemux->protection_system_ids->pdata);
7549   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7550       qtdemux->protection_system_ids->len - 1);
7551   if (!selected_system) {
7552     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7553         "suitable decryptor element has been found");
7554     return FALSE;
7555   }
7556
7557   s = gst_caps_get_structure (stream->caps, 0);
7558   if (!gst_structure_has_name (s, "application/x-cenc")) {
7559     gst_structure_set (s,
7560         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7561         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7562         NULL);
7563     gst_structure_set_name (s, "application/x-cenc");
7564   }
7565   return TRUE;
7566 }
7567
7568 static gboolean
7569 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7570 {
7571   if (stream->subtype == FOURCC_vide) {
7572     /* fps is calculated base on the duration of the average framerate since
7573      * qt does not have a fixed framerate. */
7574     gboolean fps_available = TRUE;
7575
7576     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7577       /* still frame */
7578       stream->fps_n = 0;
7579       stream->fps_d = 1;
7580     } else {
7581       if (stream->duration == 0 || stream->n_samples < 2) {
7582         stream->fps_n = stream->timescale;
7583         stream->fps_d = 1;
7584         fps_available = FALSE;
7585       } else {
7586         GstClockTime avg_duration;
7587         guint64 duration;
7588         guint32 n_samples;
7589
7590         /* duration and n_samples can be updated for fragmented format
7591          * so, framerate of fragmented format is calculated using data in a moof */
7592         if (qtdemux->fragmented && stream->n_samples_moof > 0
7593             && stream->duration_moof > 0) {
7594           n_samples = stream->n_samples_moof;
7595           duration = stream->duration_moof;
7596         } else {
7597           n_samples = stream->n_samples;
7598           duration = stream->duration;
7599         }
7600
7601         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7602         /* stream->duration is guint64, timescale, n_samples are guint32 */
7603         avg_duration =
7604             gst_util_uint64_scale_round (duration -
7605             stream->first_duration, GST_SECOND,
7606             (guint64) (stream->timescale) * (n_samples - 1));
7607
7608         GST_LOG_OBJECT (qtdemux,
7609             "Calculating avg sample duration based on stream (or moof) duration %"
7610             G_GUINT64_FORMAT
7611             " minus first sample %u, leaving %d samples gives %"
7612             GST_TIME_FORMAT, duration, stream->first_duration,
7613             n_samples - 1, GST_TIME_ARGS (avg_duration));
7614
7615         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7616             &stream->fps_d);
7617
7618         GST_DEBUG_OBJECT (qtdemux,
7619             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7620             stream->timescale, stream->fps_n, stream->fps_d);
7621       }
7622     }
7623
7624     if (stream->caps) {
7625       stream->caps = gst_caps_make_writable (stream->caps);
7626
7627       gst_caps_set_simple (stream->caps,
7628           "width", G_TYPE_INT, stream->width,
7629           "height", G_TYPE_INT, stream->height, NULL);
7630
7631       /* set framerate if calculated framerate is reliable */
7632       if (fps_available) {
7633         gst_caps_set_simple (stream->caps,
7634             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7635       }
7636
7637       /* calculate pixel-aspect-ratio using display width and height */
7638       GST_DEBUG_OBJECT (qtdemux,
7639           "video size %dx%d, target display size %dx%d", stream->width,
7640           stream->height, stream->display_width, stream->display_height);
7641       /* qt file might have pasp atom */
7642       if (stream->par_w > 0 && stream->par_h > 0) {
7643         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7644         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7645             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7646       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7647           stream->width > 0 && stream->height > 0) {
7648         gint n, d;
7649
7650         /* calculate the pixel aspect ratio using the display and pixel w/h */
7651         n = stream->display_width * stream->height;
7652         d = stream->display_height * stream->width;
7653         if (n == d)
7654           n = d = 1;
7655         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7656         stream->par_w = n;
7657         stream->par_h = d;
7658         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7659             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7660       }
7661
7662       if (stream->interlace_mode > 0) {
7663         if (stream->interlace_mode == 1) {
7664           gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_STRING,
7665               "progressive", NULL);
7666         } else if (stream->interlace_mode == 2) {
7667           gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_STRING,
7668               "interleaved", NULL);
7669           if (stream->field_order == 9) {
7670             gst_caps_set_simple (stream->caps, "field-order", G_TYPE_STRING,
7671                 "top-field-first", NULL);
7672           } else if (stream->field_order == 14) {
7673             gst_caps_set_simple (stream->caps, "field-order", G_TYPE_STRING,
7674                 "bottom-field-first", NULL);
7675           }
7676         }
7677       }
7678
7679       /* Create incomplete colorimetry here if needed */
7680       if (stream->colorimetry.range ||
7681           stream->colorimetry.matrix ||
7682           stream->colorimetry.transfer || stream->colorimetry.primaries) {
7683         gchar *colorimetry =
7684             gst_video_colorimetry_to_string (&stream->colorimetry);
7685         gst_caps_set_simple (stream->caps, "colorimetry", G_TYPE_STRING,
7686             colorimetry, NULL);
7687         g_free (colorimetry);
7688       }
7689
7690       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7691         guint par_w = 1, par_h = 1;
7692
7693         if (stream->par_w > 0 && stream->par_h > 0) {
7694           par_w = stream->par_w;
7695           par_h = stream->par_h;
7696         }
7697
7698         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7699                 stream->width, stream->height, par_w, par_h)) {
7700           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7701         }
7702
7703         gst_caps_set_simple (stream->caps,
7704             "multiview-mode", G_TYPE_STRING,
7705             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7706             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7707             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7708       }
7709     }
7710   }
7711
7712   else if (stream->subtype == FOURCC_soun) {
7713     if (stream->caps) {
7714       stream->caps = gst_caps_make_writable (stream->caps);
7715       if (stream->rate > 0)
7716         gst_caps_set_simple (stream->caps,
7717             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7718       if (stream->n_channels > 0)
7719         gst_caps_set_simple (stream->caps,
7720             "channels", G_TYPE_INT, stream->n_channels, NULL);
7721       if (stream->n_channels > 2) {
7722         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7723          * correctly; this is just the minimum we can do - assume
7724          * we don't actually have any channel positions. */
7725         gst_caps_set_simple (stream->caps,
7726             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7727       }
7728     }
7729   }
7730
7731   if (stream->pad) {
7732     GstCaps *prev_caps = NULL;
7733
7734     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7735     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7736     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7737     gst_pad_set_active (stream->pad, TRUE);
7738
7739     gst_pad_use_fixed_caps (stream->pad);
7740
7741     if (stream->protected) {
7742       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7743         GST_ERROR_OBJECT (qtdemux,
7744             "Failed to configure protected stream caps.");
7745         return FALSE;
7746       }
7747     }
7748
7749     if (stream->new_stream) {
7750       gchar *stream_id;
7751       GstEvent *event;
7752       GstStreamFlags stream_flags;
7753
7754       event =
7755           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7756           0);
7757       if (event) {
7758         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7759           qtdemux->have_group_id = TRUE;
7760         else
7761           qtdemux->have_group_id = FALSE;
7762         gst_event_unref (event);
7763       } else if (!qtdemux->have_group_id) {
7764         qtdemux->have_group_id = TRUE;
7765         qtdemux->group_id = gst_util_group_id_next ();
7766       }
7767
7768       stream->new_stream = FALSE;
7769       stream_id =
7770           gst_pad_create_stream_id_printf (stream->pad,
7771           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7772       event = gst_event_new_stream_start (stream_id);
7773       if (qtdemux->have_group_id)
7774         gst_event_set_group_id (event, qtdemux->group_id);
7775       stream_flags = GST_STREAM_FLAG_NONE;
7776       if (stream->disabled)
7777         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7778       if (stream->sparse)
7779         stream_flags |= GST_STREAM_FLAG_SPARSE;
7780       gst_event_set_stream_flags (event, stream_flags);
7781       gst_pad_push_event (stream->pad, event);
7782       g_free (stream_id);
7783     }
7784
7785     prev_caps = gst_pad_get_current_caps (stream->pad);
7786
7787     if (!prev_caps || !gst_caps_is_equal_fixed (prev_caps, stream->caps)) {
7788       GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7789       gst_pad_set_caps (stream->pad, stream->caps);
7790     } else {
7791       GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7792     }
7793
7794     if (prev_caps)
7795       gst_caps_unref (prev_caps);
7796     stream->new_caps = FALSE;
7797   }
7798   return TRUE;
7799 }
7800
7801 static gboolean
7802 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7803     QtDemuxStream * stream, GstTagList * list)
7804 {
7805   gboolean ret = TRUE;
7806   /* consistent default for push based mode */
7807   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7808
7809   if (stream->subtype == FOURCC_vide) {
7810     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7811
7812     stream->pad =
7813         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7814     g_free (name);
7815
7816     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7817       gst_object_unref (stream->pad);
7818       stream->pad = NULL;
7819       ret = FALSE;
7820       goto done;
7821     }
7822
7823     qtdemux->n_video_streams++;
7824   } else if (stream->subtype == FOURCC_soun) {
7825     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7826
7827     stream->pad =
7828         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7829     g_free (name);
7830     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7831       gst_object_unref (stream->pad);
7832       stream->pad = NULL;
7833       ret = FALSE;
7834       goto done;
7835     }
7836     qtdemux->n_audio_streams++;
7837   } else if (stream->subtype == FOURCC_strm) {
7838     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7839   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7840       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7841     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7842
7843     stream->pad =
7844         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7845     g_free (name);
7846     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7847       gst_object_unref (stream->pad);
7848       stream->pad = NULL;
7849       ret = FALSE;
7850       goto done;
7851     }
7852     qtdemux->n_sub_streams++;
7853   } else if (stream->caps) {
7854     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7855
7856     stream->pad =
7857         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7858     g_free (name);
7859     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7860       gst_object_unref (stream->pad);
7861       stream->pad = NULL;
7862       ret = FALSE;
7863       goto done;
7864     }
7865     qtdemux->n_video_streams++;
7866   } else {
7867     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7868     goto done;
7869   }
7870
7871   if (stream->pad) {
7872     GList *l;
7873
7874     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7875         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7876     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7877     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7878
7879     if (stream->pending_tags)
7880       gst_tag_list_unref (stream->pending_tags);
7881     stream->pending_tags = list;
7882     list = NULL;
7883     /* global tags go on each pad anyway */
7884     stream->send_global_tags = TRUE;
7885     /* send upstream GST_EVENT_PROTECTION events that were received before
7886        this source pad was created */
7887     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7888       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7889   }
7890 done:
7891   if (list)
7892     gst_tag_list_unref (list);
7893   return ret;
7894 }
7895
7896 /* find next atom with @fourcc starting at @offset */
7897 static GstFlowReturn
7898 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7899     guint64 * length, guint32 fourcc)
7900 {
7901   GstFlowReturn ret;
7902   guint32 lfourcc;
7903   GstBuffer *buf;
7904
7905   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7906       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7907
7908   while (TRUE) {
7909     GstMapInfo map;
7910
7911     buf = NULL;
7912     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7913     if (G_UNLIKELY (ret != GST_FLOW_OK))
7914       goto locate_failed;
7915     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7916       /* likely EOF */
7917       ret = GST_FLOW_EOS;
7918       gst_buffer_unref (buf);
7919       goto locate_failed;
7920     }
7921     gst_buffer_map (buf, &map, GST_MAP_READ);
7922     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7923     gst_buffer_unmap (buf, &map);
7924     gst_buffer_unref (buf);
7925
7926     if (G_UNLIKELY (*length == 0)) {
7927       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7928       ret = GST_FLOW_ERROR;
7929       goto locate_failed;
7930     }
7931
7932     if (lfourcc == fourcc) {
7933       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7934           *offset);
7935       break;
7936     } else {
7937       GST_LOG_OBJECT (qtdemux,
7938           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7939           GST_FOURCC_ARGS (fourcc), *offset);
7940       *offset += *length;
7941     }
7942   }
7943
7944   return GST_FLOW_OK;
7945
7946 locate_failed:
7947   {
7948     /* might simply have had last one */
7949     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7950     return ret;
7951   }
7952 }
7953
7954 /* should only do something in pull mode */
7955 /* call with OBJECT lock */
7956 static GstFlowReturn
7957 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7958 {
7959   guint64 length, offset;
7960   GstBuffer *buf = NULL;
7961   GstFlowReturn ret = GST_FLOW_OK;
7962   GstFlowReturn res = GST_FLOW_OK;
7963   GstMapInfo map;
7964
7965   offset = qtdemux->moof_offset;
7966   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7967
7968   if (!offset) {
7969     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7970     return GST_FLOW_EOS;
7971   }
7972
7973   /* best not do pull etc with lock held */
7974   GST_OBJECT_UNLOCK (qtdemux);
7975
7976   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7977   if (ret != GST_FLOW_OK)
7978     goto flow_failed;
7979
7980   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7981   if (G_UNLIKELY (ret != GST_FLOW_OK))
7982     goto flow_failed;
7983   gst_buffer_map (buf, &map, GST_MAP_READ);
7984   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7985     gst_buffer_unmap (buf, &map);
7986     gst_buffer_unref (buf);
7987     buf = NULL;
7988     goto parse_failed;
7989   }
7990
7991   gst_buffer_unmap (buf, &map);
7992   gst_buffer_unref (buf);
7993   buf = NULL;
7994
7995   offset += length;
7996   /* look for next moof */
7997   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7998   if (G_UNLIKELY (ret != GST_FLOW_OK))
7999     goto flow_failed;
8000
8001 exit:
8002   GST_OBJECT_LOCK (qtdemux);
8003
8004   qtdemux->moof_offset = offset;
8005
8006   return res;
8007
8008 parse_failed:
8009   {
8010     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8011     offset = 0;
8012     res = GST_FLOW_ERROR;
8013     goto exit;
8014   }
8015 flow_failed:
8016   {
8017     /* maybe upstream temporarily flushing */
8018     if (ret != GST_FLOW_FLUSHING) {
8019       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8020       offset = 0;
8021     } else {
8022       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8023       /* resume at current position next time */
8024     }
8025     res = ret;
8026     goto exit;
8027   }
8028 }
8029
8030 /* initialise bytereaders for stbl sub-atoms */
8031 static gboolean
8032 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8033 {
8034   stream->stbl_index = -1;      /* no samples have yet been parsed */
8035   stream->sample_index = -1;
8036
8037   /* time-to-sample atom */
8038   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8039     goto corrupt_file;
8040
8041   /* copy atom data into a new buffer for later use */
8042   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8043
8044   /* skip version + flags */
8045   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8046       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8047     goto corrupt_file;
8048   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8049
8050   /* make sure there's enough data */
8051   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8052     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8053     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8054         stream->n_sample_times);
8055     if (!stream->n_sample_times)
8056       goto corrupt_file;
8057   }
8058
8059   /* sync sample atom */
8060   stream->stps_present = FALSE;
8061   if ((stream->stss_present =
8062           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8063               &stream->stss) ? TRUE : FALSE) == TRUE) {
8064     /* copy atom data into a new buffer for later use */
8065     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8066
8067     /* skip version + flags */
8068     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8069         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8070       goto corrupt_file;
8071
8072     if (stream->n_sample_syncs) {
8073       /* make sure there's enough data */
8074       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8075         goto corrupt_file;
8076     }
8077
8078     /* partial sync sample atom */
8079     if ((stream->stps_present =
8080             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8081                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8082       /* copy atom data into a new buffer for later use */
8083       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8084
8085       /* skip version + flags */
8086       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8087           !gst_byte_reader_get_uint32_be (&stream->stps,
8088               &stream->n_sample_partial_syncs))
8089         goto corrupt_file;
8090
8091       /* if there are no entries, the stss table contains the real
8092        * sync samples */
8093       if (stream->n_sample_partial_syncs) {
8094         /* make sure there's enough data */
8095         if (!qt_atom_parser_has_chunks (&stream->stps,
8096                 stream->n_sample_partial_syncs, 4))
8097           goto corrupt_file;
8098       }
8099     }
8100   }
8101
8102   /* sample size */
8103   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8104     goto no_samples;
8105
8106   /* copy atom data into a new buffer for later use */
8107   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8108
8109   /* skip version + flags */
8110   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8111       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8112     goto corrupt_file;
8113
8114   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8115     goto corrupt_file;
8116
8117   if (!stream->n_samples)
8118     goto no_samples;
8119
8120   /* sample-to-chunk atom */
8121   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8122     goto corrupt_file;
8123
8124   /* copy atom data into a new buffer for later use */
8125   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8126
8127   /* skip version + flags */
8128   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8129       !gst_byte_reader_get_uint32_be (&stream->stsc,
8130           &stream->n_samples_per_chunk))
8131     goto corrupt_file;
8132
8133   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8134       stream->n_samples_per_chunk);
8135
8136   /* make sure there's enough data */
8137   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8138           12))
8139     goto corrupt_file;
8140
8141
8142   /* chunk offset */
8143   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8144     stream->co_size = sizeof (guint32);
8145   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8146           &stream->stco))
8147     stream->co_size = sizeof (guint64);
8148   else
8149     goto corrupt_file;
8150
8151   /* copy atom data into a new buffer for later use */
8152   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8153
8154   /* skip version + flags */
8155   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8156     goto corrupt_file;
8157
8158   /* chunks_are_samples == TRUE means treat chunks as samples */
8159   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
8160   if (stream->chunks_are_samples) {
8161     /* treat chunks as samples */
8162     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8163       goto corrupt_file;
8164   } else {
8165     /* skip number of entries */
8166     if (!gst_byte_reader_skip (&stream->stco, 4))
8167       goto corrupt_file;
8168
8169     /* make sure there are enough data in the stsz atom */
8170     if (!stream->sample_size) {
8171       /* different sizes for each sample */
8172       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8173         goto corrupt_file;
8174     }
8175   }
8176
8177   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8178       stream->n_samples, (guint) sizeof (QtDemuxSample),
8179       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8180
8181   if (stream->n_samples >=
8182       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8183     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8184         "be larger than %uMB (broken file?)", stream->n_samples,
8185         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8186     return FALSE;
8187   }
8188
8189   g_assert (stream->samples == NULL);
8190   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8191   if (!stream->samples) {
8192     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8193         stream->n_samples);
8194     return FALSE;
8195   }
8196
8197   /* composition time-to-sample */
8198   if ((stream->ctts_present =
8199           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8200               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8201     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8202
8203     /* copy atom data into a new buffer for later use */
8204     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8205
8206     /* skip version + flags */
8207     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8208         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8209             &stream->n_composition_times))
8210       goto corrupt_file;
8211
8212     /* make sure there's enough data */
8213     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8214             4 + 4))
8215       goto corrupt_file;
8216
8217     /* This is optional, if missing we iterate the ctts */
8218     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8219       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8220           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8221         g_free ((gpointer) cslg.data);
8222         goto corrupt_file;
8223       }
8224     } else {
8225       gint32 cslg_least = 0;
8226       guint num_entries, pos;
8227       gint i;
8228
8229       pos = gst_byte_reader_get_pos (&stream->ctts);
8230       num_entries = stream->n_composition_times;
8231
8232       stream->cslg_shift = 0;
8233
8234       for (i = 0; i < num_entries; i++) {
8235         gint32 offset;
8236
8237         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8238         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8239
8240         if (offset < cslg_least)
8241           cslg_least = offset;
8242       }
8243
8244       if (cslg_least < 0)
8245         stream->cslg_shift = ABS (cslg_least);
8246       else
8247         stream->cslg_shift = 0;
8248
8249       /* reset the reader so we can generate sample table */
8250       gst_byte_reader_set_pos (&stream->ctts, pos);
8251     }
8252   } else {
8253     /* Ensure the cslg_shift value is consistent so we can use it
8254      * unconditionnally to produce TS and Segment */
8255     stream->cslg_shift = 0;
8256   }
8257
8258   return TRUE;
8259
8260 corrupt_file:
8261   {
8262     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8263         (_("This file is corrupt and cannot be played.")), (NULL));
8264     return FALSE;
8265   }
8266 no_samples:
8267   {
8268     gst_qtdemux_stbl_free (stream);
8269     if (!qtdemux->fragmented) {
8270       /* not quite good */
8271       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8272       return FALSE;
8273     } else {
8274       /* may pick up samples elsewhere */
8275       return TRUE;
8276     }
8277   }
8278 }
8279
8280 /* collect samples from the next sample to be parsed up to sample @n for @stream
8281  * by reading the info from @stbl
8282  *
8283  * This code can be executed from both the streaming thread and the seeking
8284  * thread so it takes the object lock to protect itself
8285  */
8286 static gboolean
8287 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8288 {
8289   gint i, j, k;
8290   QtDemuxSample *samples, *first, *cur, *last;
8291   guint32 n_samples_per_chunk;
8292   guint32 n_samples;
8293
8294   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8295       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8296       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8297
8298   n_samples = stream->n_samples;
8299
8300   if (n >= n_samples)
8301     goto out_of_samples;
8302
8303   GST_OBJECT_LOCK (qtdemux);
8304   if (n <= stream->stbl_index)
8305     goto already_parsed;
8306
8307   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8308
8309   if (!stream->stsz.data) {
8310     /* so we already parsed and passed all the moov samples;
8311      * onto fragmented ones */
8312     g_assert (qtdemux->fragmented);
8313     goto done;
8314   }
8315
8316   /* pointer to the sample table */
8317   samples = stream->samples;
8318
8319   /* starts from -1, moves to the next sample index to parse */
8320   stream->stbl_index++;
8321
8322   /* keep track of the first and last sample to fill */
8323   first = &samples[stream->stbl_index];
8324   last = &samples[n];
8325
8326   if (!stream->chunks_are_samples) {
8327     /* set the sample sizes */
8328     if (stream->sample_size == 0) {
8329       /* different sizes for each sample */
8330       for (cur = first; cur <= last; cur++) {
8331         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8332         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8333             (guint) (cur - samples), cur->size);
8334       }
8335     } else {
8336       /* samples have the same size */
8337       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8338       for (cur = first; cur <= last; cur++)
8339         cur->size = stream->sample_size;
8340     }
8341   }
8342
8343   n_samples_per_chunk = stream->n_samples_per_chunk;
8344   cur = first;
8345
8346   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8347     guint32 last_chunk;
8348
8349     if (stream->stsc_chunk_index >= stream->last_chunk
8350         || stream->stsc_chunk_index < stream->first_chunk) {
8351       stream->first_chunk =
8352           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8353       stream->samples_per_chunk =
8354           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8355       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8356
8357       /* chunk numbers are counted from 1 it seems */
8358       if (G_UNLIKELY (stream->first_chunk == 0))
8359         goto corrupt_file;
8360
8361       --stream->first_chunk;
8362
8363       /* the last chunk of each entry is calculated by taking the first chunk
8364        * of the next entry; except if there is no next, where we fake it with
8365        * INT_MAX */
8366       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8367         stream->last_chunk = G_MAXUINT32;
8368       } else {
8369         stream->last_chunk =
8370             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8371         if (G_UNLIKELY (stream->last_chunk == 0))
8372           goto corrupt_file;
8373
8374         --stream->last_chunk;
8375       }
8376
8377       GST_LOG_OBJECT (qtdemux,
8378           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8379           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8380
8381       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8382         goto corrupt_file;
8383
8384       if (stream->last_chunk != G_MAXUINT32) {
8385         if (!qt_atom_parser_peek_sub (&stream->stco,
8386                 stream->first_chunk * stream->co_size,
8387                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8388                 &stream->co_chunk))
8389           goto corrupt_file;
8390
8391       } else {
8392         stream->co_chunk = stream->stco;
8393         if (!gst_byte_reader_skip (&stream->co_chunk,
8394                 stream->first_chunk * stream->co_size))
8395           goto corrupt_file;
8396       }
8397
8398       stream->stsc_chunk_index = stream->first_chunk;
8399     }
8400
8401     last_chunk = stream->last_chunk;
8402
8403     if (stream->chunks_are_samples) {
8404       cur = &samples[stream->stsc_chunk_index];
8405
8406       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8407         if (j > n) {
8408           /* save state */
8409           stream->stsc_chunk_index = j;
8410           goto done;
8411         }
8412
8413         cur->offset =
8414             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8415             stream->co_size);
8416
8417         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8418             "%" G_GUINT64_FORMAT, j, cur->offset);
8419
8420         if (stream->samples_per_frame * stream->bytes_per_frame) {
8421           cur->size =
8422               (stream->samples_per_chunk * stream->n_channels) /
8423               stream->samples_per_frame * stream->bytes_per_frame;
8424         } else {
8425           cur->size = stream->samples_per_chunk;
8426         }
8427
8428         GST_DEBUG_OBJECT (qtdemux,
8429             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8430             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8431                     stream->stco_sample_index)), cur->size);
8432
8433         cur->timestamp = stream->stco_sample_index;
8434         cur->duration = stream->samples_per_chunk;
8435         cur->keyframe = TRUE;
8436         cur++;
8437
8438         stream->stco_sample_index += stream->samples_per_chunk;
8439       }
8440       stream->stsc_chunk_index = j;
8441     } else {
8442       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8443         guint32 samples_per_chunk;
8444         guint64 chunk_offset;
8445
8446         if (!stream->stsc_sample_index
8447             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8448                 &stream->chunk_offset))
8449           goto corrupt_file;
8450
8451         samples_per_chunk = stream->samples_per_chunk;
8452         chunk_offset = stream->chunk_offset;
8453
8454         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8455           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8456               G_GUINT64_FORMAT " and size %d",
8457               (guint) (cur - samples), chunk_offset, cur->size);
8458
8459           cur->offset = chunk_offset;
8460           chunk_offset += cur->size;
8461           cur++;
8462
8463           if (G_UNLIKELY (cur > last)) {
8464             /* save state */
8465             stream->stsc_sample_index = k + 1;
8466             stream->chunk_offset = chunk_offset;
8467             stream->stsc_chunk_index = j;
8468             goto done2;
8469           }
8470         }
8471         stream->stsc_sample_index = 0;
8472       }
8473       stream->stsc_chunk_index = j;
8474     }
8475     stream->stsc_index++;
8476   }
8477
8478   if (stream->chunks_are_samples)
8479     goto ctts;
8480 done2:
8481   {
8482     guint32 n_sample_times;
8483
8484     n_sample_times = stream->n_sample_times;
8485     cur = first;
8486
8487     for (i = stream->stts_index; i < n_sample_times; i++) {
8488       guint32 stts_samples;
8489       gint32 stts_duration;
8490       gint64 stts_time;
8491
8492       if (stream->stts_sample_index >= stream->stts_samples
8493           || !stream->stts_sample_index) {
8494
8495         stream->stts_samples =
8496             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8497         stream->stts_duration =
8498             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8499
8500         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8501             i, stream->stts_samples, stream->stts_duration);
8502
8503         stream->stts_sample_index = 0;
8504       }
8505
8506       stts_samples = stream->stts_samples;
8507       stts_duration = stream->stts_duration;
8508       stts_time = stream->stts_time;
8509
8510       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8511         GST_DEBUG_OBJECT (qtdemux,
8512             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8513             (guint) (cur - samples), j,
8514             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8515
8516         cur->timestamp = stts_time;
8517         cur->duration = stts_duration;
8518
8519         /* avoid 32-bit wrap-around,
8520          * but still mind possible 'negative' duration */
8521         stts_time += (gint64) stts_duration;
8522         cur++;
8523
8524         if (G_UNLIKELY (cur > last)) {
8525           /* save values */
8526           stream->stts_time = stts_time;
8527           stream->stts_sample_index = j + 1;
8528           goto done3;
8529         }
8530       }
8531       stream->stts_sample_index = 0;
8532       stream->stts_time = stts_time;
8533       stream->stts_index++;
8534     }
8535     /* fill up empty timestamps with the last timestamp, this can happen when
8536      * the last samples do not decode and so we don't have timestamps for them.
8537      * We however look at the last timestamp to estimate the track length so we
8538      * need something in here. */
8539     for (; cur < last; cur++) {
8540       GST_DEBUG_OBJECT (qtdemux,
8541           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8542           (guint) (cur - samples),
8543           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8544       cur->timestamp = stream->stts_time;
8545       cur->duration = -1;
8546     }
8547   }
8548 done3:
8549   {
8550     /* sample sync, can be NULL */
8551     if (stream->stss_present == TRUE) {
8552       guint32 n_sample_syncs;
8553
8554       n_sample_syncs = stream->n_sample_syncs;
8555
8556       if (!n_sample_syncs) {
8557         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8558         stream->all_keyframe = TRUE;
8559       } else {
8560         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8561           /* note that the first sample is index 1, not 0 */
8562           guint32 index;
8563
8564           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8565
8566           if (G_LIKELY (index > 0 && index <= n_samples)) {
8567             index -= 1;
8568             samples[index].keyframe = TRUE;
8569             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8570             /* and exit if we have enough samples */
8571             if (G_UNLIKELY (index >= n)) {
8572               i++;
8573               break;
8574             }
8575           }
8576         }
8577         /* save state */
8578         stream->stss_index = i;
8579       }
8580
8581       /* stps marks partial sync frames like open GOP I-Frames */
8582       if (stream->stps_present == TRUE) {
8583         guint32 n_sample_partial_syncs;
8584
8585         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8586
8587         /* if there are no entries, the stss table contains the real
8588          * sync samples */
8589         if (n_sample_partial_syncs) {
8590           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8591             /* note that the first sample is index 1, not 0 */
8592             guint32 index;
8593
8594             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8595
8596             if (G_LIKELY (index > 0 && index <= n_samples)) {
8597               index -= 1;
8598               samples[index].keyframe = TRUE;
8599               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8600               /* and exit if we have enough samples */
8601               if (G_UNLIKELY (index >= n)) {
8602                 i++;
8603                 break;
8604               }
8605             }
8606           }
8607           /* save state */
8608           stream->stps_index = i;
8609         }
8610       }
8611     } else {
8612       /* no stss, all samples are keyframes */
8613       stream->all_keyframe = TRUE;
8614       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8615     }
8616   }
8617
8618 ctts:
8619   /* composition time to sample */
8620   if (stream->ctts_present == TRUE) {
8621     guint32 n_composition_times;
8622     guint32 ctts_count;
8623     gint32 ctts_soffset;
8624
8625     /* Fill in the pts_offsets */
8626     cur = first;
8627     n_composition_times = stream->n_composition_times;
8628
8629     for (i = stream->ctts_index; i < n_composition_times; i++) {
8630       if (stream->ctts_sample_index >= stream->ctts_count
8631           || !stream->ctts_sample_index) {
8632         stream->ctts_count =
8633             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8634         stream->ctts_soffset =
8635             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8636         stream->ctts_sample_index = 0;
8637       }
8638
8639       ctts_count = stream->ctts_count;
8640       ctts_soffset = stream->ctts_soffset;
8641
8642       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8643         cur->pts_offset = ctts_soffset;
8644         cur++;
8645
8646         if (G_UNLIKELY (cur > last)) {
8647           /* save state */
8648           stream->ctts_sample_index = j + 1;
8649           goto done;
8650         }
8651       }
8652       stream->ctts_sample_index = 0;
8653       stream->ctts_index++;
8654     }
8655   }
8656 done:
8657   stream->stbl_index = n;
8658   /* if index has been completely parsed, free data that is no-longer needed */
8659   if (n + 1 == stream->n_samples) {
8660     gst_qtdemux_stbl_free (stream);
8661     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8662     if (qtdemux->pullbased) {
8663       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8664       while (n + 1 == stream->n_samples)
8665         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8666           break;
8667     }
8668   }
8669   GST_OBJECT_UNLOCK (qtdemux);
8670
8671   return TRUE;
8672
8673   /* SUCCESS */
8674 already_parsed:
8675   {
8676     GST_LOG_OBJECT (qtdemux,
8677         "Tried to parse up to sample %u but this sample has already been parsed",
8678         n);
8679     /* if fragmented, there may be more */
8680     if (qtdemux->fragmented && n == stream->stbl_index)
8681       goto done;
8682     GST_OBJECT_UNLOCK (qtdemux);
8683     return TRUE;
8684   }
8685   /* ERRORS */
8686 out_of_samples:
8687   {
8688     GST_LOG_OBJECT (qtdemux,
8689         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8690         stream->n_samples);
8691     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8692         (_("This file is corrupt and cannot be played.")), (NULL));
8693     return FALSE;
8694   }
8695 corrupt_file:
8696   {
8697     GST_OBJECT_UNLOCK (qtdemux);
8698     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8699         (_("This file is corrupt and cannot be played.")), (NULL));
8700     return FALSE;
8701   }
8702 }
8703
8704 /* collect all segment info for @stream.
8705  */
8706 static gboolean
8707 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8708     GNode * trak)
8709 {
8710   GNode *edts;
8711   /* accept edts if they contain gaps at start and there is only
8712    * one media segment */
8713   gboolean allow_pushbased_edts = TRUE;
8714   gint media_segments_count = 0;
8715
8716   /* parse and prepare segment info from the edit list */
8717   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8718   stream->n_segments = 0;
8719   stream->segments = NULL;
8720   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8721     GNode *elst;
8722     gint n_segments;
8723     gint i, count, entry_size;
8724     guint64 time;
8725     GstClockTime stime;
8726     const guint8 *buffer;
8727     guint8 version;
8728     guint32 size;
8729
8730     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8731     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8732       goto done;
8733
8734     buffer = elst->data;
8735
8736     size = QT_UINT32 (buffer);
8737     /* version, flags, n_segments */
8738     if (size < 16) {
8739       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8740       goto done;
8741     }
8742     version = QT_UINT8 (buffer + 8);
8743     entry_size = (version == 1) ? 20 : 12;
8744
8745     n_segments = QT_UINT32 (buffer + 12);
8746
8747     if (size < 16 + n_segments * entry_size) {
8748       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8749       goto done;
8750     }
8751
8752     /* we might allocate a bit too much, at least allocate 1 segment */
8753     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8754
8755     /* segments always start from 0 */
8756     time = 0;
8757     stime = 0;
8758     count = 0;
8759     buffer += 16;
8760     for (i = 0; i < n_segments; i++) {
8761       guint64 duration;
8762       guint64 media_time;
8763       gboolean time_valid = TRUE;
8764       QtDemuxSegment *segment;
8765       guint32 rate_int;
8766       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8767
8768       if (version == 1) {
8769         media_time = QT_UINT64 (buffer + 8);
8770         duration = QT_UINT64 (buffer);
8771         if (media_time == G_MAXUINT64)
8772           time_valid = FALSE;
8773       } else {
8774         media_time = QT_UINT32 (buffer + 4);
8775         duration = QT_UINT32 (buffer);
8776         if (media_time == G_MAXUINT32)
8777           time_valid = FALSE;
8778       }
8779
8780       if (time_valid)
8781         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8782
8783       segment = &stream->segments[count++];
8784
8785       /* time and duration expressed in global timescale */
8786       segment->time = stime;
8787       /* add non scaled values so we don't cause roundoff errors */
8788       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8789         time += duration;
8790         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8791         segment->duration = stime - segment->time;
8792       } else {
8793         /* zero duration does not imply media_start == media_stop
8794          * but, only specify media_start.*/
8795         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8796         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8797             && stime >= media_start) {
8798           segment->duration = stime - media_start;
8799         } else {
8800           segment->duration = GST_CLOCK_TIME_NONE;
8801         }
8802       }
8803       segment->stop_time = stime;
8804
8805       segment->trak_media_start = media_time;
8806       /* media_time expressed in stream timescale */
8807       if (time_valid) {
8808         segment->media_start = media_start;
8809         segment->media_stop = segment->media_start + segment->duration;
8810         media_segments_count++;
8811       } else {
8812         segment->media_start = GST_CLOCK_TIME_NONE;
8813         segment->media_stop = GST_CLOCK_TIME_NONE;
8814       }
8815       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
8816
8817       if (rate_int <= 1) {
8818         /* 0 is not allowed, some programs write 1 instead of the floating point
8819          * value */
8820         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8821             rate_int);
8822         segment->rate = 1;
8823       } else {
8824         segment->rate = rate_int / 65536.0;
8825       }
8826
8827       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8828           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8829           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8830           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8831           i, GST_TIME_ARGS (segment->time),
8832           GST_TIME_ARGS (segment->duration),
8833           GST_TIME_ARGS (segment->media_start), media_time,
8834           GST_TIME_ARGS (segment->media_stop),
8835           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8836           stream->timescale);
8837       if (segment->stop_time > qtdemux->segment.stop) {
8838         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8839             " extends to %" GST_TIME_FORMAT
8840             " past the end of the file duration %" GST_TIME_FORMAT
8841             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8842             GST_TIME_ARGS (qtdemux->segment.stop));
8843         qtdemux->segment.stop = segment->stop_time;
8844       }
8845
8846       buffer += entry_size;
8847     }
8848     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8849     stream->n_segments = count;
8850     if (media_segments_count != 1)
8851       allow_pushbased_edts = FALSE;
8852   }
8853 done:
8854
8855   /* push based does not handle segments, so act accordingly here,
8856    * and warn if applicable */
8857   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8858     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8859     /* remove and use default one below, we stream like it anyway */
8860     g_free (stream->segments);
8861     stream->segments = NULL;
8862     stream->n_segments = 0;
8863   }
8864
8865   /* no segments, create one to play the complete trak */
8866   if (stream->n_segments == 0) {
8867     GstClockTime stream_duration =
8868         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8869
8870     if (stream->segments == NULL)
8871       stream->segments = g_new (QtDemuxSegment, 1);
8872
8873     /* represent unknown our way */
8874     if (stream_duration == 0)
8875       stream_duration = GST_CLOCK_TIME_NONE;
8876
8877     stream->segments[0].time = 0;
8878     stream->segments[0].stop_time = stream_duration;
8879     stream->segments[0].duration = stream_duration;
8880     stream->segments[0].media_start = 0;
8881     stream->segments[0].media_stop = stream_duration;
8882     stream->segments[0].rate = 1.0;
8883     stream->segments[0].trak_media_start = 0;
8884
8885     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8886         GST_TIME_ARGS (stream_duration));
8887     stream->n_segments = 1;
8888     stream->dummy_segment = TRUE;
8889   }
8890   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8891
8892   return TRUE;
8893 }
8894
8895 /*
8896  * Parses the stsd atom of a svq3 trak looking for
8897  * the SMI and gama atoms.
8898  */
8899 static void
8900 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8901     guint8 ** gamma, GstBuffer ** seqh)
8902 {
8903   guint8 *_gamma = NULL;
8904   GstBuffer *_seqh = NULL;
8905   guint8 *stsd_data = stsd->data;
8906   guint32 length = QT_UINT32 (stsd_data);
8907   guint16 version;
8908
8909   if (length < 32) {
8910     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8911     goto end;
8912   }
8913
8914   stsd_data += 32;
8915   length -= 32;
8916   version = QT_UINT16 (stsd_data);
8917   if (version == 3) {
8918     if (length >= 70) {
8919       length -= 70;
8920       stsd_data += 70;
8921       while (length > 8) {
8922         guint32 fourcc, size;
8923         guint8 *data;
8924         size = QT_UINT32 (stsd_data);
8925         fourcc = QT_FOURCC (stsd_data + 4);
8926         data = stsd_data + 8;
8927
8928         if (size == 0) {
8929           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8930               "svq3 atom parsing");
8931           goto end;
8932         }
8933
8934         switch (fourcc) {
8935           case FOURCC_gama:{
8936             if (size == 12) {
8937               _gamma = data;
8938             } else {
8939               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8940                   " for gama atom, expected 12", size);
8941             }
8942             break;
8943           }
8944           case FOURCC_SMI_:{
8945             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8946               guint32 seqh_size;
8947               if (_seqh != NULL) {
8948                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8949                     " found, ignoring");
8950               } else {
8951                 seqh_size = QT_UINT32 (data + 4);
8952                 if (seqh_size > 0) {
8953                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8954                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8955                 }
8956               }
8957             }
8958             break;
8959           }
8960           default:{
8961             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8962                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8963           }
8964         }
8965
8966         if (size <= length) {
8967           length -= size;
8968           stsd_data += size;
8969         }
8970       }
8971     } else {
8972       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8973     }
8974   } else {
8975     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8976         G_GUINT16_FORMAT, version);
8977     goto end;
8978   }
8979
8980 end:
8981   if (gamma) {
8982     *gamma = _gamma;
8983   }
8984   if (seqh) {
8985     *seqh = _seqh;
8986   } else if (_seqh) {
8987     gst_buffer_unref (_seqh);
8988   }
8989 }
8990
8991 static gchar *
8992 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8993 {
8994   GNode *dinf;
8995   GstByteReader dref;
8996   gchar *uri = NULL;
8997
8998   /*
8999    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9000    * atom that might contain a 'data' atom with the rtsp uri.
9001    * This case was reported in bug #597497, some info about
9002    * the hndl atom can be found in TN1195
9003    */
9004   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9005   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9006
9007   if (dinf) {
9008     guint32 dref_num_entries = 0;
9009     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9010         gst_byte_reader_skip (&dref, 4) &&
9011         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9012       gint i;
9013
9014       /* search dref entries for hndl atom */
9015       for (i = 0; i < dref_num_entries; i++) {
9016         guint32 size = 0, type;
9017         guint8 string_len = 0;
9018         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9019             qt_atom_parser_get_fourcc (&dref, &type)) {
9020           if (type == FOURCC_hndl) {
9021             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9022
9023             /* skip data reference handle bytes and the
9024              * following pascal string and some extra 4
9025              * bytes I have no idea what are */
9026             if (!gst_byte_reader_skip (&dref, 4) ||
9027                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9028                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9029               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9030               break;
9031             }
9032
9033             /* iterate over the atoms to find the data atom */
9034             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9035               guint32 atom_size;
9036               guint32 atom_type;
9037
9038               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9039                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9040                 if (atom_type == FOURCC_data) {
9041                   const guint8 *uri_aux = NULL;
9042
9043                   /* found the data atom that might contain the rtsp uri */
9044                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9045                       "hndl atom, interpreting it as an URI");
9046                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9047                           &uri_aux)) {
9048                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9049                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9050                     else
9051                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9052                           "didn't contain a rtsp address");
9053                   } else {
9054                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9055                         "atom contents");
9056                   }
9057                   break;
9058                 }
9059                 /* skipping to the next entry */
9060                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9061                   break;
9062               } else {
9063                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9064                     "atom header");
9065                 break;
9066               }
9067             }
9068             break;
9069           }
9070           /* skip to the next entry */
9071           if (!gst_byte_reader_skip (&dref, size - 8))
9072             break;
9073         } else {
9074           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9075         }
9076       }
9077       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9078     }
9079   }
9080   return uri;
9081 }
9082
9083 #define AMR_NB_ALL_MODES        0x81ff
9084 #define AMR_WB_ALL_MODES        0x83ff
9085 static guint
9086 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9087 {
9088   /* The 'damr' atom is of the form:
9089    *
9090    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9091    *    32 b       8 b          16 b           8 b                 8 b
9092    *
9093    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9094    * represents the highest mode used in the stream (and thus the maximum
9095    * bitrate), with a couple of special cases as seen below.
9096    */
9097
9098   /* Map of frame type ID -> bitrate */
9099   static const guint nb_bitrates[] = {
9100     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9101   };
9102   static const guint wb_bitrates[] = {
9103     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9104   };
9105   GstMapInfo map;
9106   gsize max_mode;
9107   guint16 mode_set;
9108
9109   gst_buffer_map (buf, &map, GST_MAP_READ);
9110
9111   if (map.size != 0x11) {
9112     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9113     goto bad_data;
9114   }
9115
9116   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9117     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9118         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9119     goto bad_data;
9120   }
9121
9122   mode_set = QT_UINT16 (map.data + 13);
9123
9124   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9125     max_mode = 7 + (wb ? 1 : 0);
9126   else
9127     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9128     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9129
9130   if (max_mode == -1) {
9131     GST_DEBUG ("No mode indication was found (mode set) = %x",
9132         (guint) mode_set);
9133     goto bad_data;
9134   }
9135
9136   gst_buffer_unmap (buf, &map);
9137   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9138
9139 bad_data:
9140   gst_buffer_unmap (buf, &map);
9141   return 0;
9142 }
9143
9144 static gboolean
9145 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9146     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9147 {
9148   /*
9149    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9150    * [0 1 2]
9151    * [3 4 5]
9152    * [6 7 8]
9153    */
9154
9155   if (gst_byte_reader_get_remaining (reader) < 36)
9156     return FALSE;
9157
9158   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9159   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9160   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9161   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9162   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9163   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9164   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9165   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9166   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9167
9168   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9169   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9170       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9171       matrix[2] & 0xFF);
9172   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9173       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9174       matrix[5] & 0xFF);
9175   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9176       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9177       matrix[8] & 0xFF);
9178
9179   return TRUE;
9180 }
9181
9182 static void
9183 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9184     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9185 {
9186
9187 /* [a b c]
9188  * [d e f]
9189  * [g h i]
9190  *
9191  * This macro will only compare value abdegh, it expects cfi to have already
9192  * been checked
9193  */
9194 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9195                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9196
9197   /* only handle the cases where the last column has standard values */
9198   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9199     const gchar *rotation_tag = NULL;
9200
9201     /* no rotation needed */
9202     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9203       /* NOP */
9204     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9205       rotation_tag = "rotate-90";
9206     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9207       rotation_tag = "rotate-180";
9208     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9209       rotation_tag = "rotate-270";
9210     } else {
9211       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9212     }
9213
9214     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9215         rotation_tag);
9216     if (rotation_tag != NULL) {
9217       if (*taglist == NULL)
9218         *taglist = gst_tag_list_new_empty ();
9219       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9220           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9221     }
9222   } else {
9223     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9224   }
9225 }
9226
9227 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9228  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9229  * Common Encryption (cenc), the function will also parse the tenc box (defined
9230  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9231  * (typically an enc[v|a|t|s] sample entry); the function will set
9232  * @original_fmt to the fourcc of the original unencrypted stream format.
9233  * Returns TRUE if successful; FALSE otherwise. */
9234 static gboolean
9235 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9236     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9237 {
9238   GNode *sinf;
9239   GNode *frma;
9240   GNode *schm;
9241   GNode *schi;
9242
9243   g_return_val_if_fail (qtdemux != NULL, FALSE);
9244   g_return_val_if_fail (stream != NULL, FALSE);
9245   g_return_val_if_fail (container != NULL, FALSE);
9246   g_return_val_if_fail (original_fmt != NULL, FALSE);
9247
9248   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9249   if (G_UNLIKELY (!sinf)) {
9250     if (stream->protection_scheme_type == FOURCC_cenc) {
9251       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9252           "mandatory for Common Encryption");
9253       return FALSE;
9254     }
9255     return TRUE;
9256   }
9257
9258   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9259   if (G_UNLIKELY (!frma)) {
9260     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9261     return FALSE;
9262   }
9263
9264   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9265   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9266       GST_FOURCC_ARGS (*original_fmt));
9267
9268   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9269   if (!schm) {
9270     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9271     return FALSE;
9272   }
9273   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9274   stream->protection_scheme_version =
9275       QT_UINT32 ((const guint8 *) schm->data + 16);
9276
9277   GST_DEBUG_OBJECT (qtdemux,
9278       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9279       "protection_scheme_version: %#010x",
9280       GST_FOURCC_ARGS (stream->protection_scheme_type),
9281       stream->protection_scheme_version);
9282
9283   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9284   if (!schi) {
9285     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9286     return FALSE;
9287   }
9288   if (stream->protection_scheme_type == FOURCC_cenc) {
9289     QtDemuxCencSampleSetInfo *info;
9290     GNode *tenc;
9291     const guint8 *tenc_data;
9292     guint32 isEncrypted;
9293     guint8 iv_size;
9294     const guint8 *default_kid;
9295     GstBuffer *kid_buf;
9296
9297     if (G_UNLIKELY (!stream->protection_scheme_info))
9298       stream->protection_scheme_info =
9299           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9300
9301     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9302
9303     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9304     if (!tenc) {
9305       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9306           "which is mandatory for Common Encryption");
9307       return FALSE;
9308     }
9309     tenc_data = (const guint8 *) tenc->data + 12;
9310     isEncrypted = QT_UINT24 (tenc_data);
9311     iv_size = QT_UINT8 (tenc_data + 3);
9312     default_kid = (tenc_data + 4);
9313     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9314     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9315     if (info->default_properties)
9316       gst_structure_free (info->default_properties);
9317     info->default_properties =
9318         gst_structure_new ("application/x-cenc",
9319         "iv_size", G_TYPE_UINT, iv_size,
9320         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9321         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9322     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9323         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9324     gst_buffer_unref (kid_buf);
9325   }
9326   return TRUE;
9327 }
9328
9329 /* parse the traks.
9330  * With each track we associate a new QtDemuxStream that contains all the info
9331  * about the trak.
9332  * traks that do not decode to something (like strm traks) will not have a pad.
9333  */
9334 static gboolean
9335 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9336 {
9337   GstByteReader tkhd;
9338   int offset;
9339   GNode *mdia;
9340   GNode *mdhd;
9341   GNode *hdlr;
9342   GNode *minf;
9343   GNode *stbl;
9344   GNode *stsd;
9345   GNode *mp4a;
9346   GNode *mp4v;
9347   GNode *wave;
9348   GNode *esds;
9349   GNode *pasp;
9350   GNode *colr;
9351   GNode *tref;
9352   GNode *udta;
9353   GNode *svmi;
9354   GNode *fiel;
9355
9356   QtDemuxStream *stream = NULL;
9357   gboolean new_stream = FALSE;
9358   gchar *codec = NULL;
9359   const guint8 *stsd_data;
9360   guint16 lang_code;            /* quicktime lang code or packed iso code */
9361   guint32 version;
9362   guint32 tkhd_flags = 0;
9363   guint8 tkhd_version = 0;
9364   guint32 fourcc;
9365   guint value_size, stsd_len, len;
9366   guint32 track_id;
9367   guint32 dummy;
9368
9369   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9370
9371   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9372       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9373       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9374     goto corrupt_file;
9375
9376   /* pick between 64 or 32 bits */
9377   value_size = tkhd_version == 1 ? 8 : 4;
9378   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9379       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9380     goto corrupt_file;
9381
9382   if (!qtdemux->got_moov) {
9383     if (qtdemux_find_stream (qtdemux, track_id))
9384       goto existing_stream;
9385     stream = _create_stream ();
9386     stream->track_id = track_id;
9387     new_stream = TRUE;
9388   } else {
9389     stream = qtdemux_find_stream (qtdemux, track_id);
9390     if (!stream) {
9391       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9392       goto skip_track;
9393     }
9394
9395     /* flush samples data from this track from previous moov */
9396     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9397     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9398   }
9399   /* need defaults for fragments */
9400   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9401
9402   if (stream->pending_tags == NULL)
9403     stream->pending_tags = gst_tag_list_new_empty ();
9404
9405   if ((tkhd_flags & 1) == 0)
9406     stream->disabled = TRUE;
9407
9408   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9409       tkhd_version, tkhd_flags, stream->track_id);
9410
9411   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9412     goto corrupt_file;
9413
9414   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9415     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9416     if (qtdemux->major_brand != FOURCC_mjp2 ||
9417         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9418       goto corrupt_file;
9419   }
9420
9421   len = QT_UINT32 ((guint8 *) mdhd->data);
9422   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9423   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9424   if (version == 0x01000000) {
9425     if (len < 38)
9426       goto corrupt_file;
9427     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9428     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9429     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9430   } else {
9431     if (len < 30)
9432       goto corrupt_file;
9433     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9434     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9435     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9436   }
9437
9438   if (lang_code < 0x400) {
9439     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9440   } else if (lang_code == 0x7fff) {
9441     stream->lang_id[0] = 0;     /* unspecified */
9442   } else {
9443     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9444     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9445     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9446     stream->lang_id[3] = 0;
9447   }
9448
9449   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9450       stream->timescale);
9451   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9452       stream->duration);
9453   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9454       lang_code, stream->lang_id);
9455
9456   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9457     goto corrupt_file;
9458
9459   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9460     /* chapters track reference */
9461     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9462     if (chap) {
9463       gsize length = GST_READ_UINT32_BE (chap->data);
9464       if (qtdemux->chapters_track_id)
9465         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9466
9467       if (length >= 12) {
9468         qtdemux->chapters_track_id =
9469             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9470       }
9471     }
9472   }
9473
9474   /* fragmented files may have bogus duration in moov */
9475   if (!qtdemux->fragmented &&
9476       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9477     guint64 tdur1, tdur2;
9478
9479     /* don't overflow */
9480     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9481     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9482
9483     /* HACK:
9484      * some of those trailers, nowadays, have prologue images that are
9485      * themselves video tracks as well. I haven't really found a way to
9486      * identify those yet, except for just looking at their duration. */
9487     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9488       GST_WARNING_OBJECT (qtdemux,
9489           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9490           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9491           "found, assuming preview image or something; skipping track",
9492           stream->duration, stream->timescale, qtdemux->duration,
9493           qtdemux->timescale);
9494       if (new_stream)
9495         gst_qtdemux_stream_free (qtdemux, stream);
9496       return TRUE;
9497     }
9498   }
9499
9500   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9501     goto corrupt_file;
9502
9503   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9504       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9505
9506   len = QT_UINT32 ((guint8 *) hdlr->data);
9507   if (len >= 20)
9508     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9509   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9510       GST_FOURCC_ARGS (stream->subtype));
9511
9512   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9513     goto corrupt_file;
9514
9515   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9516     goto corrupt_file;
9517
9518   /*parse svmi header if existing */
9519   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9520   if (svmi) {
9521     len = QT_UINT32 ((guint8 *) svmi->data);
9522     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9523     if (!version) {
9524       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9525       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9526       guint8 frame_type, frame_layout;
9527
9528       /* MPEG-A stereo video */
9529       if (qtdemux->major_brand == FOURCC_ss02)
9530         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9531
9532       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9533       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9534       switch (frame_type) {
9535         case 0:
9536           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9537           break;
9538         case 1:
9539           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9540           break;
9541         case 2:
9542           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9543           break;
9544         case 3:
9545           /* mode 3 is primary/secondary view sequence, ie
9546            * left/right views in separate tracks. See section 7.2
9547            * of ISO/IEC 23000-11:2009 */
9548           GST_FIXME_OBJECT (qtdemux,
9549               "Implement stereo video in separate streams");
9550       }
9551
9552       if ((frame_layout & 0x1) == 0)
9553         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9554
9555       GST_LOG_OBJECT (qtdemux,
9556           "StereoVideo: composition type: %u, is_left_first: %u",
9557           frame_type, frame_layout);
9558       stream->multiview_mode = mode;
9559       stream->multiview_flags = flags;
9560     }
9561   }
9562
9563   /* parse stsd */
9564   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9565     goto corrupt_file;
9566   stsd_data = (const guint8 *) stsd->data;
9567
9568   /* stsd should at least have one entry */
9569   stsd_len = QT_UINT32 (stsd_data);
9570   if (stsd_len < 24) {
9571     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9572     if (stream->subtype == FOURCC_vivo) {
9573       if (new_stream)
9574         gst_qtdemux_stream_free (qtdemux, stream);
9575       return TRUE;
9576     } else {
9577       goto corrupt_file;
9578     }
9579   }
9580
9581   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9582
9583   /* and that entry should fit within stsd */
9584   len = QT_UINT32 (stsd_data + 16);
9585   if (len > stsd_len + 16)
9586     goto corrupt_file;
9587
9588   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9589   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9590       GST_FOURCC_ARGS (stream->fourcc));
9591   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9592
9593   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9594     goto error_encrypted;
9595
9596   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9597     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9598     stream->protected = TRUE;
9599     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9600       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9601   }
9602
9603   if (stream->subtype == FOURCC_vide) {
9604     guint32 w = 0, h = 0;
9605     gboolean gray;
9606     gint depth, palette_size, palette_count;
9607     guint32 matrix[9];
9608     guint32 *palette_data = NULL;
9609
9610     stream->sampled = TRUE;
9611
9612     /* version 1 uses some 64-bit ints */
9613     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9614       goto corrupt_file;
9615
9616     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9617       goto corrupt_file;
9618
9619     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9620         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9621       goto corrupt_file;
9622
9623     stream->display_width = w >> 16;
9624     stream->display_height = h >> 16;
9625
9626     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9627         &stream->pending_tags);
9628
9629     offset = 16;
9630     if (len < 86)
9631       goto corrupt_file;
9632
9633     stream->width = QT_UINT16 (stsd_data + offset + 32);
9634     stream->height = QT_UINT16 (stsd_data + offset + 34);
9635     stream->fps_n = 0;          /* this is filled in later */
9636     stream->fps_d = 0;          /* this is filled in later */
9637     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9638     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9639
9640     /* if color_table_id is 0, ctab atom must follow; however some files
9641      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9642      * if color table is not present we'll correct the value */
9643     if (stream->color_table_id == 0 &&
9644         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9645       stream->color_table_id = -1;
9646     }
9647
9648     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9649         stream->width, stream->height, stream->bits_per_sample,
9650         stream->color_table_id);
9651
9652     depth = stream->bits_per_sample;
9653
9654     /* more than 32 bits means grayscale */
9655     gray = (depth > 32);
9656     /* low 32 bits specify the depth  */
9657     depth &= 0x1F;
9658
9659     /* different number of palette entries is determined by depth. */
9660     palette_count = 0;
9661     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9662       palette_count = (1 << depth);
9663     palette_size = palette_count * 4;
9664
9665     if (stream->color_table_id) {
9666       switch (palette_count) {
9667         case 0:
9668           break;
9669         case 2:
9670           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9671           break;
9672         case 4:
9673           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9674           break;
9675         case 16:
9676           if (gray)
9677             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9678           else
9679             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9680           break;
9681         case 256:
9682           if (gray)
9683             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9684           else
9685             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9686           break;
9687         default:
9688           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9689               (_("The video in this file might not play correctly.")),
9690               ("unsupported palette depth %d", depth));
9691           break;
9692       }
9693     } else {
9694       gint i, j, start, end;
9695
9696       if (len < 94)
9697         goto corrupt_file;
9698
9699       /* read table */
9700       start = QT_UINT32 (stsd_data + offset + 86);
9701       palette_count = QT_UINT16 (stsd_data + offset + 90);
9702       end = QT_UINT16 (stsd_data + offset + 92);
9703
9704       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9705           start, end, palette_count);
9706
9707       if (end > 255)
9708         end = 255;
9709       if (start > end)
9710         start = end;
9711
9712       if (len < 94 + (end - start) * 8)
9713         goto corrupt_file;
9714
9715       /* palette is always the same size */
9716       palette_data = g_malloc0 (256 * 4);
9717       palette_size = 256 * 4;
9718
9719       for (j = 0, i = start; i <= end; j++, i++) {
9720         guint32 a, r, g, b;
9721
9722         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9723         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9724         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9725         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9726
9727         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9728             (g & 0xff00) | (b >> 8);
9729       }
9730     }
9731
9732     if (stream->caps)
9733       gst_caps_unref (stream->caps);
9734
9735     stream->caps =
9736         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9737     if (G_UNLIKELY (!stream->caps)) {
9738       g_free (palette_data);
9739       goto unknown_stream;
9740     }
9741
9742     if (codec) {
9743       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9744           GST_TAG_VIDEO_CODEC, codec, NULL);
9745       g_free (codec);
9746       codec = NULL;
9747     }
9748
9749
9750     if (palette_data) {
9751       GstStructure *s;
9752
9753       if (stream->rgb8_palette)
9754         gst_memory_unref (stream->rgb8_palette);
9755       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9756           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9757
9758       s = gst_caps_get_structure (stream->caps, 0);
9759
9760       /* non-raw video has a palette_data property. raw video has the palette as
9761        * an extra plane that we append to the output buffers before we push
9762        * them*/
9763       if (!gst_structure_has_name (s, "video/x-raw")) {
9764         GstBuffer *palette;
9765
9766         palette = gst_buffer_new ();
9767         gst_buffer_append_memory (palette, stream->rgb8_palette);
9768         stream->rgb8_palette = NULL;
9769
9770         gst_caps_set_simple (stream->caps, "palette_data",
9771             GST_TYPE_BUFFER, palette, NULL);
9772         gst_buffer_unref (palette);
9773       }
9774     } else if (palette_count != 0) {
9775       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9776           (NULL), ("Unsupported palette depth %d", depth));
9777     }
9778
9779     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9780         QT_UINT16 (stsd_data + offset + 48));
9781
9782     esds = NULL;
9783     pasp = NULL;
9784     colr = NULL;
9785     fiel = NULL;
9786     /* pick 'the' stsd child */
9787     if (!stream->protected)
9788       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9789     else
9790       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9791
9792     if (mp4v) {
9793       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9794       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9795       colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
9796       fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
9797     }
9798
9799     if (pasp) {
9800       const guint8 *pasp_data = (const guint8 *) pasp->data;
9801       gint len = QT_UINT32 (pasp_data);
9802
9803       if (len == 16) {
9804         stream->par_w = QT_UINT32 (pasp_data + 8);
9805         stream->par_h = QT_UINT32 (pasp_data + 12);
9806       } else {
9807         stream->par_w = 0;
9808         stream->par_h = 0;
9809       }
9810     } else {
9811       stream->par_w = 0;
9812       stream->par_h = 0;
9813     }
9814
9815     if (fiel) {
9816       const guint8 *fiel_data = (const guint8 *) fiel->data;
9817       gint len = QT_UINT32 (fiel_data);
9818
9819       if (len == 10) {
9820         stream->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
9821         stream->field_order = GST_READ_UINT8 (fiel_data + 9);
9822       }
9823     }
9824
9825     if (colr) {
9826       const guint8 *colr_data = (const guint8 *) colr->data;
9827       gint len = QT_UINT32 (colr_data);
9828
9829       if (len == 19 || len == 18) {
9830         guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
9831
9832         if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
9833           guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
9834           guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
9835           guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
9836           gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
9837
9838           switch (primaries) {
9839             case 1:
9840               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
9841               break;
9842             case 5:
9843               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
9844               break;
9845             case 6:
9846               stream->colorimetry.primaries =
9847                   GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
9848               break;
9849             case 9:
9850               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT2020;
9851               break;
9852             default:
9853               break;
9854           }
9855
9856           switch (transfer_function) {
9857             case 1:
9858               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
9859               break;
9860             case 7:
9861               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE240M;
9862               break;
9863             default:
9864               break;
9865           }
9866
9867           switch (matrix) {
9868             case 1:
9869               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
9870               break;
9871             case 6:
9872               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
9873               break;
9874             case 7:
9875               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_SMPTE240M;
9876               break;
9877             case 9:
9878               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT2020;
9879               break;
9880             default:
9881               break;
9882           }
9883
9884           stream->colorimetry.range =
9885               full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
9886               GST_VIDEO_COLOR_RANGE_16_235;
9887         } else {
9888           GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
9889         }
9890       } else {
9891         GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
9892       }
9893     }
9894
9895     if (esds) {
9896       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9897     } else {
9898       switch (fourcc) {
9899         case FOURCC_H264:
9900         case FOURCC_avc1:
9901         case FOURCC_avc3:
9902         {
9903           gint len = QT_UINT32 (stsd_data) - 0x66;
9904           const guint8 *avc_data = stsd_data + 0x66;
9905
9906           /* find avcC */
9907           while (len >= 0x8) {
9908             gint size;
9909
9910             if (QT_UINT32 (avc_data) <= len)
9911               size = QT_UINT32 (avc_data) - 0x8;
9912             else
9913               size = len - 0x8;
9914
9915             if (size < 1)
9916               /* No real data, so break out */
9917               break;
9918
9919             switch (QT_FOURCC (avc_data + 0x4)) {
9920               case FOURCC_avcC:
9921               {
9922                 /* parse, if found */
9923                 GstBuffer *buf;
9924
9925                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9926
9927                 /* First 4 bytes are the length of the atom, the next 4 bytes
9928                  * are the fourcc, the next 1 byte is the version, and the
9929                  * subsequent bytes are profile_tier_level structure like data. */
9930                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9931                     avc_data + 8 + 1, size - 1);
9932                 buf = gst_buffer_new_and_alloc (size);
9933                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9934                 gst_caps_set_simple (stream->caps,
9935                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9936                 gst_buffer_unref (buf);
9937
9938                 break;
9939               }
9940               case FOURCC_strf:
9941               {
9942                 GstBuffer *buf;
9943
9944                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9945
9946                 /* First 4 bytes are the length of the atom, the next 4 bytes
9947                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9948                  * next 1 byte is the version, and the
9949                  * subsequent bytes are sequence parameter set like data. */
9950
9951                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9952                 if (size > 1) {
9953                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9954                       avc_data + 8 + 40 + 1, size - 1);
9955
9956                   buf = gst_buffer_new_and_alloc (size);
9957                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9958                   gst_caps_set_simple (stream->caps,
9959                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9960                   gst_buffer_unref (buf);
9961                 }
9962                 break;
9963               }
9964               case FOURCC_btrt:
9965               {
9966                 guint avg_bitrate, max_bitrate;
9967
9968                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9969                 if (size < 12)
9970                   break;
9971
9972                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9973                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9974
9975                 if (!max_bitrate && !avg_bitrate)
9976                   break;
9977
9978                 /* Some muxers seem to swap the average and maximum bitrates
9979                  * (I'm looking at you, YouTube), so we swap for sanity. */
9980                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9981                   guint temp = avg_bitrate;
9982
9983                   avg_bitrate = max_bitrate;
9984                   max_bitrate = temp;
9985                 }
9986
9987                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9988                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9989                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9990                 }
9991                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9992                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9993                       GST_TAG_BITRATE, avg_bitrate, NULL);
9994                 }
9995
9996                 break;
9997               }
9998
9999               default:
10000                 break;
10001             }
10002
10003             len -= size + 8;
10004             avc_data += size + 8;
10005           }
10006
10007           break;
10008         }
10009         case FOURCC_H265:
10010         case FOURCC_hvc1:
10011         case FOURCC_hev1:
10012         {
10013           gint len = QT_UINT32 (stsd_data) - 0x66;
10014           const guint8 *hevc_data = stsd_data + 0x66;
10015
10016           /* find hevc */
10017           while (len >= 0x8) {
10018             gint size;
10019
10020             if (QT_UINT32 (hevc_data) <= len)
10021               size = QT_UINT32 (hevc_data) - 0x8;
10022             else
10023               size = len - 0x8;
10024
10025             if (size < 1)
10026               /* No real data, so break out */
10027               break;
10028
10029             switch (QT_FOURCC (hevc_data + 0x4)) {
10030               case FOURCC_hvcC:
10031               {
10032                 /* parse, if found */
10033                 GstBuffer *buf;
10034
10035                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10036
10037                 /* First 4 bytes are the length of the atom, the next 4 bytes
10038                  * are the fourcc, the next 1 byte is the version, and the
10039                  * subsequent bytes are sequence parameter set like data. */
10040                 gst_codec_utils_h265_caps_set_level_tier_and_profile
10041                     (stream->caps, hevc_data + 8 + 1, size - 1);
10042
10043                 buf = gst_buffer_new_and_alloc (size);
10044                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10045                 gst_caps_set_simple (stream->caps,
10046                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10047                 gst_buffer_unref (buf);
10048                 break;
10049               }
10050               default:
10051                 break;
10052             }
10053             len -= size + 8;
10054             hevc_data += size + 8;
10055           }
10056           break;
10057         }
10058         case FOURCC_mp4v:
10059         case FOURCC_MP4V:
10060         case FOURCC_fmp4:
10061         case FOURCC_FMP4:
10062         case FOURCC_xvid:
10063         case FOURCC_XVID:
10064         {
10065           GNode *glbl;
10066
10067           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10068               GST_FOURCC_ARGS (fourcc));
10069
10070           /* codec data might be in glbl extension atom */
10071           glbl = mp4v ?
10072               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10073           if (glbl) {
10074             guint8 *data;
10075             GstBuffer *buf;
10076             gint len;
10077
10078             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10079             data = glbl->data;
10080             len = QT_UINT32 (data);
10081             if (len > 0x8) {
10082               len -= 0x8;
10083               buf = gst_buffer_new_and_alloc (len);
10084               gst_buffer_fill (buf, 0, data + 8, len);
10085               gst_caps_set_simple (stream->caps,
10086                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10087               gst_buffer_unref (buf);
10088             }
10089           }
10090           break;
10091         }
10092         case FOURCC_mjp2:
10093         {
10094           /* see annex I of the jpeg2000 spec */
10095           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10096           const guint8 *data;
10097           const gchar *colorspace = NULL;
10098           gint ncomp = 0;
10099           guint32 ncomp_map = 0;
10100           gint32 *comp_map = NULL;
10101           guint32 nchan_def = 0;
10102           gint32 *chan_def = NULL;
10103
10104           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10105           /* some required atoms */
10106           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
10107           if (!mjp2)
10108             break;
10109           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10110           if (!jp2h)
10111             break;
10112
10113           /* number of components; redundant with info in codestream, but useful
10114              to a muxer */
10115           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10116           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10117             break;
10118           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10119
10120           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10121           if (!colr)
10122             break;
10123           GST_DEBUG_OBJECT (qtdemux, "found colr");
10124           /* extract colour space info */
10125           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10126             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10127               case 16:
10128                 colorspace = "sRGB";
10129                 break;
10130               case 17:
10131                 colorspace = "GRAY";
10132                 break;
10133               case 18:
10134                 colorspace = "sYUV";
10135                 break;
10136               default:
10137                 colorspace = NULL;
10138                 break;
10139             }
10140           }
10141           if (!colorspace)
10142             /* colr is required, and only values 16, 17, and 18 are specified,
10143                so error if we have no colorspace */
10144             break;
10145
10146           /* extract component mapping */
10147           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10148           if (cmap) {
10149             guint32 cmap_len = 0;
10150             int i;
10151             cmap_len = QT_UINT32 (cmap->data);
10152             if (cmap_len >= 8) {
10153               /* normal box, subtract off header */
10154               cmap_len -= 8;
10155               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10156               if (cmap_len % 4 == 0) {
10157                 ncomp_map = (cmap_len / 4);
10158                 comp_map = g_new0 (gint32, ncomp_map);
10159                 for (i = 0; i < ncomp_map; i++) {
10160                   guint16 cmp;
10161                   guint8 mtyp, pcol;
10162                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10163                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10164                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10165                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10166                 }
10167               }
10168             }
10169           }
10170           /* extract channel definitions */
10171           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10172           if (cdef) {
10173             guint32 cdef_len = 0;
10174             int i;
10175             cdef_len = QT_UINT32 (cdef->data);
10176             if (cdef_len >= 10) {
10177               /* normal box, subtract off header and len */
10178               cdef_len -= 10;
10179               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10180               if (cdef_len % 6 == 0) {
10181                 nchan_def = (cdef_len / 6);
10182                 chan_def = g_new0 (gint32, nchan_def);
10183                 for (i = 0; i < nchan_def; i++)
10184                   chan_def[i] = -1;
10185                 for (i = 0; i < nchan_def; i++) {
10186                   guint16 cn, typ, asoc;
10187                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10188                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10189                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10190                   if (cn < nchan_def) {
10191                     switch (typ) {
10192                       case 0:
10193                         chan_def[cn] = asoc;
10194                         break;
10195                       case 1:
10196                         chan_def[cn] = 0;       /* alpha */
10197                         break;
10198                       default:
10199                         chan_def[cn] = -typ;
10200                     }
10201                   }
10202                 }
10203               }
10204             }
10205           }
10206
10207           gst_caps_set_simple (stream->caps,
10208               "num-components", G_TYPE_INT, ncomp, NULL);
10209           gst_caps_set_simple (stream->caps,
10210               "colorspace", G_TYPE_STRING, colorspace, NULL);
10211
10212           if (comp_map) {
10213             GValue arr = { 0, };
10214             GValue elt = { 0, };
10215             int i;
10216             g_value_init (&arr, GST_TYPE_ARRAY);
10217             g_value_init (&elt, G_TYPE_INT);
10218             for (i = 0; i < ncomp_map; i++) {
10219               g_value_set_int (&elt, comp_map[i]);
10220               gst_value_array_append_value (&arr, &elt);
10221             }
10222             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10223                 "component-map", &arr);
10224             g_value_unset (&elt);
10225             g_value_unset (&arr);
10226             g_free (comp_map);
10227           }
10228
10229           if (chan_def) {
10230             GValue arr = { 0, };
10231             GValue elt = { 0, };
10232             int i;
10233             g_value_init (&arr, GST_TYPE_ARRAY);
10234             g_value_init (&elt, G_TYPE_INT);
10235             for (i = 0; i < nchan_def; i++) {
10236               g_value_set_int (&elt, chan_def[i]);
10237               gst_value_array_append_value (&arr, &elt);
10238             }
10239             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10240                 "channel-definitions", &arr);
10241             g_value_unset (&elt);
10242             g_value_unset (&arr);
10243             g_free (chan_def);
10244           }
10245
10246           /* some optional atoms */
10247           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10248           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10249
10250           /* indicate possible fields in caps */
10251           if (field) {
10252             data = (guint8 *) field->data + 8;
10253             if (*data != 1)
10254               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
10255                   (gint) * data, NULL);
10256           }
10257           /* add codec_data if provided */
10258           if (prefix) {
10259             GstBuffer *buf;
10260             gint len;
10261
10262             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10263             data = prefix->data;
10264             len = QT_UINT32 (data);
10265             if (len > 0x8) {
10266               len -= 0x8;
10267               buf = gst_buffer_new_and_alloc (len);
10268               gst_buffer_fill (buf, 0, data + 8, len);
10269               gst_caps_set_simple (stream->caps,
10270                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10271               gst_buffer_unref (buf);
10272             }
10273           }
10274           break;
10275         }
10276         case FOURCC_jpeg:
10277         {
10278           /* https://developer.apple.com/standards/qtff-2001.pdf,
10279            * page 92, "Video Sample Description", under table 3.1 */
10280           GstByteReader br;
10281
10282           const gint compressor_offset = 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10283           const gint min_size = compressor_offset + 32 + 2 + 2;
10284           GNode *jpeg;
10285           guint32 len;
10286           guint16 color_table_id = 0;
10287           gboolean ok;
10288
10289           GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10290
10291           /* recover information on interlaced/progressive */
10292           jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10293           if (!jpeg)
10294             break;
10295
10296           len = QT_UINT32 (jpeg->data);
10297           GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10298               min_size);
10299           if (len >= min_size) {
10300             gst_byte_reader_init (&br, jpeg->data, len);
10301
10302             gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10303             gst_byte_reader_get_uint16_le (&br, &color_table_id);
10304             if (color_table_id != 0) {
10305               /* the spec says there can be concatenated chunks in the data, and we want
10306                * to find one called field. Walk through them. */
10307               gint offset = min_size;
10308               while (offset + 8 < len) {
10309                 guint32 size = 0, tag;
10310                 ok = gst_byte_reader_get_uint32_le (&br, &size);
10311                 ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10312                 if (!ok || size < 8) {
10313                   GST_WARNING_OBJECT (qtdemux,
10314                       "Failed to walk optional chunk list");
10315                   break;
10316                 }
10317                 GST_DEBUG_OBJECT (qtdemux,
10318                     "Found optional %4.4s chunk, size %u", (const char *) &tag,
10319                     size);
10320                 if (tag == FOURCC_fiel) {
10321                   guint8 n_fields, ordering;
10322                   gst_byte_reader_get_uint8 (&br, &n_fields);
10323                   gst_byte_reader_get_uint8 (&br, &ordering);
10324                   if (n_fields == 1 || n_fields == 2) {
10325                     GST_DEBUG_OBJECT (qtdemux,
10326                         "Found fiel tag with %u fields, ordering %u", n_fields,
10327                         ordering);
10328                     if (n_fields == 2)
10329                       gst_caps_set_simple (stream->caps, "interlace-mode",
10330                           G_TYPE_STRING, "interleaved", NULL);
10331                   } else {
10332                     GST_WARNING_OBJECT (qtdemux,
10333                         "Found fiel tag with invalid fields (%u)", n_fields);
10334                   }
10335                 }
10336                 offset += size;
10337               }
10338             } else {
10339               GST_DEBUG_OBJECT (qtdemux,
10340                   "Color table ID is 0, not trying to get interlacedness");
10341             }
10342           } else {
10343             GST_WARNING_OBJECT (qtdemux,
10344                 "Length of jpeg chunk is too small, not trying to get interlacedness");
10345           }
10346
10347           break;
10348         }
10349         case FOURCC_SVQ3:
10350         case FOURCC_VP31:
10351         {
10352           GstBuffer *buf;
10353           GstBuffer *seqh = NULL;
10354           guint8 *gamma_data = NULL;
10355           gint len = QT_UINT32 (stsd_data);
10356
10357           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
10358           if (gamma_data) {
10359             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
10360                 QT_FP32 (gamma_data), NULL);
10361           }
10362           if (seqh) {
10363             /* sorry for the bad name, but we don't know what this is, other
10364              * than its own fourcc */
10365             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
10366                 NULL);
10367           }
10368
10369           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10370           buf = gst_buffer_new_and_alloc (len);
10371           gst_buffer_fill (buf, 0, stsd_data, len);
10372           gst_caps_set_simple (stream->caps,
10373               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10374           gst_buffer_unref (buf);
10375           break;
10376         }
10377         case FOURCC_rle_:
10378         case FOURCC_WRLE:
10379         {
10380           gst_caps_set_simple (stream->caps,
10381               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
10382           break;
10383         }
10384         case FOURCC_XiTh:
10385         {
10386           GNode *xith, *xdxt;
10387
10388           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10389           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
10390           if (!xith)
10391             break;
10392
10393           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10394           if (!xdxt)
10395             break;
10396
10397           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10398           /* collect the headers and store them in a stream list so that we can
10399            * send them out first */
10400           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10401           break;
10402         }
10403         case FOURCC_ovc1:
10404         {
10405           GNode *ovc1;
10406           guint8 *ovc1_data;
10407           guint ovc1_len;
10408           GstBuffer *buf;
10409
10410           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10411           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
10412           if (!ovc1)
10413             break;
10414           ovc1_data = ovc1->data;
10415           ovc1_len = QT_UINT32 (ovc1_data);
10416           if (ovc1_len <= 198) {
10417             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10418             break;
10419           }
10420           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10421           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10422           gst_caps_set_simple (stream->caps,
10423               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10424           gst_buffer_unref (buf);
10425           break;
10426         }
10427         case FOURCC_vc_1:
10428         {
10429           gint len = QT_UINT32 (stsd_data) - 0x66;
10430           const guint8 *vc1_data = stsd_data + 0x66;
10431
10432           /* find dvc1 */
10433           while (len >= 8) {
10434             gint size;
10435
10436             if (QT_UINT32 (vc1_data) <= len)
10437               size = QT_UINT32 (vc1_data) - 8;
10438             else
10439               size = len - 8;
10440
10441             if (size < 1)
10442               /* No real data, so break out */
10443               break;
10444
10445             switch (QT_FOURCC (vc1_data + 0x4)) {
10446               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10447               {
10448                 GstBuffer *buf;
10449
10450                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10451                 buf = gst_buffer_new_and_alloc (size);
10452                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
10453                 gst_caps_set_simple (stream->caps,
10454                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10455                 gst_buffer_unref (buf);
10456                 break;
10457               }
10458               default:
10459                 break;
10460             }
10461             len -= size + 8;
10462             vc1_data += size + 8;
10463           }
10464           break;
10465         }
10466         default:
10467           break;
10468       }
10469     }
10470
10471     GST_INFO_OBJECT (qtdemux,
10472         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10473         GST_FOURCC_ARGS (fourcc), stream->caps);
10474
10475   } else if (stream->subtype == FOURCC_soun) {
10476     int version, samplesize;
10477     guint16 compression_id;
10478     gboolean amrwb = FALSE;
10479
10480     offset = 32;
10481     /* sample description entry (16) + sound sample description v0 (20) */
10482     if (len < 36)
10483       goto corrupt_file;
10484
10485     version = QT_UINT32 (stsd_data + offset);
10486     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10487     samplesize = QT_UINT16 (stsd_data + offset + 10);
10488     compression_id = QT_UINT16 (stsd_data + offset + 12);
10489     stream->rate = QT_FP32 (stsd_data + offset + 16);
10490
10491     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10492     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10493         QT_UINT32 (stsd_data + offset + 4));
10494     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10495     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10496     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10497     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10498         QT_UINT16 (stsd_data + offset + 14));
10499     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10500
10501     if (compression_id == 0xfffe)
10502       stream->sampled = TRUE;
10503
10504     /* first assume uncompressed audio */
10505     stream->bytes_per_sample = samplesize / 8;
10506     stream->samples_per_frame = stream->n_channels;
10507     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10508     stream->samples_per_packet = stream->samples_per_frame;
10509     stream->bytes_per_packet = stream->bytes_per_sample;
10510
10511     offset = 52;
10512     switch (fourcc) {
10513         /* Yes, these have to be hard-coded */
10514       case FOURCC_MAC6:
10515       {
10516         stream->samples_per_packet = 6;
10517         stream->bytes_per_packet = 1;
10518         stream->bytes_per_frame = 1 * stream->n_channels;
10519         stream->bytes_per_sample = 1;
10520         stream->samples_per_frame = 6 * stream->n_channels;
10521         break;
10522       }
10523       case FOURCC_MAC3:
10524       {
10525         stream->samples_per_packet = 3;
10526         stream->bytes_per_packet = 1;
10527         stream->bytes_per_frame = 1 * stream->n_channels;
10528         stream->bytes_per_sample = 1;
10529         stream->samples_per_frame = 3 * stream->n_channels;
10530         break;
10531       }
10532       case FOURCC_ima4:
10533       {
10534         stream->samples_per_packet = 64;
10535         stream->bytes_per_packet = 34;
10536         stream->bytes_per_frame = 34 * stream->n_channels;
10537         stream->bytes_per_sample = 2;
10538         stream->samples_per_frame = 64 * stream->n_channels;
10539         break;
10540       }
10541       case FOURCC_ulaw:
10542       case FOURCC_alaw:
10543       {
10544         stream->samples_per_packet = 1;
10545         stream->bytes_per_packet = 1;
10546         stream->bytes_per_frame = 1 * stream->n_channels;
10547         stream->bytes_per_sample = 1;
10548         stream->samples_per_frame = 1 * stream->n_channels;
10549         break;
10550       }
10551       case FOURCC_agsm:
10552       {
10553         stream->samples_per_packet = 160;
10554         stream->bytes_per_packet = 33;
10555         stream->bytes_per_frame = 33 * stream->n_channels;
10556         stream->bytes_per_sample = 2;
10557         stream->samples_per_frame = 160 * stream->n_channels;
10558         break;
10559       }
10560       default:
10561         break;
10562     }
10563
10564     if (version == 0x00010000) {
10565       /* sample description entry (16) + sound sample description v1 (20+16) */
10566       if (len < 52)
10567         goto corrupt_file;
10568
10569       switch (fourcc) {
10570         case FOURCC_twos:
10571         case FOURCC_sowt:
10572         case FOURCC_raw_:
10573           break;
10574         default:
10575         {
10576           /* only parse extra decoding config for non-pcm audio */
10577           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10578           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10579           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10580           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10581
10582           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10583               stream->samples_per_packet);
10584           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10585               stream->bytes_per_packet);
10586           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10587               stream->bytes_per_frame);
10588           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10589               stream->bytes_per_sample);
10590
10591           if (!stream->sampled && stream->bytes_per_packet) {
10592             stream->samples_per_frame = (stream->bytes_per_frame /
10593                 stream->bytes_per_packet) * stream->samples_per_packet;
10594             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10595                 stream->samples_per_frame);
10596           }
10597           break;
10598         }
10599       }
10600     } else if (version == 0x00020000) {
10601       union
10602       {
10603         gdouble fp;
10604         guint64 val;
10605       } qtfp;
10606
10607       /* sample description entry (16) + sound sample description v2 (56) */
10608       if (len < 72)
10609         goto corrupt_file;
10610
10611       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10612       stream->rate = qtfp.fp;
10613       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10614
10615       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10616       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10617       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10618       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10619           QT_UINT32 (stsd_data + offset + 20));
10620       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10621           QT_UINT32 (stsd_data + offset + 24));
10622       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10623           QT_UINT32 (stsd_data + offset + 28));
10624       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10625           QT_UINT32 (stsd_data + offset + 32));
10626     } else if (version != 0x00000) {
10627       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10628     }
10629
10630     if (stream->caps)
10631       gst_caps_unref (stream->caps);
10632
10633     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10634         stsd_data + 32, len - 16, &codec);
10635
10636     switch (fourcc) {
10637       case FOURCC_in24:
10638       {
10639         GNode *enda;
10640         GNode *in24;
10641
10642         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10643
10644         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10645         if (!enda) {
10646           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10647           if (wave)
10648             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10649         }
10650         if (enda) {
10651           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10652           gst_caps_set_simple (stream->caps,
10653               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10654         }
10655         break;
10656       }
10657       case FOURCC_owma:
10658       {
10659         GNode *owma;
10660         const guint8 *owma_data;
10661         const gchar *codec_name = NULL;
10662         guint owma_len;
10663         GstBuffer *buf;
10664         gint version = 1;
10665         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10666         /* FIXME this should also be gst_riff_strf_auds,
10667          * but the latter one is actually missing bits-per-sample :( */
10668         typedef struct
10669         {
10670           gint16 wFormatTag;
10671           gint16 nChannels;
10672           gint32 nSamplesPerSec;
10673           gint32 nAvgBytesPerSec;
10674           gint16 nBlockAlign;
10675           gint16 wBitsPerSample;
10676           gint16 cbSize;
10677         } WAVEFORMATEX;
10678         WAVEFORMATEX *wfex;
10679
10680         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10681         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10682         if (!owma)
10683           break;
10684         owma_data = owma->data;
10685         owma_len = QT_UINT32 (owma_data);
10686         if (owma_len <= 54) {
10687           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10688           break;
10689         }
10690         wfex = (WAVEFORMATEX *) (owma_data + 36);
10691         buf = gst_buffer_new_and_alloc (owma_len - 54);
10692         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10693         if (wfex->wFormatTag == 0x0161) {
10694           codec_name = "Windows Media Audio";
10695           version = 2;
10696         } else if (wfex->wFormatTag == 0x0162) {
10697           codec_name = "Windows Media Audio 9 Pro";
10698           version = 3;
10699         } else if (wfex->wFormatTag == 0x0163) {
10700           codec_name = "Windows Media Audio 9 Lossless";
10701           /* is that correct? gstffmpegcodecmap.c is missing it, but
10702            * fluendo codec seems to support it */
10703           version = 4;
10704         }
10705
10706         gst_caps_set_simple (stream->caps,
10707             "codec_data", GST_TYPE_BUFFER, buf,
10708             "wmaversion", G_TYPE_INT, version,
10709             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10710             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10711             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10712             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10713             NULL);
10714         gst_buffer_unref (buf);
10715
10716         if (codec_name) {
10717           g_free (codec);
10718           codec = g_strdup (codec_name);
10719         }
10720         break;
10721       }
10722       case FOURCC_wma_:
10723       {
10724         gint len = QT_UINT32 (stsd_data) - offset;
10725         const guint8 *wfex_data = stsd_data + offset;
10726         const gchar *codec_name = NULL;
10727         gint version = 1;
10728         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10729         /* FIXME this should also be gst_riff_strf_auds,
10730          * but the latter one is actually missing bits-per-sample :( */
10731         typedef struct
10732         {
10733           gint16 wFormatTag;
10734           gint16 nChannels;
10735           gint32 nSamplesPerSec;
10736           gint32 nAvgBytesPerSec;
10737           gint16 nBlockAlign;
10738           gint16 wBitsPerSample;
10739           gint16 cbSize;
10740         } WAVEFORMATEX;
10741         WAVEFORMATEX wfex;
10742
10743         /* FIXME: unify with similar wavformatex parsing code above */
10744         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10745
10746         /* find wfex */
10747         while (len >= 8) {
10748           gint size;
10749
10750           if (QT_UINT32 (wfex_data) <= len)
10751             size = QT_UINT32 (wfex_data) - 8;
10752           else
10753             size = len - 8;
10754
10755           if (size < 1)
10756             /* No real data, so break out */
10757             break;
10758
10759           switch (QT_FOURCC (wfex_data + 4)) {
10760             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10761             {
10762               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10763
10764               if (size < 8 + 18)
10765                 break;
10766
10767               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10768               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10769               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10770               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10771               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10772               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10773               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10774
10775               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10776               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10777                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10778                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10779                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10780                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10781
10782               if (wfex.wFormatTag == 0x0161) {
10783                 codec_name = "Windows Media Audio";
10784                 version = 2;
10785               } else if (wfex.wFormatTag == 0x0162) {
10786                 codec_name = "Windows Media Audio 9 Pro";
10787                 version = 3;
10788               } else if (wfex.wFormatTag == 0x0163) {
10789                 codec_name = "Windows Media Audio 9 Lossless";
10790                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10791                  * fluendo codec seems to support it */
10792                 version = 4;
10793               }
10794
10795               gst_caps_set_simple (stream->caps,
10796                   "wmaversion", G_TYPE_INT, version,
10797                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10798                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10799                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10800                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10801
10802               if (size > wfex.cbSize) {
10803                 GstBuffer *buf;
10804
10805                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10806                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10807                     size - wfex.cbSize);
10808                 gst_caps_set_simple (stream->caps,
10809                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10810                 gst_buffer_unref (buf);
10811               } else {
10812                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10813               }
10814
10815               if (codec_name) {
10816                 g_free (codec);
10817                 codec = g_strdup (codec_name);
10818               }
10819               break;
10820             }
10821             default:
10822               break;
10823           }
10824           len -= size + 8;
10825           wfex_data += size + 8;
10826         }
10827         break;
10828       }
10829       case FOURCC_opus:
10830       {
10831         GNode *opus;
10832         const guint8 *opus_data;
10833         guint8 *channel_mapping = NULL;
10834         guint32 rate;
10835         guint8 channels;
10836         guint8 channel_mapping_family;
10837         guint8 stream_count;
10838         guint8 coupled_count;
10839         guint8 i;
10840
10841         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10842         opus_data = opus->data;
10843
10844         channels = GST_READ_UINT8 (opus_data + 45);
10845         rate = GST_READ_UINT32_LE (opus_data + 48);
10846         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10847         stream_count = GST_READ_UINT8 (opus_data + 55);
10848         coupled_count = GST_READ_UINT8 (opus_data + 56);
10849
10850         if (channels > 0) {
10851           channel_mapping = g_malloc (channels * sizeof (guint8));
10852           for (i = 0; i < channels; i++)
10853             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10854         }
10855
10856         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10857             channel_mapping_family, stream_count, coupled_count,
10858             channel_mapping);
10859         break;
10860       }
10861       default:
10862         break;
10863     }
10864
10865     if (codec) {
10866       GstStructure *s;
10867       gint bitrate = 0;
10868
10869       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10870           GST_TAG_AUDIO_CODEC, codec, NULL);
10871       g_free (codec);
10872       codec = NULL;
10873
10874       /* some bitrate info may have ended up in caps */
10875       s = gst_caps_get_structure (stream->caps, 0);
10876       gst_structure_get_int (s, "bitrate", &bitrate);
10877       if (bitrate > 0)
10878         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10879             GST_TAG_BITRATE, bitrate, NULL);
10880     }
10881
10882     if (stream->protected && fourcc == FOURCC_mp4a)
10883       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10884     else
10885       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10886
10887     wave = NULL;
10888     esds = NULL;
10889     if (mp4a) {
10890       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10891       if (wave)
10892         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10893       if (!esds)
10894         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10895     }
10896
10897
10898     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10899        16 bits is a byte-swapped wave-style codec identifier,
10900        and we can find a WAVE header internally to a 'wave' atom here.
10901        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10902        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10903        is big-endian).
10904      */
10905     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10906       if (len < offset + 20) {
10907         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10908       } else {
10909         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10910         const guint8 *data = stsd_data + offset + 16;
10911         GNode *wavenode;
10912         GNode *waveheadernode;
10913
10914         wavenode = g_node_new ((guint8 *) data);
10915         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10916           const guint8 *waveheader;
10917           guint32 headerlen;
10918
10919           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10920           if (waveheadernode) {
10921             waveheader = (const guint8 *) waveheadernode->data;
10922             headerlen = QT_UINT32 (waveheader);
10923
10924             if (headerlen > 8) {
10925               gst_riff_strf_auds *header = NULL;
10926               GstBuffer *headerbuf;
10927               GstBuffer *extra;
10928
10929               waveheader += 8;
10930               headerlen -= 8;
10931
10932               headerbuf = gst_buffer_new_and_alloc (headerlen);
10933               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10934
10935               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10936                       headerbuf, &header, &extra)) {
10937                 gst_caps_unref (stream->caps);
10938                 /* FIXME: Need to do something with the channel reorder map */
10939                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10940                     header, extra, NULL, NULL, NULL);
10941
10942                 if (extra)
10943                   gst_buffer_unref (extra);
10944                 g_free (header);
10945               }
10946             }
10947           } else
10948             GST_DEBUG ("Didn't find waveheadernode for this codec");
10949         }
10950         g_node_destroy (wavenode);
10951       }
10952     } else if (esds) {
10953       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10954     } else {
10955       switch (fourcc) {
10956 #if 0
10957           /* FIXME: what is in the chunk? */
10958         case FOURCC_QDMC:
10959         {
10960           gint len = QT_UINT32 (stsd_data);
10961
10962           /* seems to be always = 116 = 0x74 */
10963           break;
10964         }
10965 #endif
10966         case FOURCC_QDM2:
10967         {
10968           gint len = QT_UINT32 (stsd_data);
10969
10970           if (len > 0x4C) {
10971             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10972
10973             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10974             gst_caps_set_simple (stream->caps,
10975                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10976             gst_buffer_unref (buf);
10977           }
10978           gst_caps_set_simple (stream->caps,
10979               "samplesize", G_TYPE_INT, samplesize, NULL);
10980           break;
10981         }
10982         case FOURCC_alac:
10983         {
10984           GNode *alac, *wave = NULL;
10985
10986           /* apparently, m4a has this atom appended directly in the stsd entry,
10987            * while mov has it in a wave atom */
10988           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10989           if (alac) {
10990             /* alac now refers to stsd entry atom */
10991             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10992             if (wave)
10993               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10994             else
10995               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10996           }
10997           if (alac) {
10998             const guint8 *alac_data = alac->data;
10999             gint len = QT_UINT32 (alac->data);
11000             GstBuffer *buf;
11001
11002             if (len < 36) {
11003               GST_DEBUG_OBJECT (qtdemux,
11004                   "discarding alac atom with unexpected len %d", len);
11005             } else {
11006               /* codec-data contains alac atom size and prefix,
11007                * ffmpeg likes it that way, not quite gst-ish though ...*/
11008               buf = gst_buffer_new_and_alloc (len);
11009               gst_buffer_fill (buf, 0, alac->data, len);
11010               gst_caps_set_simple (stream->caps,
11011                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11012               gst_buffer_unref (buf);
11013
11014               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
11015               stream->n_channels = QT_UINT8 (alac_data + 21);
11016               stream->rate = QT_UINT32 (alac_data + 32);
11017             }
11018           }
11019           gst_caps_set_simple (stream->caps,
11020               "samplesize", G_TYPE_INT, samplesize, NULL);
11021           break;
11022         }
11023         case FOURCC_fLaC:
11024         {
11025           /* The codingname of the sample entry is 'fLaC' */
11026           GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11027
11028           if (flac) {
11029             /* The 'dfLa' box is added to the sample entry to convey
11030                initializing information for the decoder. */
11031             const GNode *dfla =
11032                 qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11033
11034             if (dfla) {
11035               const guint32 len = QT_UINT32 (dfla->data);
11036
11037               /* Must contain at least dfLa box header (12),
11038                * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11039               if (len < 50) {
11040                 GST_DEBUG_OBJECT (qtdemux,
11041                     "discarding dfla atom with unexpected len %d", len);
11042               } else {
11043                 /* skip dfLa header to get the METADATA_BLOCKs */
11044                 const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11045                 const guint32 metadata_blocks_len = len - 12;
11046
11047                 gchar *stream_marker = g_strdup ("fLaC");
11048                 GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11049                     strlen (stream_marker));
11050
11051                 guint32 index = 0;
11052                 guint32 remainder = 0;
11053                 guint32 block_size = 0;
11054                 gboolean is_last = FALSE;
11055
11056                 GValue array = G_VALUE_INIT;
11057                 GValue value = G_VALUE_INIT;
11058
11059                 g_value_init (&array, GST_TYPE_ARRAY);
11060                 g_value_init (&value, GST_TYPE_BUFFER);
11061
11062                 gst_value_set_buffer (&value, block);
11063                 gst_value_array_append_value (&array, &value);
11064                 g_value_reset (&value);
11065
11066                 gst_buffer_unref (block);
11067
11068                 /* check there's at least one METADATA_BLOCK_HEADER's worth
11069                  * of data, and we haven't already finished parsing */
11070                 while (!is_last && ((index + 3) < metadata_blocks_len)) {
11071                   remainder = metadata_blocks_len - index;
11072
11073                   /* add the METADATA_BLOCK_HEADER size to the signalled size */
11074                   block_size = 4 +
11075                       (metadata_blocks[index + 1] << 16) +
11076                       (metadata_blocks[index + 2] << 8) +
11077                       metadata_blocks[index + 3];
11078
11079                   /* be careful not to read off end of box */
11080                   if (block_size > remainder) {
11081                     break;
11082                   }
11083
11084                   is_last = metadata_blocks[index] >> 7;
11085
11086                   block = gst_buffer_new_and_alloc (block_size);
11087
11088                   gst_buffer_fill (block, 0, &metadata_blocks[index],
11089                       block_size);
11090
11091                   gst_value_set_buffer (&value, block);
11092                   gst_value_array_append_value (&array, &value);
11093                   g_value_reset (&value);
11094
11095                   gst_buffer_unref (block);
11096
11097                   index += block_size;
11098                 }
11099
11100                 /* only append the metadata if we successfully read all of it */
11101                 if (is_last) {
11102                   gst_structure_set_value (gst_caps_get_structure (stream->caps,
11103                           0), "streamheader", &array);
11104                 } else {
11105                   GST_WARNING_OBJECT (qtdemux,
11106                       "discarding all METADATA_BLOCKs due to invalid "
11107                       "block_size %d at idx %d, rem %d", block_size, index,
11108                       remainder);
11109                 }
11110
11111                 g_value_unset (&value);
11112                 g_value_unset (&array);
11113
11114                 /* The sample rate obtained from the stsd may not be accurate
11115                  * since it cannot represent rates greater than 65535Hz, so
11116                  * override that value with the sample rate from the
11117                  * METADATA_BLOCK_STREAMINFO block */
11118                 stream->rate =
11119                     (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11120               }
11121             }
11122           }
11123           break;
11124         }
11125         case FOURCC_sawb:
11126           /* Fallthrough! */
11127           amrwb = TRUE;
11128         case FOURCC_samr:
11129         {
11130           gint len = QT_UINT32 (stsd_data);
11131
11132           if (len > 0x34) {
11133             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
11134             guint bitrate;
11135
11136             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
11137
11138             /* If we have enough data, let's try to get the 'damr' atom. See
11139              * the 3GPP container spec (26.244) for more details. */
11140             if ((len - 0x34) > 8 &&
11141                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11142               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11143                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11144             }
11145
11146             gst_caps_set_simple (stream->caps,
11147                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11148             gst_buffer_unref (buf);
11149           }
11150           break;
11151         }
11152         case FOURCC_mp4a:
11153         {
11154           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11155           gint len = QT_UINT32 (stsd_data);
11156
11157           if (len >= 50) {
11158             guint16 sound_version = QT_UINT16 (stsd_data + 32);
11159
11160             if (sound_version == 1) {
11161               guint16 channels = QT_UINT16 (stsd_data + 40);
11162               guint32 time_scale = QT_UINT32 (stsd_data + 46);
11163               guint8 codec_data[2];
11164               GstBuffer *buf;
11165               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11166
11167               gint sample_rate_index =
11168                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11169
11170               /* build AAC codec data */
11171               codec_data[0] = profile << 3;
11172               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11173               codec_data[1] = (sample_rate_index & 0x01) << 7;
11174               codec_data[1] |= (channels & 0xF) << 3;
11175
11176               buf = gst_buffer_new_and_alloc (2);
11177               gst_buffer_fill (buf, 0, codec_data, 2);
11178               gst_caps_set_simple (stream->caps,
11179                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11180               gst_buffer_unref (buf);
11181             }
11182           }
11183           break;
11184         }
11185         default:
11186           GST_INFO_OBJECT (qtdemux,
11187               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11188           break;
11189       }
11190     }
11191     GST_INFO_OBJECT (qtdemux,
11192         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11193         GST_FOURCC_ARGS (fourcc), stream->caps);
11194
11195   } else if (stream->subtype == FOURCC_strm) {
11196     if (fourcc == FOURCC_rtsp) {
11197       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11198     } else {
11199       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11200           GST_FOURCC_ARGS (fourcc));
11201       goto unknown_stream;
11202     }
11203     stream->sampled = TRUE;
11204   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11205       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11206
11207     stream->sampled = TRUE;
11208     stream->sparse = TRUE;
11209
11210     stream->caps =
11211         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
11212     if (codec) {
11213       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11214           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11215       g_free (codec);
11216       codec = NULL;
11217     }
11218
11219     /* hunt for sort-of codec data */
11220     switch (fourcc) {
11221       case FOURCC_mp4s:
11222       {
11223         GNode *mp4s = NULL;
11224         GNode *esds = NULL;
11225
11226         /* look for palette in a stsd->mp4s->esds sub-atom */
11227         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11228         if (mp4s)
11229           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11230         if (esds == NULL) {
11231           /* Invalid STSD */
11232           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11233           break;
11234         }
11235
11236         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
11237         break;
11238       }
11239       default:
11240         GST_INFO_OBJECT (qtdemux,
11241             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11242         break;
11243     }
11244     GST_INFO_OBJECT (qtdemux,
11245         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11246         GST_FOURCC_ARGS (fourcc), stream->caps);
11247   } else {
11248     /* everything in 1 sample */
11249     stream->sampled = TRUE;
11250
11251     stream->caps =
11252         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
11253
11254     if (stream->caps == NULL)
11255       goto unknown_stream;
11256
11257     if (codec) {
11258       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11259           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11260       g_free (codec);
11261       codec = NULL;
11262     }
11263   }
11264
11265   /* promote to sampled format */
11266   if (stream->fourcc == FOURCC_samr) {
11267     /* force mono 8000 Hz for AMR */
11268     stream->sampled = TRUE;
11269     stream->n_channels = 1;
11270     stream->rate = 8000;
11271   } else if (stream->fourcc == FOURCC_sawb) {
11272     /* force mono 16000 Hz for AMR-WB */
11273     stream->sampled = TRUE;
11274     stream->n_channels = 1;
11275     stream->rate = 16000;
11276   } else if (stream->fourcc == FOURCC_mp4a) {
11277     stream->sampled = TRUE;
11278   }
11279
11280   /* collect sample information */
11281   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11282     goto samples_failed;
11283
11284   if (qtdemux->fragmented) {
11285     guint64 offset;
11286
11287     /* need all moov samples as basis; probably not many if any at all */
11288     /* prevent moof parsing taking of at this time */
11289     offset = qtdemux->moof_offset;
11290     qtdemux->moof_offset = 0;
11291     if (stream->n_samples &&
11292         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11293       qtdemux->moof_offset = offset;
11294       goto samples_failed;
11295     }
11296     qtdemux->moof_offset = 0;
11297     /* movie duration more reliable in this case (e.g. mehd) */
11298     if (qtdemux->segment.duration &&
11299         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11300       stream->duration =
11301           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11302   }
11303
11304   /* configure segments */
11305   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11306     goto segments_failed;
11307
11308   /* add some language tag, if useful */
11309   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11310       strcmp (stream->lang_id, "und")) {
11311     const gchar *lang_code;
11312
11313     /* convert ISO 639-2 code to ISO 639-1 */
11314     lang_code = gst_tag_get_language_code (stream->lang_id);
11315     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11316         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11317   }
11318
11319   /* Check for UDTA tags */
11320   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11321     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
11322   }
11323
11324   /* now we are ready to add the stream */
11325   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11326     goto too_many_streams;
11327
11328   if (!qtdemux->got_moov) {
11329     qtdemux->streams[qtdemux->n_streams] = stream;
11330     qtdemux->n_streams++;
11331     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11332   }
11333
11334   return TRUE;
11335
11336 /* ERRORS */
11337 skip_track:
11338   {
11339     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11340     if (new_stream)
11341       gst_qtdemux_stream_free (qtdemux, stream);
11342     return TRUE;
11343   }
11344 corrupt_file:
11345   {
11346     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11347         (_("This file is corrupt and cannot be played.")), (NULL));
11348     if (new_stream)
11349       gst_qtdemux_stream_free (qtdemux, stream);
11350     return FALSE;
11351   }
11352 error_encrypted:
11353   {
11354     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11355     if (new_stream)
11356       gst_qtdemux_stream_free (qtdemux, stream);
11357     return FALSE;
11358   }
11359 samples_failed:
11360 segments_failed:
11361   {
11362     /* we posted an error already */
11363     /* free stbl sub-atoms */
11364     gst_qtdemux_stbl_free (stream);
11365     if (new_stream)
11366       gst_qtdemux_stream_free (qtdemux, stream);
11367     return FALSE;
11368   }
11369 existing_stream:
11370   {
11371     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11372         track_id);
11373     if (new_stream)
11374       gst_qtdemux_stream_free (qtdemux, stream);
11375     return TRUE;
11376   }
11377 unknown_stream:
11378   {
11379     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11380         GST_FOURCC_ARGS (stream->subtype));
11381     if (new_stream)
11382       gst_qtdemux_stream_free (qtdemux, stream);
11383     return TRUE;
11384   }
11385 too_many_streams:
11386   {
11387     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11388         (_("This file contains too many streams. Only playing first %d"),
11389             GST_QTDEMUX_MAX_STREAMS), (NULL));
11390     return TRUE;
11391   }
11392 }
11393
11394 /* If we can estimate the overall bitrate, and don't have information about the
11395  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11396  * the overall bitrate minus the sum of the bitrates of all other streams. This
11397  * should be useful for the common case where we have one audio and one video
11398  * stream and can estimate the bitrate of one, but not the other. */
11399 static void
11400 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11401 {
11402   QtDemuxStream *stream = NULL;
11403   gint64 size, sys_bitrate, sum_bitrate = 0;
11404   GstClockTime duration;
11405   gint i;
11406   guint bitrate;
11407
11408   if (qtdemux->fragmented)
11409     return;
11410
11411   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11412
11413   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11414       || size <= 0) {
11415     GST_DEBUG_OBJECT (qtdemux,
11416         "Size in bytes of the stream not known - bailing");
11417     return;
11418   }
11419
11420   /* Subtract the header size */
11421   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11422       size, qtdemux->header_size);
11423
11424   if (size < qtdemux->header_size)
11425     return;
11426
11427   size = size - qtdemux->header_size;
11428
11429   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11430     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11431     return;
11432   }
11433
11434   for (i = 0; i < qtdemux->n_streams; i++) {
11435     switch (qtdemux->streams[i]->subtype) {
11436       case FOURCC_soun:
11437       case FOURCC_vide:
11438         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11439             qtdemux->streams[i]->caps);
11440         /* retrieve bitrate, prefer avg then max */
11441         bitrate = 0;
11442         if (qtdemux->streams[i]->pending_tags) {
11443           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11444               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11445           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11446           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11447               GST_TAG_NOMINAL_BITRATE, &bitrate);
11448           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11449           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11450               GST_TAG_BITRATE, &bitrate);
11451           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11452         }
11453         if (bitrate)
11454           sum_bitrate += bitrate;
11455         else {
11456           if (stream) {
11457             GST_DEBUG_OBJECT (qtdemux,
11458                 ">1 stream with unknown bitrate - bailing");
11459             return;
11460           } else
11461             stream = qtdemux->streams[i];
11462         }
11463
11464       default:
11465         /* For other subtypes, we assume no significant impact on bitrate */
11466         break;
11467     }
11468   }
11469
11470   if (!stream) {
11471     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11472     return;
11473   }
11474
11475   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11476
11477   if (sys_bitrate < sum_bitrate) {
11478     /* This can happen, since sum_bitrate might be derived from maximum
11479      * bitrates and not average bitrates */
11480     GST_DEBUG_OBJECT (qtdemux,
11481         "System bitrate less than sum bitrate - bailing");
11482     return;
11483   }
11484
11485   bitrate = sys_bitrate - sum_bitrate;
11486   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11487       ", Stream bitrate = %u", sys_bitrate, bitrate);
11488
11489   if (!stream->pending_tags)
11490     stream->pending_tags = gst_tag_list_new_empty ();
11491
11492   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11493       GST_TAG_BITRATE, bitrate, NULL);
11494 }
11495
11496 static GstFlowReturn
11497 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11498 {
11499   gint i;
11500   GstFlowReturn ret = GST_FLOW_OK;
11501
11502   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11503
11504   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11505     QtDemuxStream *stream = qtdemux->streams[i];
11506     guint32 sample_num = 0;
11507
11508     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11509         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11510
11511     if (qtdemux->fragmented) {
11512       /* need all moov samples first */
11513       GST_OBJECT_LOCK (qtdemux);
11514       while (stream->n_samples == 0)
11515         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11516           break;
11517       GST_OBJECT_UNLOCK (qtdemux);
11518     } else {
11519       /* discard any stray moof */
11520       qtdemux->moof_offset = 0;
11521     }
11522
11523     /* prepare braking */
11524     if (ret != GST_FLOW_ERROR)
11525       ret = GST_FLOW_OK;
11526
11527     /* in pull mode, we should have parsed some sample info by now;
11528      * and quite some code will not handle no samples.
11529      * in push mode, we'll just have to deal with it */
11530     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11531       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11532       gst_qtdemux_remove_stream (qtdemux, i);
11533       i--;
11534       continue;
11535     }
11536
11537     /* parse the initial sample for use in setting the frame rate cap */
11538     while (sample_num == 0 && sample_num < stream->n_samples) {
11539       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11540         break;
11541       ++sample_num;
11542     }
11543     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11544       stream->first_duration = stream->samples[0].duration;
11545       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11546           stream->track_id, stream->first_duration);
11547     }
11548   }
11549
11550   return ret;
11551 }
11552
11553 static GstFlowReturn
11554 qtdemux_expose_streams (GstQTDemux * qtdemux)
11555 {
11556   gint i;
11557   GSList *oldpads = NULL;
11558   GSList *iter;
11559
11560   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11561
11562   for (i = 0; i < qtdemux->n_streams; i++) {
11563     QtDemuxStream *stream = qtdemux->streams[i];
11564     GstPad *oldpad = stream->pad;
11565     GstTagList *list;
11566
11567     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11568         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11569
11570     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11571         stream->track_id == qtdemux->chapters_track_id) {
11572       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11573          so that it doesn't look like a subtitle track */
11574       gst_qtdemux_remove_stream (qtdemux, i);
11575       i--;
11576       continue;
11577     }
11578
11579     /* now we have all info and can expose */
11580     list = stream->pending_tags;
11581     stream->pending_tags = NULL;
11582     if (oldpad)
11583       oldpads = g_slist_prepend (oldpads, oldpad);
11584     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11585       return GST_FLOW_ERROR;
11586   }
11587
11588   gst_qtdemux_guess_bitrate (qtdemux);
11589
11590   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11591
11592   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11593     GstPad *oldpad = iter->data;
11594     GstEvent *event;
11595
11596     event = gst_event_new_eos ();
11597     if (qtdemux->segment_seqnum)
11598       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11599
11600     gst_pad_push_event (oldpad, event);
11601     gst_pad_set_active (oldpad, FALSE);
11602     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11603     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11604     gst_object_unref (oldpad);
11605   }
11606
11607   /* check if we should post a redirect in case there is a single trak
11608    * and it is a redirecting trak */
11609   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11610     GstMessage *m;
11611
11612     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11613         "an external content");
11614     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11615         gst_structure_new ("redirect",
11616             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11617             NULL));
11618     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11619     qtdemux->posted_redirect = TRUE;
11620   }
11621
11622   for (i = 0; i < qtdemux->n_streams; i++) {
11623     QtDemuxStream *stream = qtdemux->streams[i];
11624
11625     qtdemux_do_allocation (qtdemux, stream);
11626   }
11627
11628   qtdemux->exposed = TRUE;
11629   return GST_FLOW_OK;
11630 }
11631
11632 /* check if major or compatible brand is 3GP */
11633 static inline gboolean
11634 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11635 {
11636   if (major) {
11637     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11638         FOURCC_3g__);
11639   } else if (qtdemux->comp_brands != NULL) {
11640     GstMapInfo map;
11641     guint8 *data;
11642     gsize size;
11643     gboolean res = FALSE;
11644
11645     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11646     data = map.data;
11647     size = map.size;
11648     while (size >= 4) {
11649       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11650           FOURCC_3g__);
11651       data += 4;
11652       size -= 4;
11653     }
11654     gst_buffer_unmap (qtdemux->comp_brands, &map);
11655     return res;
11656   } else {
11657     return FALSE;
11658   }
11659 }
11660
11661 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11662 static inline gboolean
11663 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11664 {
11665   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11666       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11667       || fourcc == FOURCC_albm;
11668 }
11669
11670 static void
11671 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11672     const char *tag, const char *dummy, GNode * node)
11673 {
11674   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11675   int offset;
11676   char *name;
11677   gchar *data;
11678   gdouble longitude, latitude, altitude;
11679   gint len;
11680
11681   len = QT_UINT32 (node->data);
11682   if (len <= 14)
11683     goto short_read;
11684
11685   data = node->data;
11686   offset = 14;
11687
11688   /* TODO: language code skipped */
11689
11690   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11691
11692   if (!name) {
11693     /* do not alarm in trivial case, but bail out otherwise */
11694     if (*(data + offset) != 0) {
11695       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11696           "giving up", tag);
11697     }
11698   } else {
11699     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11700         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11701     offset += strlen (name);
11702     g_free (name);
11703   }
11704
11705   if (len < offset + 2 + 4 + 4 + 4)
11706     goto short_read;
11707
11708   /* +1 +1 = skip null-terminator and location role byte */
11709   offset += 1 + 1;
11710   /* table in spec says unsigned, semantics say negative has meaning ... */
11711   longitude = QT_SFP32 (data + offset);
11712
11713   offset += 4;
11714   latitude = QT_SFP32 (data + offset);
11715
11716   offset += 4;
11717   altitude = QT_SFP32 (data + offset);
11718
11719   /* one invalid means all are invalid */
11720   if (longitude >= -180.0 && longitude <= 180.0 &&
11721       latitude >= -90.0 && latitude <= 90.0) {
11722     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11723         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11724         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11725         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11726   }
11727
11728   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11729
11730   return;
11731
11732   /* ERRORS */
11733 short_read:
11734   {
11735     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11736     return;
11737   }
11738 }
11739
11740
11741 static void
11742 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11743     const char *tag, const char *dummy, GNode * node)
11744 {
11745   guint16 y;
11746   GDate *date;
11747   gint len;
11748
11749   len = QT_UINT32 (node->data);
11750   if (len < 14)
11751     return;
11752
11753   y = QT_UINT16 ((guint8 *) node->data + 12);
11754   if (y == 0) {
11755     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11756     return;
11757   }
11758   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11759
11760   date = g_date_new_dmy (1, 1, y);
11761   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11762   g_date_free (date);
11763 }
11764
11765 static void
11766 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11767     const char *tag, const char *dummy, GNode * node)
11768 {
11769   int offset;
11770   char *tag_str = NULL;
11771   guint8 *entity;
11772   guint16 table;
11773   gint len;
11774
11775   len = QT_UINT32 (node->data);
11776   if (len <= 20)
11777     goto short_read;
11778
11779   offset = 12;
11780   entity = (guint8 *) node->data + offset;
11781   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11782     GST_DEBUG_OBJECT (qtdemux,
11783         "classification info: %c%c%c%c invalid classification entity",
11784         entity[0], entity[1], entity[2], entity[3]);
11785     return;
11786   }
11787
11788   offset += 4;
11789   table = QT_UINT16 ((guint8 *) node->data + offset);
11790
11791   /* Language code skipped */
11792
11793   offset += 4;
11794
11795   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11796    * XXXX: classification entity, fixed length 4 chars.
11797    * Y[YYYY]: classification table, max 5 chars.
11798    */
11799   tag_str = g_strdup_printf ("----://%u/%s",
11800       table, (char *) node->data + offset);
11801
11802   /* memcpy To be sure we're preserving byte order */
11803   memcpy (tag_str, entity, 4);
11804   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11805
11806   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11807
11808   g_free (tag_str);
11809
11810   return;
11811
11812   /* ERRORS */
11813 short_read:
11814   {
11815     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11816     return;
11817   }
11818 }
11819
11820 static gboolean
11821 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11822     const char *tag, const char *dummy, GNode * node)
11823 {
11824   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11825   GNode *data;
11826   char *s;
11827   int len;
11828   guint32 type;
11829   int offset;
11830   gboolean ret = TRUE;
11831   const gchar *charset = NULL;
11832
11833   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11834   if (data) {
11835     len = QT_UINT32 (data->data);
11836     type = QT_UINT32 ((guint8 *) data->data + 8);
11837     if (type == 0x00000001 && len > 16) {
11838       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11839           env_vars);
11840       if (s) {
11841         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11842         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11843         g_free (s);
11844       } else {
11845         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11846       }
11847     }
11848   } else {
11849     len = QT_UINT32 (node->data);
11850     type = QT_UINT32 ((guint8 *) node->data + 4);
11851     if ((type >> 24) == 0xa9 && len > 8 + 4) {
11852       gint str_len;
11853       gint lang_code;
11854
11855       /* Type starts with the (C) symbol, so the next data is a list
11856        * of (string size(16), language code(16), string) */
11857
11858       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11859       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11860
11861       /* the string + fourcc + size + 2 16bit fields,
11862        * means that there are more tags in this atom */
11863       if (len > str_len + 8 + 4) {
11864         /* TODO how to represent the same tag in different languages? */
11865         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11866             "text alternatives, reading only first one");
11867       }
11868
11869       offset = 12;
11870       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
11871       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11872
11873       if (lang_code < 0x800) {  /* MAC encoded string */
11874         charset = "mac";
11875       }
11876     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11877             QT_FOURCC ((guint8 *) node->data + 4))) {
11878       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11879
11880       /* we go for 3GP style encoding if major brands claims so,
11881        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11882       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11883           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11884               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11885         offset = 14;
11886         /* 16-bit Language code is ignored here as well */
11887         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11888       } else {
11889         goto normal;
11890       }
11891     } else {
11892     normal:
11893       offset = 8;
11894       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11895       ret = FALSE;              /* may have to fallback */
11896     }
11897     if (charset) {
11898       GError *err = NULL;
11899
11900       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11901           charset, NULL, NULL, &err);
11902       if (err) {
11903         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11904             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11905             err->message);
11906         g_error_free (err);
11907       }
11908     } else {
11909       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11910           len - offset, env_vars);
11911     }
11912     if (s) {
11913       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11914       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11915       g_free (s);
11916       ret = TRUE;
11917     } else {
11918       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11919     }
11920   }
11921   return ret;
11922 }
11923
11924 static void
11925 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11926     const char *tag, const char *dummy, GNode * node)
11927 {
11928   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11929 }
11930
11931 static void
11932 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11933     const char *tag, const char *dummy, GNode * node)
11934 {
11935   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11936   guint8 *data;
11937   char *s, *t, *k = NULL;
11938   int len;
11939   int offset;
11940   int count;
11941
11942   /* first try normal string tag if major brand not 3GP */
11943   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11944     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11945       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11946        * let's try it 3gpp way after minor safety check */
11947       data = node->data;
11948       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11949         return;
11950     } else
11951       return;
11952   }
11953
11954   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11955
11956   data = node->data;
11957
11958   len = QT_UINT32 (data);
11959   if (len < 15)
11960     goto short_read;
11961
11962   count = QT_UINT8 (data + 14);
11963   offset = 15;
11964   for (; count; count--) {
11965     gint slen;
11966
11967     if (offset + 1 > len)
11968       goto short_read;
11969     slen = QT_UINT8 (data + offset);
11970     offset += 1;
11971     if (offset + slen > len)
11972       goto short_read;
11973     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11974         slen, env_vars);
11975     if (s) {
11976       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11977       if (k) {
11978         t = g_strjoin (",", k, s, NULL);
11979         g_free (s);
11980         g_free (k);
11981         k = t;
11982       } else {
11983         k = s;
11984       }
11985     } else {
11986       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11987     }
11988     offset += slen;
11989   }
11990
11991 done:
11992   if (k) {
11993     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11994     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11995   }
11996   g_free (k);
11997
11998   return;
11999
12000   /* ERRORS */
12001 short_read:
12002   {
12003     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12004     goto done;
12005   }
12006 }
12007
12008 static void
12009 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12010     const char *tag1, const char *tag2, GNode * node)
12011 {
12012   GNode *data;
12013   int len;
12014   int type;
12015   int n1, n2;
12016
12017   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12018   if (data) {
12019     len = QT_UINT32 (data->data);
12020     type = QT_UINT32 ((guint8 *) data->data + 8);
12021     if (type == 0x00000000 && len >= 22) {
12022       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12023       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12024       if (n1 > 0) {
12025         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12026         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12027       }
12028       if (n2 > 0) {
12029         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12030         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12031       }
12032     }
12033   }
12034 }
12035
12036 static void
12037 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12038     const char *tag1, const char *dummy, GNode * node)
12039 {
12040   GNode *data;
12041   int len;
12042   int type;
12043   int n1;
12044
12045   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12046   if (data) {
12047     len = QT_UINT32 (data->data);
12048     type = QT_UINT32 ((guint8 *) data->data + 8);
12049     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12050     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12051     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12052       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12053       if (n1) {
12054         /* do not add bpm=0 */
12055         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12056         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12057             NULL);
12058       }
12059     }
12060   }
12061 }
12062
12063 static void
12064 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12065     const char *tag1, const char *dummy, GNode * node)
12066 {
12067   GNode *data;
12068   int len;
12069   int type;
12070   guint32 num;
12071
12072   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12073   if (data) {
12074     len = QT_UINT32 (data->data);
12075     type = QT_UINT32 ((guint8 *) data->data + 8);
12076     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12077     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12078     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12079       num = QT_UINT32 ((guint8 *) data->data + 16);
12080       if (num) {
12081         /* do not add num=0 */
12082         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12083         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12084       }
12085     }
12086   }
12087 }
12088
12089 static void
12090 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12091     const char *tag1, const char *dummy, GNode * node)
12092 {
12093   GNode *data;
12094   int len;
12095   int type;
12096   GstSample *sample;
12097
12098   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12099   if (data) {
12100     len = QT_UINT32 (data->data);
12101     type = QT_UINT32 ((guint8 *) data->data + 8);
12102     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12103     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12104       if ((sample =
12105               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12106                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
12107         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12108         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12109         gst_sample_unref (sample);
12110       }
12111     }
12112   }
12113 }
12114
12115 static void
12116 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12117     const char *tag, const char *dummy, GNode * node)
12118 {
12119   GNode *data;
12120   char *s;
12121   int len;
12122   int type;
12123
12124   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12125   if (data) {
12126     len = QT_UINT32 (data->data);
12127     type = QT_UINT32 ((guint8 *) data->data + 8);
12128     if (type == 0x00000001 && len > 16) {
12129       guint y, m = 1, d = 1;
12130       gint ret;
12131
12132       s = g_strndup ((char *) data->data + 16, len - 16);
12133       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12134       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12135       if (ret >= 1 && y > 1500 && y < 3000) {
12136         GDate *date;
12137
12138         date = g_date_new_dmy (d, m, y);
12139         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12140         g_date_free (date);
12141       } else {
12142         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12143       }
12144       g_free (s);
12145     }
12146   }
12147 }
12148
12149 static void
12150 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12151     const char *tag, const char *dummy, GNode * node)
12152 {
12153   GNode *data;
12154
12155   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12156
12157   /* re-route to normal string tag if major brand says so
12158    * or no data atom and compatible brand suggests so */
12159   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12160       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12161     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12162     return;
12163   }
12164
12165   if (data) {
12166     guint len, type, n;
12167
12168     len = QT_UINT32 (data->data);
12169     type = QT_UINT32 ((guint8 *) data->data + 8);
12170     if (type == 0x00000000 && len >= 18) {
12171       n = QT_UINT16 ((guint8 *) data->data + 16);
12172       if (n > 0) {
12173         const gchar *genre;
12174
12175         genre = gst_tag_id3_genre_get (n - 1);
12176         if (genre != NULL) {
12177           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12178           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12179         }
12180       }
12181     }
12182   }
12183 }
12184
12185 static void
12186 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12187     const gchar * tag, guint8 * data, guint32 datasize)
12188 {
12189   gdouble value;
12190   gchar *datacopy;
12191
12192   /* make a copy to have \0 at the end */
12193   datacopy = g_strndup ((gchar *) data, datasize);
12194
12195   /* convert the str to double */
12196   if (sscanf (datacopy, "%lf", &value) == 1) {
12197     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12198     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12199   } else {
12200     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12201         datacopy);
12202   }
12203   g_free (datacopy);
12204 }
12205
12206
12207 static void
12208 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12209     const char *tag, const char *tag_bis, GNode * node)
12210 {
12211   GNode *mean;
12212   GNode *name;
12213   GNode *data;
12214   guint32 meansize;
12215   guint32 namesize;
12216   guint32 datatype;
12217   guint32 datasize;
12218   const gchar *meanstr;
12219   const gchar *namestr;
12220
12221   /* checking the whole ---- atom size for consistency */
12222   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12223     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12224     return;
12225   }
12226
12227   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12228   if (!mean) {
12229     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12230     return;
12231   }
12232
12233   meansize = QT_UINT32 (mean->data);
12234   if (meansize <= 12) {
12235     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12236     return;
12237   }
12238   meanstr = ((gchar *) mean->data) + 12;
12239   meansize -= 12;
12240
12241   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12242   if (!name) {
12243     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12244     return;
12245   }
12246
12247   namesize = QT_UINT32 (name->data);
12248   if (namesize <= 12) {
12249     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12250     return;
12251   }
12252   namestr = ((gchar *) name->data) + 12;
12253   namesize -= 12;
12254
12255   /*
12256    * Data atom is:
12257    * uint32 - size
12258    * uint32 - name
12259    * uint8  - version
12260    * uint24 - data type
12261    * uint32 - all 0
12262    * rest   - the data
12263    */
12264   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12265   if (!data) {
12266     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12267     return;
12268   }
12269   datasize = QT_UINT32 (data->data);
12270   if (datasize <= 16) {
12271     GST_WARNING_OBJECT (demux, "Data atom too small");
12272     return;
12273   }
12274   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12275
12276   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12277       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12278     static const struct
12279     {
12280       const gchar name[28];
12281       const gchar tag[28];
12282     } tags[] = {
12283       {
12284       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12285       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12286       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12287       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12288       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12289       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12290       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12291       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12292     };
12293     int i;
12294
12295     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12296       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12297         switch (gst_tag_get_type (tags[i].tag)) {
12298           case G_TYPE_DOUBLE:
12299             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12300                 ((guint8 *) data->data) + 16, datasize - 16);
12301             break;
12302           case G_TYPE_STRING:
12303             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12304             break;
12305           default:
12306             /* not reached */
12307             break;
12308         }
12309         break;
12310       }
12311     }
12312     if (i == G_N_ELEMENTS (tags))
12313       goto unknown_tag;
12314   } else {
12315     goto unknown_tag;
12316   }
12317
12318   return;
12319
12320 /* errors */
12321 unknown_tag:
12322 #ifndef GST_DISABLE_GST_DEBUG
12323   {
12324     gchar *namestr_dbg;
12325     gchar *meanstr_dbg;
12326
12327     meanstr_dbg = g_strndup (meanstr, meansize);
12328     namestr_dbg = g_strndup (namestr, namesize);
12329
12330     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12331         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12332
12333     g_free (namestr_dbg);
12334     g_free (meanstr_dbg);
12335   }
12336 #endif
12337   return;
12338 }
12339
12340 static void
12341 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12342     const char *tag_bis, GNode * node)
12343 {
12344   guint8 *data;
12345   GstBuffer *buf;
12346   guint len;
12347   GstTagList *id32_taglist = NULL;
12348
12349   GST_LOG_OBJECT (demux, "parsing ID32");
12350
12351   data = node->data;
12352   len = GST_READ_UINT32_BE (data);
12353
12354   /* need at least full box and language tag */
12355   if (len < 12 + 2)
12356     return;
12357
12358   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12359   gst_buffer_fill (buf, 0, data + 14, len - 14);
12360
12361   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12362   if (id32_taglist) {
12363     GST_LOG_OBJECT (demux, "parsing ok");
12364     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12365     gst_tag_list_unref (id32_taglist);
12366   } else {
12367     GST_LOG_OBJECT (demux, "parsing failed");
12368   }
12369
12370   gst_buffer_unref (buf);
12371 }
12372
12373 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12374     const char *tag, const char *tag_bis, GNode * node);
12375
12376 /* unmapped tags
12377 FOURCC_pcst -> if media is a podcast -> bool
12378 FOURCC_cpil -> if media is part of a compilation -> bool
12379 FOURCC_pgap -> if media is part of a gapless context -> bool
12380 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12381 */
12382
12383 static const struct
12384 {
12385   guint32 fourcc;
12386   const gchar *gst_tag;
12387   const gchar *gst_tag_bis;
12388   const GstQTDemuxAddTagFunc func;
12389 } add_funcs[] = {
12390   {
12391   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12392   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12393   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12394   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12395   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12396   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12397   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12398   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12399   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12400   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12401   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12402   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12403   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12404   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12405   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12406   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12407   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12408   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12409   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12410   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12411   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12412   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12413   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12414         qtdemux_tag_add_num}, {
12415   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12416         qtdemux_tag_add_num}, {
12417   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12418   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12419   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12420   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
12421   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12422   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12423   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12424   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12425   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12426   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12427   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12428   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12429   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12430   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12431   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12432   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12433   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12434   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12435         qtdemux_tag_add_classification}, {
12436   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12437   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12438   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12439
12440     /* This is a special case, some tags are stored in this
12441      * 'reverse dns naming', according to:
12442      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12443      * bug #614471
12444      */
12445   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12446     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12447   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12448 };
12449
12450 struct _GstQtDemuxTagList
12451 {
12452   GstQTDemux *demux;
12453   GstTagList *taglist;
12454 };
12455 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12456
12457 static void
12458 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12459 {
12460   gint len;
12461   guint8 *data;
12462   GstBuffer *buf;
12463   gchar *media_type;
12464   const gchar *style;
12465   GstSample *sample;
12466   GstStructure *s;
12467   guint i;
12468   guint8 ndata[4];
12469   GstQTDemux *demux = qtdemuxtaglist->demux;
12470   GstTagList *taglist = qtdemuxtaglist->taglist;
12471
12472   data = node->data;
12473   len = QT_UINT32 (data);
12474   buf = gst_buffer_new_and_alloc (len);
12475   gst_buffer_fill (buf, 0, data, len);
12476
12477   /* heuristic to determine style of tag */
12478   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12479       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12480     style = "itunes";
12481   else if (demux->major_brand == FOURCC_qt__)
12482     style = "quicktime";
12483   /* fall back to assuming iso/3gp tag style */
12484   else
12485     style = "iso";
12486
12487   /* santize the name for the caps. */
12488   for (i = 0; i < 4; i++) {
12489     guint8 d = data[4 + i];
12490     if (g_ascii_isalnum (d))
12491       ndata[i] = g_ascii_tolower (d);
12492     else
12493       ndata[i] = '_';
12494   }
12495
12496   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12497       ndata[0], ndata[1], ndata[2], ndata[3]);
12498   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12499
12500   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12501   sample = gst_sample_new (buf, NULL, NULL, s);
12502   gst_buffer_unref (buf);
12503   g_free (media_type);
12504
12505   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12506       len, s);
12507
12508   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12509       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12510
12511   gst_sample_unref (sample);
12512 }
12513
12514 static void
12515 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12516 {
12517   GNode *meta;
12518   GNode *ilst;
12519   GNode *xmp_;
12520   GNode *node;
12521   gint i;
12522   GstQtDemuxTagList demuxtaglist;
12523
12524   demuxtaglist.demux = qtdemux;
12525   demuxtaglist.taglist = taglist;
12526
12527   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12528   if (meta != NULL) {
12529     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12530     if (ilst == NULL) {
12531       GST_LOG_OBJECT (qtdemux, "no ilst");
12532       return;
12533     }
12534   } else {
12535     ilst = udta;
12536     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12537   }
12538
12539   i = 0;
12540   while (i < G_N_ELEMENTS (add_funcs)) {
12541     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12542     if (node) {
12543       gint len;
12544
12545       len = QT_UINT32 (node->data);
12546       if (len < 12) {
12547         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12548             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12549       } else {
12550         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12551             add_funcs[i].gst_tag_bis, node);
12552       }
12553       g_node_destroy (node);
12554     } else {
12555       i++;
12556     }
12557   }
12558
12559   /* parsed nodes have been removed, pass along remainder as blob */
12560   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12561       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12562
12563   /* parse up XMP_ node if existing */
12564   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12565   if (xmp_ != NULL) {
12566     GstBuffer *buf;
12567     GstTagList *xmptaglist;
12568
12569     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12570         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12571     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12572     gst_buffer_unref (buf);
12573
12574     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12575   } else {
12576     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12577   }
12578 }
12579
12580 typedef struct
12581 {
12582   GstStructure *structure;      /* helper for sort function */
12583   gchar *location;
12584   guint min_req_bitrate;
12585   guint min_req_qt_version;
12586 } GstQtReference;
12587
12588 static gint
12589 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12590 {
12591   GstQtReference *ref_a = (GstQtReference *) a;
12592   GstQtReference *ref_b = (GstQtReference *) b;
12593
12594   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12595     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12596
12597   /* known bitrates go before unknown; higher bitrates go first */
12598   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12599 }
12600
12601 /* sort the redirects and post a message for the application.
12602  */
12603 static void
12604 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12605 {
12606   GstQtReference *best;
12607   GstStructure *s;
12608   GstMessage *msg;
12609   GValue list_val = { 0, };
12610   GList *l;
12611
12612   g_assert (references != NULL);
12613
12614   references = g_list_sort (references, qtdemux_redirects_sort_func);
12615
12616   best = (GstQtReference *) references->data;
12617
12618   g_value_init (&list_val, GST_TYPE_LIST);
12619
12620   for (l = references; l != NULL; l = l->next) {
12621     GstQtReference *ref = (GstQtReference *) l->data;
12622     GValue struct_val = { 0, };
12623
12624     ref->structure = gst_structure_new ("redirect",
12625         "new-location", G_TYPE_STRING, ref->location, NULL);
12626
12627     if (ref->min_req_bitrate > 0) {
12628       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12629           ref->min_req_bitrate, NULL);
12630     }
12631
12632     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12633     g_value_set_boxed (&struct_val, ref->structure);
12634     gst_value_list_append_value (&list_val, &struct_val);
12635     g_value_unset (&struct_val);
12636     /* don't free anything here yet, since we need best->structure below */
12637   }
12638
12639   g_assert (best != NULL);
12640   s = gst_structure_copy (best->structure);
12641
12642   if (g_list_length (references) > 1) {
12643     gst_structure_set_value (s, "locations", &list_val);
12644   }
12645
12646   g_value_unset (&list_val);
12647
12648   for (l = references; l != NULL; l = l->next) {
12649     GstQtReference *ref = (GstQtReference *) l->data;
12650
12651     gst_structure_free (ref->structure);
12652     g_free (ref->location);
12653     g_free (ref);
12654   }
12655   g_list_free (references);
12656
12657   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12658   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12659   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12660   qtdemux->posted_redirect = TRUE;
12661 }
12662
12663 /* look for redirect nodes, collect all redirect information and
12664  * process it.
12665  */
12666 static gboolean
12667 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12668 {
12669   GNode *rmra, *rmda, *rdrf;
12670
12671   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12672   if (rmra) {
12673     GList *redirects = NULL;
12674
12675     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12676     while (rmda) {
12677       GstQtReference ref = { NULL, NULL, 0, 0 };
12678       GNode *rmdr, *rmvc;
12679
12680       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12681         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12682         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12683             ref.min_req_bitrate);
12684       }
12685
12686       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12687         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12688         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12689
12690 #ifndef GST_DISABLE_GST_DEBUG
12691         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12692 #endif
12693         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12694
12695         GST_LOG_OBJECT (qtdemux,
12696             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12697             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12698             bitmask, check_type);
12699         if (package == FOURCC_qtim && check_type == 0) {
12700           ref.min_req_qt_version = version;
12701         }
12702       }
12703
12704       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12705       if (rdrf) {
12706         guint32 ref_type;
12707         guint8 *ref_data;
12708         guint ref_len;
12709
12710         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12711         if (ref_len > 20) {
12712           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12713           ref_data = (guint8 *) rdrf->data + 20;
12714           if (ref_type == FOURCC_alis) {
12715             guint record_len, record_version, fn_len;
12716
12717             if (ref_len > 70) {
12718               /* MacOSX alias record, google for alias-layout.txt */
12719               record_len = QT_UINT16 (ref_data + 4);
12720               record_version = QT_UINT16 (ref_data + 4 + 2);
12721               fn_len = QT_UINT8 (ref_data + 50);
12722               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12723                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12724               }
12725             } else {
12726               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12727                   ref_len);
12728             }
12729           } else if (ref_type == FOURCC_url_) {
12730             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12731           } else {
12732             GST_DEBUG_OBJECT (qtdemux,
12733                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12734                 GST_FOURCC_ARGS (ref_type));
12735           }
12736           if (ref.location != NULL) {
12737             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12738             redirects =
12739                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12740           } else {
12741             GST_WARNING_OBJECT (qtdemux,
12742                 "Failed to extract redirect location from rdrf atom");
12743           }
12744         } else {
12745           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12746         }
12747       }
12748
12749       /* look for others */
12750       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12751     }
12752
12753     if (redirects != NULL) {
12754       qtdemux_process_redirects (qtdemux, redirects);
12755     }
12756   }
12757   return TRUE;
12758 }
12759
12760 static GstTagList *
12761 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12762 {
12763   const gchar *fmt;
12764
12765   if (tags == NULL) {
12766     tags = gst_tag_list_new_empty ();
12767     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12768   }
12769
12770   if (qtdemux->major_brand == FOURCC_mjp2)
12771     fmt = "Motion JPEG 2000";
12772   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12773     fmt = "3GP";
12774   else if (qtdemux->major_brand == FOURCC_qt__)
12775     fmt = "Quicktime";
12776   else if (qtdemux->fragmented)
12777     fmt = "ISO fMP4";
12778   else
12779     fmt = "ISO MP4/M4A";
12780
12781   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12782       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12783
12784   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12785       fmt, NULL);
12786
12787   return tags;
12788 }
12789
12790 /* we have read the complete moov node now.
12791  * This function parses all of the relevant info, creates the traks and
12792  * prepares all data structures for playback
12793  */
12794 static gboolean
12795 qtdemux_parse_tree (GstQTDemux * qtdemux)
12796 {
12797   GNode *mvhd;
12798   GNode *trak;
12799   GNode *udta;
12800   GNode *mvex;
12801   GstClockTime duration;
12802   GNode *pssh;
12803   guint64 creation_time;
12804   GstDateTime *datetime = NULL;
12805   gint version;
12806
12807   /* make sure we have a usable taglist */
12808   if (!qtdemux->tag_list) {
12809     qtdemux->tag_list = gst_tag_list_new_empty ();
12810     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12811   } else {
12812     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12813   }
12814
12815   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12816   if (mvhd == NULL) {
12817     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12818     return qtdemux_parse_redirects (qtdemux);
12819   }
12820
12821   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12822   if (version == 1) {
12823     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12824     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12825     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12826   } else if (version == 0) {
12827     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12828     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12829     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12830   } else {
12831     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12832     return FALSE;
12833   }
12834
12835   /* Moving qt creation time (secs since 1904) to unix time */
12836   if (creation_time != 0) {
12837     /* Try to use epoch first as it should be faster and more commonly found */
12838     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12839       GTimeVal now;
12840
12841       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12842       /* some data cleansing sanity */
12843       g_get_current_time (&now);
12844       if (now.tv_sec + 24 * 3600 < creation_time) {
12845         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12846       } else {
12847         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12848       }
12849     } else {
12850       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12851       GDateTime *dt, *dt_local;
12852
12853       dt = g_date_time_add_seconds (base_dt, creation_time);
12854       dt_local = g_date_time_to_local (dt);
12855       datetime = gst_date_time_new_from_g_date_time (dt_local);
12856
12857       g_date_time_unref (base_dt);
12858       g_date_time_unref (dt);
12859     }
12860   }
12861   if (datetime) {
12862     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12863     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12864         datetime, NULL);
12865     gst_date_time_unref (datetime);
12866   }
12867
12868   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12869   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12870
12871   /* check for fragmented file and get some (default) data */
12872   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12873   if (mvex) {
12874     GNode *mehd;
12875     GstByteReader mehd_data;
12876
12877     /* let track parsing or anyone know weird stuff might happen ... */
12878     qtdemux->fragmented = TRUE;
12879
12880     /* compensate for total duration */
12881     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12882     if (mehd)
12883       qtdemux_parse_mehd (qtdemux, &mehd_data);
12884   }
12885
12886   /* set duration in the segment info */
12887   gst_qtdemux_get_duration (qtdemux, &duration);
12888   if (duration) {
12889     qtdemux->segment.duration = duration;
12890     /* also do not exceed duration; stop is set that way post seek anyway,
12891      * and segment activation falls back to duration,
12892      * whereas loop only checks stop, so let's align this here as well */
12893     qtdemux->segment.stop = duration;
12894   }
12895
12896   /* parse all traks */
12897   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12898   while (trak) {
12899     qtdemux_parse_trak (qtdemux, trak);
12900     /* iterate all siblings */
12901     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12902   }
12903
12904   if (!qtdemux->tag_list) {
12905     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12906     qtdemux->tag_list = gst_tag_list_new_empty ();
12907     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12908   } else {
12909     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12910   }
12911
12912   /* find tags */
12913   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12914   if (udta) {
12915     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12916   } else {
12917     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12918   }
12919
12920   /* maybe also some tags in meta box */
12921   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12922   if (udta) {
12923     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12924     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12925   } else {
12926     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12927   }
12928
12929   /* parse any protection system info */
12930   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12931   while (pssh) {
12932     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12933     qtdemux_parse_pssh (qtdemux, pssh);
12934     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12935   }
12936
12937   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12938
12939   return TRUE;
12940 }
12941
12942 /* taken from ffmpeg */
12943 static int
12944 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12945 {
12946   int count = 4;
12947   int len = 0;
12948
12949   while (count--) {
12950     int c;
12951
12952     if (ptr >= end)
12953       return -1;
12954
12955     c = *ptr++;
12956     len = (len << 7) | (c & 0x7f);
12957     if (!(c & 0x80))
12958       break;
12959   }
12960   *end_out = ptr;
12961   return len;
12962 }
12963
12964 /* this can change the codec originally present in @list */
12965 static void
12966 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12967     GNode * esds, GstTagList * list)
12968 {
12969   int len = QT_UINT32 (esds->data);
12970   guint8 *ptr = esds->data;
12971   guint8 *end = ptr + len;
12972   int tag;
12973   guint8 *data_ptr = NULL;
12974   int data_len = 0;
12975   guint8 object_type_id = 0;
12976   const char *codec_name = NULL;
12977   GstCaps *caps = NULL;
12978
12979   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12980   ptr += 8;
12981   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12982   ptr += 4;
12983   while (ptr + 1 < end) {
12984     tag = QT_UINT8 (ptr);
12985     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12986     ptr++;
12987     len = read_descr_size (ptr, end, &ptr);
12988     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12989
12990     /* Check the stated amount of data is available for reading */
12991     if (len < 0 || ptr + len > end)
12992       break;
12993
12994     switch (tag) {
12995       case ES_DESCRIPTOR_TAG:
12996         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12997         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12998         ptr += 3;
12999         break;
13000       case DECODER_CONFIG_DESC_TAG:{
13001         guint max_bitrate, avg_bitrate;
13002
13003         object_type_id = QT_UINT8 (ptr);
13004         max_bitrate = QT_UINT32 (ptr + 5);
13005         avg_bitrate = QT_UINT32 (ptr + 9);
13006         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13007         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13008         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13009         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13010         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13011         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13012           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13013               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13014         }
13015         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13016           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13017               avg_bitrate, NULL);
13018         }
13019         ptr += 13;
13020         break;
13021       }
13022       case DECODER_SPECIFIC_INFO_TAG:
13023         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13024         if (object_type_id == 0xe0 && len == 0x40) {
13025           guint8 *data;
13026           GstStructure *s;
13027           guint32 clut[16];
13028           gint i;
13029
13030           GST_DEBUG_OBJECT (qtdemux,
13031               "Have VOBSUB palette. Creating palette event");
13032           /* move to decConfigDescr data and read palette */
13033           data = ptr;
13034           for (i = 0; i < 16; i++) {
13035             clut[i] = QT_UINT32 (data);
13036             data += 4;
13037           }
13038
13039           s = gst_structure_new ("application/x-gst-dvd", "event",
13040               G_TYPE_STRING, "dvd-spu-clut-change",
13041               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13042               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13043               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13044               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13045               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13046               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13047               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13048               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13049               NULL);
13050
13051           /* store event and trigger custom processing */
13052           stream->pending_event =
13053               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13054         } else {
13055           /* Generic codec_data handler puts it on the caps */
13056           data_ptr = ptr;
13057           data_len = len;
13058         }
13059
13060         ptr += len;
13061         break;
13062       case SL_CONFIG_DESC_TAG:
13063         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13064         ptr += 1;
13065         break;
13066       default:
13067         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13068             tag);
13069         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13070         ptr += len;
13071         break;
13072     }
13073   }
13074
13075   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13076    * in use, and should also be used to override some other parameters for some
13077    * codecs. */
13078   switch (object_type_id) {
13079     case 0x20:                 /* MPEG-4 */
13080       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13081        * profile_and_level_indication */
13082       if (data_ptr != NULL && data_len >= 5 &&
13083           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13084         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
13085             data_ptr + 4, data_len - 4);
13086       }
13087       break;                    /* Nothing special needed here */
13088     case 0x21:                 /* H.264 */
13089       codec_name = "H.264 / AVC";
13090       caps = gst_caps_new_simple ("video/x-h264",
13091           "stream-format", G_TYPE_STRING, "avc",
13092           "alignment", G_TYPE_STRING, "au", NULL);
13093       break;
13094     case 0x40:                 /* AAC (any) */
13095     case 0x66:                 /* AAC Main */
13096     case 0x67:                 /* AAC LC */
13097     case 0x68:                 /* AAC SSR */
13098       /* Override channels and rate based on the codec_data, as it's often
13099        * wrong. */
13100       /* Only do so for basic setup without HE-AAC extension */
13101       if (data_ptr && data_len == 2) {
13102         guint channels, rate;
13103
13104         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13105         if (channels > 0)
13106           stream->n_channels = channels;
13107
13108         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13109         if (rate > 0)
13110           stream->rate = rate;
13111       }
13112
13113       /* Set level and profile if possible */
13114       if (data_ptr != NULL && data_len >= 2) {
13115         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
13116             data_ptr, data_len);
13117       } else {
13118         const gchar *profile_str = NULL;
13119         GstBuffer *buffer;
13120         GstMapInfo map;
13121         guint8 *codec_data;
13122         gint rate_idx, profile;
13123
13124         /* No codec_data, let's invent something.
13125          * FIXME: This is wrong for SBR! */
13126
13127         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13128
13129         buffer = gst_buffer_new_and_alloc (2);
13130         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13131         codec_data = map.data;
13132
13133         rate_idx =
13134             gst_codec_utils_aac_get_index_from_sample_rate (stream->rate);
13135
13136         switch (object_type_id) {
13137           case 0x66:
13138             profile_str = "main";
13139             profile = 0;
13140             break;
13141           case 0x67:
13142             profile_str = "lc";
13143             profile = 1;
13144             break;
13145           case 0x68:
13146             profile_str = "ssr";
13147             profile = 2;
13148             break;
13149           default:
13150             profile = 3;
13151             break;
13152         }
13153
13154         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13155         codec_data[1] = ((rate_idx & 0x1) << 7) | (stream->n_channels << 3);
13156
13157         gst_buffer_unmap (buffer, &map);
13158         gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
13159             buffer, NULL);
13160         gst_buffer_unref (buffer);
13161
13162         if (profile_str) {
13163           gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
13164               profile_str, NULL);
13165         }
13166       }
13167       break;
13168     case 0x60:                 /* MPEG-2, various profiles */
13169     case 0x61:
13170     case 0x62:
13171     case 0x63:
13172     case 0x64:
13173     case 0x65:
13174       codec_name = "MPEG-2 video";
13175       caps = gst_caps_new_simple ("video/mpeg",
13176           "mpegversion", G_TYPE_INT, 2,
13177           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13178       break;
13179     case 0x69:                 /* MPEG-2 BC audio */
13180     case 0x6B:                 /* MPEG-1 audio */
13181       caps = gst_caps_new_simple ("audio/mpeg",
13182           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13183       codec_name = "MPEG-1 audio";
13184       break;
13185     case 0x6A:                 /* MPEG-1 */
13186       codec_name = "MPEG-1 video";
13187       caps = gst_caps_new_simple ("video/mpeg",
13188           "mpegversion", G_TYPE_INT, 1,
13189           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13190       break;
13191     case 0x6C:                 /* MJPEG */
13192       caps =
13193           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13194           NULL);
13195       codec_name = "Motion-JPEG";
13196       break;
13197     case 0x6D:                 /* PNG */
13198       caps =
13199           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13200           NULL);
13201       codec_name = "PNG still images";
13202       break;
13203     case 0x6E:                 /* JPEG2000 */
13204       codec_name = "JPEG-2000";
13205       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13206       break;
13207     case 0xA4:                 /* Dirac */
13208       codec_name = "Dirac";
13209       caps = gst_caps_new_empty_simple ("video/x-dirac");
13210       break;
13211     case 0xA5:                 /* AC3 */
13212       codec_name = "AC-3 audio";
13213       caps = gst_caps_new_simple ("audio/x-ac3",
13214           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13215       break;
13216     case 0xA9:                 /* AC3 */
13217       codec_name = "DTS audio";
13218       caps = gst_caps_new_simple ("audio/x-dts",
13219           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13220       break;
13221     case 0xE1:                 /* QCELP */
13222       /* QCELP, the codec_data is a riff tag (little endian) with
13223        * 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). */
13224       caps = gst_caps_new_empty_simple ("audio/qcelp");
13225       codec_name = "QCELP";
13226       break;
13227     default:
13228       break;
13229   }
13230
13231   /* If we have a replacement caps, then change our caps for this stream */
13232   if (caps) {
13233     gst_caps_unref (stream->caps);
13234     stream->caps = caps;
13235   }
13236
13237   if (codec_name && list)
13238     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13239         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13240
13241   /* Add the codec_data attribute to caps, if we have it */
13242   if (data_ptr) {
13243     GstBuffer *buffer;
13244
13245     buffer = gst_buffer_new_and_alloc (data_len);
13246     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13247
13248     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13249     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13250
13251     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
13252         buffer, NULL);
13253     gst_buffer_unref (buffer);
13254   }
13255
13256 }
13257
13258 static inline GstCaps *
13259 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13260 {
13261   GstCaps *caps;
13262   guint i;
13263   char *s, fourstr[5];
13264
13265   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13266   for (i = 0; i < 4; i++) {
13267     if (!g_ascii_isalnum (fourstr[i]))
13268       fourstr[i] = '_';
13269   }
13270   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13271   caps = gst_caps_new_empty_simple (s);
13272   g_free (s);
13273   return caps;
13274 }
13275
13276 #define _codec(name) \
13277   do { \
13278     if (codec_name) { \
13279       *codec_name = g_strdup (name); \
13280     } \
13281   } while (0)
13282
13283 static GstCaps *
13284 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13285     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13286 {
13287   GstCaps *caps = NULL;
13288   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13289
13290   switch (fourcc) {
13291     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
13292       _codec ("PNG still images");
13293       caps = gst_caps_new_empty_simple ("image/png");
13294       break;
13295     case FOURCC_jpeg:
13296       _codec ("JPEG still images");
13297       caps =
13298           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13299           NULL);
13300       break;
13301     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13302     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13303     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13304     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13305       _codec ("Motion-JPEG");
13306       caps =
13307           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13308           NULL);
13309       break;
13310     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13311       _codec ("Motion-JPEG format B");
13312       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13313       break;
13314     case FOURCC_mjp2:
13315       _codec ("JPEG-2000");
13316       /* override to what it should be according to spec, avoid palette_data */
13317       stream->bits_per_sample = 24;
13318       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13319       break;
13320     case FOURCC_SVQ3:
13321       _codec ("Sorensen video v.3");
13322       caps = gst_caps_new_simple ("video/x-svq",
13323           "svqversion", G_TYPE_INT, 3, NULL);
13324       break;
13325     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13326     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13327       _codec ("Sorensen video v.1");
13328       caps = gst_caps_new_simple ("video/x-svq",
13329           "svqversion", G_TYPE_INT, 1, NULL);
13330       break;
13331     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13332       caps = gst_caps_new_empty_simple ("video/x-raw");
13333       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13334       _codec ("Windows Raw RGB");
13335       stream->alignment = 32;
13336       break;
13337     case FOURCC_raw_:
13338     {
13339       guint16 bps;
13340
13341       bps = QT_UINT16 (stsd_data + 98);
13342       switch (bps) {
13343         case 15:
13344           format = GST_VIDEO_FORMAT_RGB15;
13345           break;
13346         case 16:
13347           format = GST_VIDEO_FORMAT_RGB16;
13348           break;
13349         case 24:
13350           format = GST_VIDEO_FORMAT_RGB;
13351           break;
13352         case 32:
13353           format = GST_VIDEO_FORMAT_ARGB;
13354           break;
13355         default:
13356           /* unknown */
13357           break;
13358       }
13359       break;
13360     }
13361     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13362       format = GST_VIDEO_FORMAT_I420;
13363       break;
13364     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13365     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13366       format = GST_VIDEO_FORMAT_I420;
13367       break;
13368     case FOURCC_2vuy:
13369     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13370       format = GST_VIDEO_FORMAT_UYVY;
13371       break;
13372     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13373       format = GST_VIDEO_FORMAT_v308;
13374       break;
13375     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13376       format = GST_VIDEO_FORMAT_v216;
13377       break;
13378     case FOURCC_v210:
13379       format = GST_VIDEO_FORMAT_v210;
13380       break;
13381     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13382       format = GST_VIDEO_FORMAT_r210;
13383       break;
13384       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13385          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13386          format = GST_VIDEO_FORMAT_v410;
13387          break;
13388        */
13389       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13390        * but different order than AYUV
13391        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13392        format = GST_VIDEO_FORMAT_v408;
13393        break;
13394        */
13395     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13396     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13397       _codec ("MPEG-1 video");
13398       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13399           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13400       break;
13401     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13402     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13403     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13404     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13405     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13406     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13407     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13408     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13409     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13410     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13411     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13412     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13413     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13414     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13415     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13416     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13417     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13418     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13419     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13420     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13421     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13422     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13423     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13424     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13425     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13426     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13427     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13428     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13429     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13430     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13431     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13432     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13433     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13434     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13435     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13436     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13437     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13438     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13439     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13440     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13441     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13442     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13443     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13444     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13445     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13446     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13447     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13448       _codec ("MPEG-2 video");
13449       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13450           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13451       break;
13452     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13453       _codec ("GIF still images");
13454       caps = gst_caps_new_empty_simple ("image/gif");
13455       break;
13456     case FOURCC_h263:
13457     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13458     case FOURCC_s263:
13459     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13460       _codec ("H.263");
13461       /* ffmpeg uses the height/width props, don't know why */
13462       caps = gst_caps_new_simple ("video/x-h263",
13463           "variant", G_TYPE_STRING, "itu", NULL);
13464       break;
13465     case FOURCC_mp4v:
13466     case FOURCC_MP4V:
13467       _codec ("MPEG-4 video");
13468       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13469           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13470       break;
13471     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13472     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13473       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13474       caps = gst_caps_new_simple ("video/x-msmpeg",
13475           "msmpegversion", G_TYPE_INT, 43, NULL);
13476       break;
13477     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13478       _codec ("DivX 3");
13479       caps = gst_caps_new_simple ("video/x-divx",
13480           "divxversion", G_TYPE_INT, 3, NULL);
13481       break;
13482     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13483     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13484       _codec ("DivX 4");
13485       caps = gst_caps_new_simple ("video/x-divx",
13486           "divxversion", G_TYPE_INT, 4, NULL);
13487       break;
13488     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13489       _codec ("DivX 5");
13490       caps = gst_caps_new_simple ("video/x-divx",
13491           "divxversion", G_TYPE_INT, 5, NULL);
13492       break;
13493
13494     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13495       _codec ("FFV1");
13496       caps = gst_caps_new_simple ("video/x-ffv",
13497           "ffvversion", G_TYPE_INT, 1, NULL);
13498       break;
13499
13500     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13501     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13502     case FOURCC_XVID:
13503     case FOURCC_xvid:
13504     case FOURCC_FMP4:
13505     case FOURCC_fmp4:
13506     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13507       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13508           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13509       _codec ("MPEG-4");
13510       break;
13511
13512     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13513       _codec ("Cinepak");
13514       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13515       break;
13516     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13517       _codec ("Apple QuickDraw");
13518       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13519       break;
13520     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13521       _codec ("Apple video");
13522       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13523       break;
13524     case FOURCC_H264:
13525     case FOURCC_avc1:
13526       _codec ("H.264 / AVC");
13527       caps = gst_caps_new_simple ("video/x-h264",
13528           "stream-format", G_TYPE_STRING, "avc",
13529           "alignment", G_TYPE_STRING, "au", NULL);
13530       break;
13531     case FOURCC_avc3:
13532       _codec ("H.264 / AVC");
13533       caps = gst_caps_new_simple ("video/x-h264",
13534           "stream-format", G_TYPE_STRING, "avc3",
13535           "alignment", G_TYPE_STRING, "au", NULL);
13536       break;
13537     case FOURCC_H265:
13538     case FOURCC_hvc1:
13539       _codec ("H.265 / HEVC");
13540       caps = gst_caps_new_simple ("video/x-h265",
13541           "stream-format", G_TYPE_STRING, "hvc1",
13542           "alignment", G_TYPE_STRING, "au", NULL);
13543       break;
13544     case FOURCC_hev1:
13545       _codec ("H.265 / HEVC");
13546       caps = gst_caps_new_simple ("video/x-h265",
13547           "stream-format", G_TYPE_STRING, "hev1",
13548           "alignment", G_TYPE_STRING, "au", NULL);
13549       break;
13550     case FOURCC_rle_:
13551       _codec ("Run-length encoding");
13552       caps = gst_caps_new_simple ("video/x-rle",
13553           "layout", G_TYPE_STRING, "quicktime", NULL);
13554       break;
13555     case FOURCC_WRLE:
13556       _codec ("Run-length encoding");
13557       caps = gst_caps_new_simple ("video/x-rle",
13558           "layout", G_TYPE_STRING, "microsoft", NULL);
13559       break;
13560     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13561     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13562       _codec ("Indeo Video 3");
13563       caps = gst_caps_new_simple ("video/x-indeo",
13564           "indeoversion", G_TYPE_INT, 3, NULL);
13565       break;
13566     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13567     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13568       _codec ("Intel Video 4");
13569       caps = gst_caps_new_simple ("video/x-indeo",
13570           "indeoversion", G_TYPE_INT, 4, NULL);
13571       break;
13572     case FOURCC_dvcp:
13573     case FOURCC_dvc_:
13574     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13575     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13576     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13577     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13578     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13579     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13580       _codec ("DV Video");
13581       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13582           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13583       break;
13584     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13585     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13586       _codec ("DVCPro50 Video");
13587       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13588           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13589       break;
13590     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13591     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13592       _codec ("DVCProHD Video");
13593       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13594           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13595       break;
13596     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13597       _codec ("Apple Graphics (SMC)");
13598       caps = gst_caps_new_empty_simple ("video/x-smc");
13599       break;
13600     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13601       _codec ("VP3");
13602       caps = gst_caps_new_empty_simple ("video/x-vp3");
13603       break;
13604     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13605       _codec ("VP6 Flash");
13606       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13607       break;
13608     case FOURCC_XiTh:
13609       _codec ("Theora");
13610       caps = gst_caps_new_empty_simple ("video/x-theora");
13611       /* theora uses one byte of padding in the data stream because it does not
13612        * allow 0 sized packets while theora does */
13613       stream->padding = 1;
13614       break;
13615     case FOURCC_drac:
13616       _codec ("Dirac");
13617       caps = gst_caps_new_empty_simple ("video/x-dirac");
13618       break;
13619     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13620       _codec ("TIFF still images");
13621       caps = gst_caps_new_empty_simple ("image/tiff");
13622       break;
13623     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13624       _codec ("Apple Intermediate Codec");
13625       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13626       break;
13627     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13628       _codec ("AVID DNxHD");
13629       caps = gst_caps_from_string ("video/x-dnxhd");
13630       break;
13631     case FOURCC_VP80:
13632       _codec ("On2 VP8");
13633       caps = gst_caps_from_string ("video/x-vp8");
13634       break;
13635     case FOURCC_apcs:
13636       _codec ("Apple ProRes LT");
13637       caps =
13638           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13639           NULL);
13640       break;
13641     case FOURCC_apch:
13642       _codec ("Apple ProRes HQ");
13643       caps =
13644           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13645           NULL);
13646       break;
13647     case FOURCC_apcn:
13648       _codec ("Apple ProRes");
13649       caps =
13650           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13651           "standard", NULL);
13652       break;
13653     case FOURCC_apco:
13654       _codec ("Apple ProRes Proxy");
13655       caps =
13656           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13657           "proxy", NULL);
13658       break;
13659     case FOURCC_ap4h:
13660       _codec ("Apple ProRes 4444");
13661       caps =
13662           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13663           "4444", NULL);
13664       break;
13665     case FOURCC_ap4x:
13666       _codec ("Apple ProRes 4444 XQ");
13667       caps =
13668           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13669           "4444xq", NULL);
13670       break;
13671     case FOURCC_vc_1:
13672     case FOURCC_ovc1:
13673       _codec ("VC-1");
13674       caps = gst_caps_new_simple ("video/x-wmv",
13675           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13676       break;
13677     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13678     default:
13679     {
13680       caps = _get_unknown_codec_name ("video", fourcc);
13681       break;
13682     }
13683   }
13684
13685   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13686     GstVideoInfo info;
13687
13688     gst_video_info_init (&info);
13689     gst_video_info_set_format (&info, format, stream->width, stream->height);
13690
13691     caps = gst_video_info_to_caps (&info);
13692     *codec_name = gst_pb_utils_get_codec_description (caps);
13693
13694     /* enable clipping for raw video streams */
13695     stream->need_clip = TRUE;
13696     stream->alignment = 32;
13697   }
13698
13699   return caps;
13700 }
13701
13702 static guint
13703 round_up_pow2 (guint n)
13704 {
13705   n = n - 1;
13706   n = n | (n >> 1);
13707   n = n | (n >> 2);
13708   n = n | (n >> 4);
13709   n = n | (n >> 8);
13710   n = n | (n >> 16);
13711   return n + 1;
13712 }
13713
13714 static GstCaps *
13715 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13716     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13717 {
13718   GstCaps *caps;
13719   const GstStructure *s;
13720   const gchar *name;
13721   gint endian = 0;
13722   GstAudioFormat format = 0;
13723   gint depth;
13724
13725   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13726
13727   depth = stream->bytes_per_packet * 8;
13728
13729   switch (fourcc) {
13730     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13731     case FOURCC_raw_:
13732       /* 8-bit audio is unsigned */
13733       if (depth == 8)
13734         format = GST_AUDIO_FORMAT_U8;
13735       /* otherwise it's signed and big-endian just like 'twos' */
13736     case FOURCC_twos:
13737       endian = G_BIG_ENDIAN;
13738       /* fall-through */
13739     case FOURCC_sowt:
13740     {
13741       gchar *str;
13742
13743       if (!endian)
13744         endian = G_LITTLE_ENDIAN;
13745
13746       if (!format)
13747         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13748
13749       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13750       _codec (str);
13751       g_free (str);
13752
13753       caps = gst_caps_new_simple ("audio/x-raw",
13754           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13755           "layout", G_TYPE_STRING, "interleaved", NULL);
13756       stream->alignment = GST_ROUND_UP_8 (depth);
13757       stream->alignment = round_up_pow2 (stream->alignment);
13758       break;
13759     }
13760     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13761       _codec ("Raw 64-bit floating-point audio");
13762       caps = gst_caps_new_simple ("audio/x-raw",
13763           "format", G_TYPE_STRING, "F64BE",
13764           "layout", G_TYPE_STRING, "interleaved", NULL);
13765       stream->alignment = 8;
13766       break;
13767     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13768       _codec ("Raw 32-bit floating-point audio");
13769       caps = gst_caps_new_simple ("audio/x-raw",
13770           "format", G_TYPE_STRING, "F32BE",
13771           "layout", G_TYPE_STRING, "interleaved", NULL);
13772       stream->alignment = 4;
13773       break;
13774     case FOURCC_in24:
13775       _codec ("Raw 24-bit PCM audio");
13776       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13777        * endian later */
13778       caps = gst_caps_new_simple ("audio/x-raw",
13779           "format", G_TYPE_STRING, "S24BE",
13780           "layout", G_TYPE_STRING, "interleaved", NULL);
13781       stream->alignment = 4;
13782       break;
13783     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13784       _codec ("Raw 32-bit PCM audio");
13785       caps = gst_caps_new_simple ("audio/x-raw",
13786           "format", G_TYPE_STRING, "S32BE",
13787           "layout", G_TYPE_STRING, "interleaved", NULL);
13788       stream->alignment = 4;
13789       break;
13790     case FOURCC_ulaw:
13791       _codec ("Mu-law audio");
13792       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13793       break;
13794     case FOURCC_alaw:
13795       _codec ("A-law audio");
13796       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13797       break;
13798     case 0x0200736d:
13799     case 0x6d730002:
13800       _codec ("Microsoft ADPCM");
13801       /* Microsoft ADPCM-ACM code 2 */
13802       caps = gst_caps_new_simple ("audio/x-adpcm",
13803           "layout", G_TYPE_STRING, "microsoft", NULL);
13804       break;
13805     case 0x1100736d:
13806     case 0x6d730011:
13807       _codec ("DVI/IMA ADPCM");
13808       caps = gst_caps_new_simple ("audio/x-adpcm",
13809           "layout", G_TYPE_STRING, "dvi", NULL);
13810       break;
13811     case 0x1700736d:
13812     case 0x6d730017:
13813       _codec ("DVI/Intel IMA ADPCM");
13814       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13815       caps = gst_caps_new_simple ("audio/x-adpcm",
13816           "layout", G_TYPE_STRING, "quicktime", NULL);
13817       break;
13818     case 0x5500736d:
13819     case 0x6d730055:
13820       /* MPEG layer 3, CBR only (pre QT4.1) */
13821     case FOURCC__mp3:
13822       _codec ("MPEG-1 layer 3");
13823       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13824       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13825           "mpegversion", G_TYPE_INT, 1, NULL);
13826       break;
13827     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
13828       _codec ("MPEG-1 layer 2");
13829       /* MPEG layer 2 */
13830       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
13831           "mpegversion", G_TYPE_INT, 1, NULL);
13832       break;
13833     case 0x20736d:
13834     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13835       _codec ("EAC-3 audio");
13836       caps = gst_caps_new_simple ("audio/x-eac3",
13837           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13838       stream->sampled = TRUE;
13839       break;
13840     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13841     case FOURCC_ac_3:
13842       _codec ("AC-3 audio");
13843       caps = gst_caps_new_simple ("audio/x-ac3",
13844           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13845       stream->sampled = TRUE;
13846       break;
13847     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13848     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13849       _codec ("DTS audio");
13850       caps = gst_caps_new_simple ("audio/x-dts",
13851           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13852       stream->sampled = TRUE;
13853       break;
13854     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13855     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13856       _codec ("DTS-HD audio");
13857       caps = gst_caps_new_simple ("audio/x-dts",
13858           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13859       stream->sampled = TRUE;
13860       break;
13861     case FOURCC_MAC3:
13862       _codec ("MACE-3");
13863       caps = gst_caps_new_simple ("audio/x-mace",
13864           "maceversion", G_TYPE_INT, 3, NULL);
13865       break;
13866     case FOURCC_MAC6:
13867       _codec ("MACE-6");
13868       caps = gst_caps_new_simple ("audio/x-mace",
13869           "maceversion", G_TYPE_INT, 6, NULL);
13870       break;
13871     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13872       /* ogg/vorbis */
13873       caps = gst_caps_new_empty_simple ("application/ogg");
13874       break;
13875     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13876       _codec ("DV audio");
13877       caps = gst_caps_new_empty_simple ("audio/x-dv");
13878       break;
13879     case FOURCC_mp4a:
13880       _codec ("MPEG-4 AAC audio");
13881       caps = gst_caps_new_simple ("audio/mpeg",
13882           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13883           "stream-format", G_TYPE_STRING, "raw", NULL);
13884       break;
13885     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13886       _codec ("QDesign Music");
13887       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13888       break;
13889     case FOURCC_QDM2:
13890       _codec ("QDesign Music v.2");
13891       /* FIXME: QDesign music version 2 (no constant) */
13892       if (FALSE && data) {
13893         caps = gst_caps_new_simple ("audio/x-qdm2",
13894             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13895             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13896             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13897       } else {
13898         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13899       }
13900       break;
13901     case FOURCC_agsm:
13902       _codec ("GSM audio");
13903       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13904       break;
13905     case FOURCC_samr:
13906       _codec ("AMR audio");
13907       caps = gst_caps_new_empty_simple ("audio/AMR");
13908       break;
13909     case FOURCC_sawb:
13910       _codec ("AMR-WB audio");
13911       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13912       break;
13913     case FOURCC_ima4:
13914       _codec ("Quicktime IMA ADPCM");
13915       caps = gst_caps_new_simple ("audio/x-adpcm",
13916           "layout", G_TYPE_STRING, "quicktime", NULL);
13917       break;
13918     case FOURCC_alac:
13919       _codec ("Apple lossless audio");
13920       caps = gst_caps_new_empty_simple ("audio/x-alac");
13921       break;
13922     case FOURCC_fLaC:
13923       _codec ("Free Lossless Audio Codec");
13924       caps = gst_caps_new_simple ("audio/x-flac",
13925           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13926       break;
13927     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13928       _codec ("QualComm PureVoice");
13929       caps = gst_caps_from_string ("audio/qcelp");
13930       break;
13931     case FOURCC_wma_:
13932     case FOURCC_owma:
13933       _codec ("WMA");
13934       caps = gst_caps_new_empty_simple ("audio/x-wma");
13935       break;
13936     case FOURCC_opus:
13937       _codec ("Opus");
13938       caps = gst_caps_new_empty_simple ("audio/x-opus");
13939       break;
13940     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13941     {
13942       guint32 flags = 0;
13943       guint32 depth = 0;
13944       guint32 width = 0;
13945       GstAudioFormat format;
13946       enum
13947       {
13948         FLAG_IS_FLOAT = 0x1,
13949         FLAG_IS_BIG_ENDIAN = 0x2,
13950         FLAG_IS_SIGNED = 0x4,
13951         FLAG_IS_PACKED = 0x8,
13952         FLAG_IS_ALIGNED_HIGH = 0x10,
13953         FLAG_IS_NON_INTERLEAVED = 0x20
13954       };
13955       _codec ("Raw LPCM audio");
13956
13957       if (data && len >= 56) {
13958         depth = QT_UINT32 (data + 40);
13959         flags = QT_UINT32 (data + 44);
13960         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13961       }
13962       if ((flags & FLAG_IS_FLOAT) == 0) {
13963         if (depth == 0)
13964           depth = 16;
13965         if (width == 0)
13966           width = 16;
13967         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13968             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13969             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13970         caps = gst_caps_new_simple ("audio/x-raw",
13971             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13972             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13973             "non-interleaved" : "interleaved", NULL);
13974         stream->alignment = GST_ROUND_UP_8 (depth);
13975         stream->alignment = round_up_pow2 (stream->alignment);
13976       } else {
13977         if (width == 0)
13978           width = 32;
13979         if (width == 64) {
13980           if (flags & FLAG_IS_BIG_ENDIAN)
13981             format = GST_AUDIO_FORMAT_F64BE;
13982           else
13983             format = GST_AUDIO_FORMAT_F64LE;
13984         } else {
13985           if (flags & FLAG_IS_BIG_ENDIAN)
13986             format = GST_AUDIO_FORMAT_F32BE;
13987           else
13988             format = GST_AUDIO_FORMAT_F32LE;
13989         }
13990         caps = gst_caps_new_simple ("audio/x-raw",
13991             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13992             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13993             "non-interleaved" : "interleaved", NULL);
13994         stream->alignment = width / 8;
13995       }
13996       break;
13997     }
13998     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
13999       /* ? */
14000     default:
14001     {
14002       caps = _get_unknown_codec_name ("audio", fourcc);
14003       break;
14004     }
14005   }
14006
14007   if (caps) {
14008     GstCaps *templ_caps =
14009         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14010     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14011     gst_caps_unref (caps);
14012     gst_caps_unref (templ_caps);
14013     caps = intersection;
14014   }
14015
14016   /* enable clipping for raw audio streams */
14017   s = gst_caps_get_structure (caps, 0);
14018   name = gst_structure_get_name (s);
14019   if (g_str_has_prefix (name, "audio/x-raw")) {
14020     stream->need_clip = TRUE;
14021     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
14022     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14023   }
14024   return caps;
14025 }
14026
14027 static GstCaps *
14028 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14029     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
14030 {
14031   GstCaps *caps;
14032
14033   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14034
14035   switch (fourcc) {
14036     case FOURCC_mp4s:
14037       _codec ("DVD subtitle");
14038       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14039       stream->need_process = TRUE;
14040       break;
14041     case FOURCC_text:
14042       _codec ("Quicktime timed text");
14043       goto text;
14044     case FOURCC_tx3g:
14045       _codec ("3GPP timed text");
14046     text:
14047       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14048           "utf8", NULL);
14049       /* actual text piece needs to be extracted */
14050       stream->need_process = TRUE;
14051       break;
14052     case FOURCC_stpp:
14053       _codec ("XML subtitles");
14054       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14055       break;
14056     default:
14057     {
14058       caps = _get_unknown_codec_name ("text", fourcc);
14059       break;
14060     }
14061   }
14062   return caps;
14063 }
14064
14065 static GstCaps *
14066 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14067     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
14068 {
14069   GstCaps *caps;
14070
14071   switch (fourcc) {
14072     case FOURCC_m1v:
14073       _codec ("MPEG 1 video");
14074       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14075           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14076       break;
14077     default:
14078       caps = NULL;
14079       break;
14080   }
14081   return caps;
14082 }
14083
14084 static void
14085 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14086     const gchar * system_id)
14087 {
14088   gint i;
14089
14090   if (!qtdemux->protection_system_ids)
14091     qtdemux->protection_system_ids =
14092         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14093   /* Check whether we already have an entry for this system ID. */
14094   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14095     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14096     if (g_ascii_strcasecmp (system_id, id) == 0) {
14097       return;
14098     }
14099   }
14100   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14101   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14102           -1));
14103 }