qtdemux: Don't modify upstream TIME segment
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public
24  * License along with this library; if not, write to the
25  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 /**
30  * SECTION:element-qtdemux
31  *
32  * Demuxes a .mov file into raw or compressed audio and/or video streams.
33  *
34  * This element supports both push and pull-based scheduling, depending on the
35  * capabilities of the upstream elements.
36  *
37  * <refsect2>
38  * <title>Example launch line</title>
39  * |[
40  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
41  * ]| Play (parse and decode) a .mov file and try to output it to
42  * an automatically detected soundcard and videosink. If the MOV file contains
43  * compressed audio or video data, this will only work if you have the
44  * right decoder elements/plugins installed.
45  * </refsect2>
46  */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #include "gst/gst-i18n-plugin.h"
53
54 #include <glib/gprintf.h>
55 #include <gst/tag/tag.h>
56 #include <gst/audio/audio.h>
57 #include <gst/video/video.h>
58
59 #include "qtatomparser.h"
60 #include "qtdemux_types.h"
61 #include "qtdemux_dump.h"
62 #include "fourcc.h"
63 #include "descriptors.h"
64 #include "qtdemux_lang.h"
65 #include "qtdemux.h"
66 #include "qtpalette.h"
67
68 #include "gst/riff/riff-media.h"
69 #include "gst/riff/riff-read.h"
70
71 #include <gst/pbutils/pbutils.h>
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include <math.h>
78 #include <gst/math-compat.h>
79
80 #ifdef HAVE_ZLIB
81 # include <zlib.h>
82 #endif
83
84 /* max. size considered 'sane' for non-mdat atoms */
85 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
86
87 /* if the sample index is larger than this, something is likely wrong */
88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
89
90 /* For converting qt creation times to unix epoch times */
91 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
92 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
93 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
94     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
95
96 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
97
98 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
99
100 GST_DEBUG_CATEGORY (qtdemux_debug);
101
102 typedef struct _QtDemuxSegment QtDemuxSegment;
103 typedef struct _QtDemuxSample QtDemuxSample;
104
105 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
106
107 struct _QtDemuxSample
108 {
109   guint32 size;
110   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
111   guint64 offset;
112   guint64 timestamp;            /* DTS In mov time */
113   guint32 duration;             /* In mov time */
114   gboolean keyframe;            /* TRUE when this packet is a keyframe */
115 };
116
117 /* Macros for converting to/from timescale */
118 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
119 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
120
121 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
122 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
123
124 /* timestamp is the DTS */
125 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
126 /* timestamp + offset is the PTS */
127 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
128 /* timestamp + duration - dts is the duration */
129 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
130
131 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
132
133 /*
134  * Quicktime has tracks and segments. A track is a continuous piece of
135  * multimedia content. The track is not always played from start to finish but
136  * instead, pieces of the track are 'cut out' and played in sequence. This is
137  * what the segments do.
138  *
139  * Inside the track we have keyframes (K) and delta frames. The track has its
140  * own timing, which starts from 0 and extends to end. The position in the track
141  * is called the media_time.
142  *
143  * The segments now describe the pieces that should be played from this track
144  * and are basically tuples of media_time/duration/rate entries. We can have
145  * multiple segments and they are all played after one another. An example:
146  *
147  * segment 1: media_time: 1 second, duration: 1 second, rate 1
148  * segment 2: media_time: 3 second, duration: 2 second, rate 2
149  *
150  * To correctly play back this track, one must play: 1 second of media starting
151  * from media_time 1 followed by 2 seconds of media starting from media_time 3
152  * at a rate of 2.
153  *
154  * Each of the segments will be played at a specific time, the first segment at
155  * time 0, the second one after the duration of the first one, etc.. Note that
156  * the time in resulting playback is not identical to the media_time of the
157  * track anymore.
158  *
159  * Visually, assuming the track has 4 second of media_time:
160  *
161  *                (a)                   (b)          (c)              (d)
162  *         .-----------------------------------------------------------.
163  * track:  | K.....K.........K........K.......K.......K...........K... |
164  *         '-----------------------------------------------------------'
165  *         0              1              2              3              4
166  *           .------------^              ^   .----------^              ^
167  *          /              .-------------'  /       .------------------'
168  *         /              /          .-----'       /
169  *         .--------------.         .--------------.
170  *         | segment 1    |         | segment 2    |
171  *         '--------------'         '--------------'
172  *
173  * The challenge here is to cut out the right pieces of the track for each of
174  * the playback segments. This fortunately can easily be done with the SEGMENT
175  * events of GStreamer.
176  *
177  * For playback of segment 1, we need to provide the decoder with the keyframe
178  * (a), in the above figure, but we must instruct it only to output the decoded
179  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
180  * position set to the time of the segment: 0.
181  *
182  * We then proceed to push data from keyframe (a) to frame (b). The decoder
183  * decodes but clips all before media_time 1.
184  *
185  * After finishing a segment, we push out a new SEGMENT event with the clipping
186  * boundaries of the new data.
187  *
188  * This is a good usecase for the GStreamer accumulated SEGMENT events.
189  */
190
191 struct _QtDemuxSegment
192 {
193   /* global time and duration, all gst time */
194   GstClockTime time;
195   GstClockTime stop_time;
196   GstClockTime duration;
197   /* media time of trak, all gst time */
198   GstClockTime media_start;
199   GstClockTime media_stop;
200   gdouble rate;
201   /* Media start time in trak timescale units */
202   guint32 trak_media_start;
203 };
204
205 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
206
207 /* Used with fragmented MP4 files (mfra atom) */
208 typedef struct
209 {
210   GstClockTime ts;
211   guint64 moof_offset;
212 } QtDemuxRandomAccessEntry;
213
214 struct _QtDemuxStream
215 {
216   GstPad *pad;
217
218   /* stream type */
219   guint32 subtype;
220   GstCaps *caps;
221   guint32 fourcc;
222   gboolean sparse;
223
224   gboolean new_caps;            /* If TRUE, caps need to be generated (by
225                                  * calling _configure_stream()) This happens
226                                  * for MSS and fragmented streams */
227
228   gboolean new_stream;          /* signals that a stream_start is required */
229   gboolean on_keyframe;         /* if this stream last pushed buffer was a
230                                  * keyframe. This is important to identify
231                                  * where to stop pushing buffers after a
232                                  * segment stop time */
233
234   /* if the stream has a redirect URI in its headers, we store it here */
235   gchar *redirect_uri;
236
237   /* track id */
238   guint track_id;
239
240   /* duration/scale */
241   guint64 duration;             /* in timescale units */
242   guint32 timescale;
243
244   /* language */
245   gchar lang_id[4];             /* ISO 639-2T language code */
246
247   /* our samples */
248   guint32 n_samples;
249   QtDemuxSample *samples;
250   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
251   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
252                                    the framerate */
253   guint32 n_samples_moof;       /* sample count in a moof */
254   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
255                                  * the framerate of fragmented format stream */
256   guint64 duration_last_moof;
257
258   guint32 offset_in_sample;     /* Offset in the current sample, used for
259                                  * streams which have got exceedingly big
260                                  * sample size (such as 24s of raw audio).
261                                  * Only used when max_buffer_size is non-NULL */
262   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
263                                  * Currently only set for raw audio streams*/
264
265   /* if we use chunks or samples */
266   gboolean sampled;
267   guint padding;
268
269   /* video info */
270   gint width;
271   gint height;
272   /* aspect ratio */
273   gint display_width;
274   gint display_height;
275   gint par_w;
276   gint par_h;
277   /* Numerator/denominator framerate */
278   gint fps_n;
279   gint fps_d;
280   GstVideoColorimetry colorimetry;
281   guint16 bits_per_sample;
282   guint16 color_table_id;
283   GstMemory *rgb8_palette;
284
285   /* audio info */
286   gdouble rate;
287   gint n_channels;
288   guint samples_per_packet;
289   guint samples_per_frame;
290   guint bytes_per_packet;
291   guint bytes_per_sample;
292   guint bytes_per_frame;
293   guint compression;
294
295   /* allocation */
296   gboolean use_allocator;
297   GstAllocator *allocator;
298   GstAllocationParams params;
299
300   /* when a discontinuity is pending */
301   gboolean discont;
302
303   /* list of buffers to push first */
304   GSList *buffers;
305
306   /* if we need to clip this buffer. This is only needed for uncompressed
307    * data */
308   gboolean need_clip;
309
310   /* buffer needs some custom processing, e.g. subtitles */
311   gboolean need_process;
312
313   /* current position */
314   guint32 segment_index;
315   guint32 sample_index;
316   GstClockTime time_position;   /* in gst time */
317   guint64 accumulated_base;
318
319   /* the Gst segment we are processing out, used for clipping */
320   GstSegment segment;
321
322   /* quicktime segments */
323   guint32 n_segments;
324   QtDemuxSegment *segments;
325   gboolean dummy_segment;
326   guint32 from_sample;
327   guint32 to_sample;
328
329   gboolean sent_eos;
330   GstTagList *pending_tags;
331   gboolean send_global_tags;
332
333   GstEvent *pending_event;
334
335   GstByteReader stco;
336   GstByteReader stsz;
337   GstByteReader stsc;
338   GstByteReader stts;
339   GstByteReader stss;
340   GstByteReader stps;
341   GstByteReader ctts;
342
343   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
344   gint64 stbl_index;
345   /* stco */
346   guint co_size;
347   GstByteReader co_chunk;
348   guint32 first_chunk;
349   guint32 current_chunk;
350   guint32 last_chunk;
351   guint32 samples_per_chunk;
352   guint32 stco_sample_index;
353   /* stsz */
354   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
355   /* stsc */
356   guint32 stsc_index;
357   guint32 n_samples_per_chunk;
358   guint32 stsc_chunk_index;
359   guint32 stsc_sample_index;
360   guint64 chunk_offset;
361   /* stts */
362   guint32 stts_index;
363   guint32 stts_samples;
364   guint32 n_sample_times;
365   guint32 stts_sample_index;
366   guint64 stts_time;
367   guint32 stts_duration;
368   /* stss */
369   gboolean stss_present;
370   guint32 n_sample_syncs;
371   guint32 stss_index;
372   /* stps */
373   gboolean stps_present;
374   guint32 n_sample_partial_syncs;
375   guint32 stps_index;
376   QtDemuxRandomAccessEntry *ra_entries;
377   guint n_ra_entries;
378
379   const QtDemuxRandomAccessEntry *pending_seek;
380
381   /* ctts */
382   gboolean ctts_present;
383   guint32 n_composition_times;
384   guint32 ctts_index;
385   guint32 ctts_sample_index;
386   guint32 ctts_count;
387   gint32 ctts_soffset;
388
389   /* cslg */
390   guint32 cslg_shift;
391
392   /* fragmented */
393   gboolean parsed_trex;
394   guint32 def_sample_duration;
395   guint32 def_sample_size;
396   guint32 def_sample_flags;
397
398   gboolean disabled;
399
400   /* stereoscopic video streams */
401   GstVideoMultiviewMode multiview_mode;
402   GstVideoMultiviewFlags multiview_flags;
403
404   /* protected streams */
405   gboolean protected;
406   guint32 protection_scheme_type;
407   guint32 protection_scheme_version;
408   gpointer protection_scheme_info;      /* specific to the protection scheme */
409   GQueue protection_scheme_event_queue;
410 };
411
412 /* Contains properties and cryptographic info for a set of samples from a
413  * track protected using Common Encryption (cenc) */
414 struct _QtDemuxCencSampleSetInfo
415 {
416   GstStructure *default_properties;
417
418   /* @crypto_info holds one GstStructure per sample */
419   GPtrArray *crypto_info;
420 };
421
422 static const gchar *
423 qt_demux_state_string (enum QtDemuxState state)
424 {
425   switch (state) {
426     case QTDEMUX_STATE_INITIAL:
427       return "<INITIAL>";
428     case QTDEMUX_STATE_HEADER:
429       return "<HEADER>";
430     case QTDEMUX_STATE_MOVIE:
431       return "<MOVIE>";
432     case QTDEMUX_STATE_BUFFER_MDAT:
433       return "<BUFFER_MDAT>";
434     default:
435       return "<UNKNOWN>";
436   }
437 }
438
439 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
440 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
441     guint32 fourcc, GstByteReader * parser);
442 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
443 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
444     guint32 fourcc, GstByteReader * parser);
445
446 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
447
448 static GstStaticPadTemplate gst_qtdemux_sink_template =
449     GST_STATIC_PAD_TEMPLATE ("sink",
450     GST_PAD_SINK,
451     GST_PAD_ALWAYS,
452     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
453         "application/x-3gp")
454     );
455
456 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
457 GST_STATIC_PAD_TEMPLATE ("video_%u",
458     GST_PAD_SRC,
459     GST_PAD_SOMETIMES,
460     GST_STATIC_CAPS_ANY);
461
462 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
463 GST_STATIC_PAD_TEMPLATE ("audio_%u",
464     GST_PAD_SRC,
465     GST_PAD_SOMETIMES,
466     GST_STATIC_CAPS_ANY);
467
468 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
469 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
470     GST_PAD_SRC,
471     GST_PAD_SOMETIMES,
472     GST_STATIC_CAPS_ANY);
473
474 #define gst_qtdemux_parent_class parent_class
475 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
476
477 static void gst_qtdemux_dispose (GObject * object);
478
479 static guint32
480 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
481     GstClockTime media_time);
482 static guint32
483 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
484     QtDemuxStream * str, gint64 media_offset);
485
486 #if 0
487 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
488 static GstIndex *gst_qtdemux_get_index (GstElement * element);
489 #endif
490 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
491     GstStateChange transition);
492 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
493 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
494     GstObject * parent, GstPadMode mode, gboolean active);
495
496 static void gst_qtdemux_loop (GstPad * pad);
497 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
498     GstBuffer * inbuf);
499 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
500     GstEvent * event);
501 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
502 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
503     QtDemuxStream * stream);
504 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
505     gboolean force);
506
507 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
508     const guint8 * buffer, guint length);
509 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
510     const guint8 * buffer, guint length);
511 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
512 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
513     GNode * udta);
514
515 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
516     QtDemuxStream * stream, GNode * esds, GstTagList * list);
517 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
518     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
519     gchar ** codec_name);
520 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
521     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
522     gchar ** codec_name);
523 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
524     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
525     gchar ** codec_name);
526 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
527     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
528     gchar ** codec_name);
529
530 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
531     QtDemuxStream * stream, guint32 n);
532 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
533 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
534     QtDemuxStream * stream);
535 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
536     QtDemuxStream * stream);
537 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
538 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
539 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
540     QtDemuxStream * stream);
541 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
542     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
543 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
544     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
545     GstClockTime * _start, GstClockTime * _stop);
546 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
547     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
548
549 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
550 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
551
552 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
553
554 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
555     QtDemuxStream * stream, guint sample_index);
556 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
557     const gchar * id);
558 static void qtdemux_gst_structure_free (GstStructure * gststructure);
559
560 static void
561 gst_qtdemux_class_init (GstQTDemuxClass * klass)
562 {
563   GObjectClass *gobject_class;
564   GstElementClass *gstelement_class;
565
566   gobject_class = (GObjectClass *) klass;
567   gstelement_class = (GstElementClass *) klass;
568
569   parent_class = g_type_class_peek_parent (klass);
570
571   gobject_class->dispose = gst_qtdemux_dispose;
572
573   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
574 #if 0
575   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
576   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
577 #endif
578
579   gst_tag_register_musicbrainz_tags ();
580
581   gst_element_class_add_static_pad_template (gstelement_class,
582       &gst_qtdemux_sink_template);
583   gst_element_class_add_static_pad_template (gstelement_class,
584       &gst_qtdemux_videosrc_template);
585   gst_element_class_add_static_pad_template (gstelement_class,
586       &gst_qtdemux_audiosrc_template);
587   gst_element_class_add_static_pad_template (gstelement_class,
588       &gst_qtdemux_subsrc_template);
589   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
590       "Codec/Demuxer",
591       "Demultiplex a QuickTime file into audio and video streams",
592       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
593
594   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
595
596 }
597
598 static void
599 gst_qtdemux_init (GstQTDemux * qtdemux)
600 {
601   qtdemux->sinkpad =
602       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
603   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
604   gst_pad_set_activatemode_function (qtdemux->sinkpad,
605       qtdemux_sink_activate_mode);
606   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
607   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
608   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
609
610   qtdemux->state = QTDEMUX_STATE_INITIAL;
611   qtdemux->pullbased = FALSE;
612   qtdemux->posted_redirect = FALSE;
613   qtdemux->neededbytes = 16;
614   qtdemux->todrop = 0;
615   qtdemux->adapter = gst_adapter_new ();
616   qtdemux->offset = 0;
617   qtdemux->first_mdat = -1;
618   qtdemux->got_moov = FALSE;
619   qtdemux->mdatoffset = -1;
620   qtdemux->mdatbuffer = NULL;
621   qtdemux->restoredata_buffer = NULL;
622   qtdemux->restoredata_offset = -1;
623   qtdemux->fragment_start = -1;
624   qtdemux->fragment_start_offset = -1;
625   qtdemux->media_caps = NULL;
626   qtdemux->exposed = FALSE;
627   qtdemux->mss_mode = FALSE;
628   qtdemux->pending_newsegment = NULL;
629   qtdemux->upstream_format_is_time = FALSE;
630   qtdemux->have_group_id = FALSE;
631   qtdemux->group_id = G_MAXUINT;
632   qtdemux->cenc_aux_info_offset = 0;
633   qtdemux->cenc_aux_info_sizes = NULL;
634   qtdemux->cenc_aux_sample_count = 0;
635   qtdemux->protection_system_ids = NULL;
636   g_queue_init (&qtdemux->protection_event_queue);
637   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
638   qtdemux->flowcombiner = gst_flow_combiner_new ();
639
640   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
641 }
642
643 static void
644 gst_qtdemux_dispose (GObject * object)
645 {
646   GstQTDemux *qtdemux = GST_QTDEMUX (object);
647
648   if (qtdemux->adapter) {
649     g_object_unref (G_OBJECT (qtdemux->adapter));
650     qtdemux->adapter = NULL;
651   }
652   gst_flow_combiner_free (qtdemux->flowcombiner);
653   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
654       NULL);
655   g_queue_clear (&qtdemux->protection_event_queue);
656
657   g_free (qtdemux->cenc_aux_info_sizes);
658   qtdemux->cenc_aux_info_sizes = NULL;
659
660   G_OBJECT_CLASS (parent_class)->dispose (object);
661 }
662
663 static void
664 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
665 {
666   if (qtdemux->posted_redirect) {
667     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
668         (_("This file contains no playable streams.")),
669         ("no known streams found, a redirect message has been posted"));
670   } else {
671     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
672         (_("This file contains no playable streams.")),
673         ("no known streams found"));
674   }
675 }
676
677 static GstBuffer *
678 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
679 {
680   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
681       mem, size, 0, size, mem, free_func);
682 }
683
684 static GstFlowReturn
685 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
686     GstBuffer ** buf)
687 {
688   GstFlowReturn flow;
689   GstMapInfo map;
690   gsize bsize;
691
692   if (G_UNLIKELY (size == 0)) {
693     GstFlowReturn ret;
694     GstBuffer *tmp = NULL;
695
696     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
697     if (ret != GST_FLOW_OK)
698       return ret;
699
700     gst_buffer_map (tmp, &map, GST_MAP_READ);
701     size = QT_UINT32 (map.data);
702     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
703
704     gst_buffer_unmap (tmp, &map);
705     gst_buffer_unref (tmp);
706   }
707
708   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
709   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
710     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
711       /* we're pulling header but already got most interesting bits,
712        * so never mind the rest (e.g. tags) (that much) */
713       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
714           size);
715       return GST_FLOW_EOS;
716     } else {
717       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
718           (_("This file is invalid and cannot be played.")),
719           ("atom has bogus size %" G_GUINT64_FORMAT, size));
720       return GST_FLOW_ERROR;
721     }
722   }
723
724   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
725
726   if (G_UNLIKELY (flow != GST_FLOW_OK))
727     return flow;
728
729   bsize = gst_buffer_get_size (*buf);
730   /* Catch short reads - we don't want any partial atoms */
731   if (G_UNLIKELY (bsize < size)) {
732     GST_WARNING_OBJECT (qtdemux,
733         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
734     gst_buffer_unref (*buf);
735     *buf = NULL;
736     return GST_FLOW_EOS;
737   }
738
739   return flow;
740 }
741
742 #if 1
743 static gboolean
744 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
745     GstFormat src_format, gint64 src_value, GstFormat dest_format,
746     gint64 * dest_value)
747 {
748   gboolean res = TRUE;
749   QtDemuxStream *stream = gst_pad_get_element_private (pad);
750   gint32 index;
751
752   if (stream->subtype != FOURCC_vide) {
753     res = FALSE;
754     goto done;
755   }
756
757   switch (src_format) {
758     case GST_FORMAT_TIME:
759       switch (dest_format) {
760         case GST_FORMAT_BYTES:{
761           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
762           if (-1 == index) {
763             res = FALSE;
764             goto done;
765           }
766
767           *dest_value = stream->samples[index].offset;
768
769           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
770               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
771               GST_TIME_ARGS (src_value), *dest_value);
772           break;
773         }
774         default:
775           res = FALSE;
776           break;
777       }
778       break;
779     case GST_FORMAT_BYTES:
780       switch (dest_format) {
781         case GST_FORMAT_TIME:{
782           index =
783               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
784               stream, src_value);
785
786           if (-1 == index) {
787             res = FALSE;
788             goto done;
789           }
790
791           *dest_value =
792               QTSTREAMTIME_TO_GSTTIME (stream,
793               stream->samples[index].timestamp);
794           GST_DEBUG_OBJECT (qtdemux,
795               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
796               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
797           break;
798         }
799         default:
800           res = FALSE;
801           break;
802       }
803       break;
804     default:
805       res = FALSE;
806       break;
807   }
808
809 done:
810   return res;
811 }
812 #endif
813
814 static gboolean
815 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
816 {
817   gboolean res = FALSE;
818
819   *duration = GST_CLOCK_TIME_NONE;
820
821   if (qtdemux->duration != 0 &&
822       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
823     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
824     res = TRUE;
825   } else {
826     *duration = GST_CLOCK_TIME_NONE;
827   }
828
829   return res;
830 }
831
832 static gboolean
833 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
834     GstQuery * query)
835 {
836   gboolean res = FALSE;
837   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
838
839   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
840
841   switch (GST_QUERY_TYPE (query)) {
842     case GST_QUERY_POSITION:{
843       GstFormat fmt;
844
845       gst_query_parse_position (query, &fmt, NULL);
846       if (fmt == GST_FORMAT_TIME
847           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
848         gst_query_set_position (query, GST_FORMAT_TIME,
849             qtdemux->segment.position);
850         res = TRUE;
851       }
852     }
853       break;
854     case GST_QUERY_DURATION:{
855       GstFormat fmt;
856
857       gst_query_parse_duration (query, &fmt, NULL);
858       if (fmt == GST_FORMAT_TIME) {
859         /* First try to query upstream */
860         res = gst_pad_query_default (pad, parent, query);
861         if (!res) {
862           GstClockTime duration;
863           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
864             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
865             res = TRUE;
866           }
867         }
868       }
869       break;
870     }
871     case GST_QUERY_CONVERT:{
872       GstFormat src_fmt, dest_fmt;
873       gint64 src_value, dest_value = 0;
874
875       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
876
877       res = gst_qtdemux_src_convert (qtdemux, pad,
878           src_fmt, src_value, dest_fmt, &dest_value);
879       if (res) {
880         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
881         res = TRUE;
882       }
883       break;
884     }
885     case GST_QUERY_FORMATS:
886       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
887       res = TRUE;
888       break;
889     case GST_QUERY_SEEKING:{
890       GstFormat fmt;
891       gboolean seekable;
892
893       /* try upstream first */
894       res = gst_pad_query_default (pad, parent, query);
895
896       if (!res) {
897         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
898         if (fmt == GST_FORMAT_TIME) {
899           GstClockTime duration;
900
901           gst_qtdemux_get_duration (qtdemux, &duration);
902           seekable = TRUE;
903           if (!qtdemux->pullbased) {
904             GstQuery *q;
905
906             /* we might be able with help from upstream */
907             seekable = FALSE;
908             q = gst_query_new_seeking (GST_FORMAT_BYTES);
909             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
910               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
911               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
912             }
913             gst_query_unref (q);
914           }
915           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
916           res = TRUE;
917         }
918       }
919       break;
920     }
921     case GST_QUERY_SEGMENT:
922     {
923       GstFormat format;
924       gint64 start, stop;
925
926       format = qtdemux->segment.format;
927
928       start =
929           gst_segment_to_stream_time (&qtdemux->segment, format,
930           qtdemux->segment.start);
931       if ((stop = qtdemux->segment.stop) == -1)
932         stop = qtdemux->segment.duration;
933       else
934         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
935
936       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
937       res = TRUE;
938       break;
939     }
940     default:
941       res = gst_pad_query_default (pad, parent, query);
942       break;
943   }
944
945   return res;
946 }
947
948 static void
949 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
950 {
951   if (G_LIKELY (stream->pad)) {
952     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
953         GST_DEBUG_PAD_NAME (stream->pad));
954
955     if (G_UNLIKELY (stream->pending_tags)) {
956       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
957           stream->pending_tags);
958       gst_pad_push_event (stream->pad,
959           gst_event_new_tag (stream->pending_tags));
960       stream->pending_tags = NULL;
961     }
962
963     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
964       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
965           qtdemux->tag_list);
966       gst_pad_push_event (stream->pad,
967           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
968       stream->send_global_tags = FALSE;
969     }
970   }
971 }
972
973 /* push event on all source pads; takes ownership of the event */
974 static void
975 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
976 {
977   guint n;
978   gboolean has_valid_stream = FALSE;
979   GstEventType etype = GST_EVENT_TYPE (event);
980
981   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
982       GST_EVENT_TYPE_NAME (event));
983
984   for (n = 0; n < qtdemux->n_streams; n++) {
985     GstPad *pad;
986     QtDemuxStream *stream = qtdemux->streams[n];
987     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
988
989     if ((pad = stream->pad)) {
990       has_valid_stream = TRUE;
991
992       if (etype == GST_EVENT_EOS) {
993         /* let's not send twice */
994         if (stream->sent_eos)
995           continue;
996         stream->sent_eos = TRUE;
997       }
998
999       gst_pad_push_event (pad, gst_event_ref (event));
1000     }
1001   }
1002
1003   gst_event_unref (event);
1004
1005   /* if it is EOS and there are no pads, post an error */
1006   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1007     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1008   }
1009 }
1010
1011 /* push a pending newsegment event, if any from the streaming thread */
1012 static void
1013 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1014 {
1015   if (qtdemux->pending_newsegment) {
1016     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1017     qtdemux->pending_newsegment = NULL;
1018   }
1019 }
1020
1021 typedef struct
1022 {
1023   guint64 media_time;
1024 } FindData;
1025
1026 static gint
1027 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1028 {
1029   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1030     return 1;
1031   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1032     return 0;
1033
1034   return -1;
1035 }
1036
1037 /* find the index of the sample that includes the data for @media_time using a
1038  * binary search.  Only to be called in optimized cases of linear search below.
1039  *
1040  * Returns the index of the sample.
1041  */
1042 static guint32
1043 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1044     guint64 media_time)
1045 {
1046   QtDemuxSample *result;
1047   guint32 index;
1048
1049   /* convert media_time to mov format */
1050   media_time =
1051       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1052
1053   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1054       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1055       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1056
1057   if (G_LIKELY (result))
1058     index = result - str->samples;
1059   else
1060     index = 0;
1061
1062   return index;
1063 }
1064
1065
1066
1067 /* find the index of the sample that includes the data for @media_offset using a
1068  * linear search
1069  *
1070  * Returns the index of the sample.
1071  */
1072 static guint32
1073 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1074     QtDemuxStream * str, gint64 media_offset)
1075 {
1076   QtDemuxSample *result = str->samples;
1077   guint32 index = 0;
1078
1079   if (result == NULL || str->n_samples == 0)
1080     return -1;
1081
1082   if (media_offset == result->offset)
1083     return index;
1084
1085   result++;
1086   while (index < str->n_samples - 1) {
1087     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1088       goto parse_failed;
1089
1090     if (media_offset < result->offset)
1091       break;
1092
1093     index++;
1094     result++;
1095   }
1096   return index;
1097
1098   /* ERRORS */
1099 parse_failed:
1100   {
1101     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1102     return -1;
1103   }
1104 }
1105
1106 /* find the index of the sample that includes the data for @media_time using a
1107  * linear search, and keeping in mind that not all samples may have been parsed
1108  * yet.  If possible, it will delegate to binary search.
1109  *
1110  * Returns the index of the sample.
1111  */
1112 static guint32
1113 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1114     GstClockTime media_time)
1115 {
1116   guint32 index = 0;
1117   guint64 mov_time;
1118   QtDemuxSample *sample;
1119
1120   /* convert media_time to mov format */
1121   mov_time =
1122       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1123
1124   sample = str->samples;
1125   if (mov_time == sample->timestamp + sample->pts_offset)
1126     return index;
1127
1128   /* use faster search if requested time in already parsed range */
1129   sample = str->samples + str->stbl_index;
1130   if (str->stbl_index >= 0 &&
1131       mov_time <= (sample->timestamp + sample->pts_offset))
1132     return gst_qtdemux_find_index (qtdemux, str, media_time);
1133
1134   while (index < str->n_samples - 1) {
1135     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1136       goto parse_failed;
1137
1138     sample = str->samples + index + 1;
1139     if (mov_time < (sample->timestamp + sample->pts_offset))
1140       break;
1141
1142     index++;
1143   }
1144   return index;
1145
1146   /* ERRORS */
1147 parse_failed:
1148   {
1149     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1150     return -1;
1151   }
1152 }
1153
1154 /* find the index of the keyframe needed to decode the sample at @index
1155  * of stream @str.
1156  *
1157  * Returns the index of the keyframe.
1158  */
1159 static guint32
1160 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1161     guint32 index)
1162 {
1163   guint32 new_index = index;
1164
1165   if (index >= str->n_samples) {
1166     new_index = str->n_samples;
1167     goto beach;
1168   }
1169
1170   /* all keyframes, return index */
1171   if (str->all_keyframe) {
1172     new_index = index;
1173     goto beach;
1174   }
1175
1176   /* else go back until we have a keyframe */
1177   while (TRUE) {
1178     if (str->samples[new_index].keyframe)
1179       break;
1180
1181     if (new_index == 0)
1182       break;
1183
1184     new_index--;
1185   }
1186
1187 beach:
1188   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1189       "gave %u", index, new_index);
1190
1191   return new_index;
1192 }
1193
1194 /* find the segment for @time_position for @stream
1195  *
1196  * Returns the index of the segment containing @time_position.
1197  * Returns the last segment and sets the @eos variable to TRUE
1198  * if the time is beyond the end. @eos may be NULL
1199  */
1200 static guint32
1201 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1202     GstClockTime time_position)
1203 {
1204   gint i;
1205   guint32 seg_idx;
1206
1207   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1208       GST_TIME_ARGS (time_position));
1209
1210   seg_idx = -1;
1211   for (i = 0; i < stream->n_segments; i++) {
1212     QtDemuxSegment *segment = &stream->segments[i];
1213
1214     GST_LOG_OBJECT (stream->pad,
1215         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1216         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1217
1218     /* For the last segment we include stop_time in the last segment */
1219     if (i < stream->n_segments - 1) {
1220       if (segment->time <= time_position && time_position < segment->stop_time) {
1221         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1222         seg_idx = i;
1223         break;
1224       }
1225     } else {
1226       /* Last segment always matches */
1227       seg_idx = i;
1228       break;
1229     }
1230   }
1231   return seg_idx;
1232 }
1233
1234 /* move the stream @str to the sample position @index.
1235  *
1236  * Updates @str->sample_index and marks discontinuity if needed.
1237  */
1238 static void
1239 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1240     guint32 index)
1241 {
1242   /* no change needed */
1243   if (index == str->sample_index)
1244     return;
1245
1246   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1247       str->n_samples);
1248
1249   /* position changed, we have a discont */
1250   str->sample_index = index;
1251   str->offset_in_sample = 0;
1252   /* Each time we move in the stream we store the position where we are
1253    * starting from */
1254   str->from_sample = index;
1255   str->discont = TRUE;
1256 }
1257
1258 static void
1259 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1260     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1261 {
1262   guint64 min_offset;
1263   gint64 min_byte_offset = -1;
1264   gint n;
1265
1266   min_offset = desired_time;
1267
1268   /* for each stream, find the index of the sample in the segment
1269    * and move back to the previous keyframe. */
1270   for (n = 0; n < qtdemux->n_streams; n++) {
1271     QtDemuxStream *str;
1272     guint32 index, kindex;
1273     guint32 seg_idx;
1274     GstClockTime media_start;
1275     GstClockTime media_time;
1276     GstClockTime seg_time;
1277     QtDemuxSegment *seg;
1278     gboolean empty_segment = FALSE;
1279
1280     str = qtdemux->streams[n];
1281
1282     if (str->sparse && !use_sparse)
1283       continue;
1284
1285     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1286     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1287
1288     /* get segment and time in the segment */
1289     seg = &str->segments[seg_idx];
1290     seg_time = (desired_time - seg->time) * seg->rate;
1291
1292     while (QTSEGMENT_IS_EMPTY (seg)) {
1293       seg_time = 0;
1294       empty_segment = TRUE;
1295       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1296           seg_idx);
1297       seg_idx++;
1298       if (seg_idx == str->n_segments)
1299         break;
1300       seg = &str->segments[seg_idx];
1301     }
1302
1303     if (seg_idx == str->n_segments) {
1304       /* FIXME track shouldn't have the last segment as empty, but if it
1305        * happens we better handle it */
1306       continue;
1307     }
1308
1309     /* get the media time in the segment */
1310     media_start = seg->media_start + seg_time;
1311
1312     /* get the index of the sample with media time */
1313     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1314     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1315         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1316         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1317         empty_segment);
1318
1319     if (!empty_segment) {
1320       /* find previous keyframe */
1321       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1322
1323       /* if the keyframe is at a different position, we need to update the
1324        * requested seek time */
1325       if (index != kindex) {
1326         index = kindex;
1327
1328         /* get timestamp of keyframe */
1329         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1330         GST_DEBUG_OBJECT (qtdemux,
1331             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1332             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1333             str->samples[kindex].offset);
1334
1335         /* keyframes in the segment get a chance to change the
1336          * desired_offset. keyframes out of the segment are
1337          * ignored. */
1338         if (media_time >= seg->media_start) {
1339           GstClockTime seg_time;
1340
1341           /* this keyframe is inside the segment, convert back to
1342            * segment time */
1343           seg_time = (media_time - seg->media_start) + seg->time;
1344           if (seg_time < min_offset)
1345             min_offset = seg_time;
1346         }
1347       }
1348     }
1349
1350     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1351       min_byte_offset = str->samples[index].offset;
1352   }
1353
1354   if (key_time)
1355     *key_time = min_offset;
1356   if (key_offset)
1357     *key_offset = min_byte_offset;
1358 }
1359
1360 static gboolean
1361 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1362     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1363 {
1364   gboolean res;
1365
1366   g_return_val_if_fail (format != NULL, FALSE);
1367   g_return_val_if_fail (cur != NULL, FALSE);
1368   g_return_val_if_fail (stop != NULL, FALSE);
1369
1370   if (*format == GST_FORMAT_TIME)
1371     return TRUE;
1372
1373   res = TRUE;
1374   if (cur_type != GST_SEEK_TYPE_NONE)
1375     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1376   if (res && stop_type != GST_SEEK_TYPE_NONE)
1377     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1378
1379   if (res)
1380     *format = GST_FORMAT_TIME;
1381
1382   return res;
1383 }
1384
1385 /* perform seek in push based mode:
1386    find BYTE position to move to based on time and delegate to upstream
1387 */
1388 static gboolean
1389 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1390 {
1391   gdouble rate;
1392   GstFormat format;
1393   GstSeekFlags flags;
1394   GstSeekType cur_type, stop_type;
1395   gint64 cur, stop, key_cur;
1396   gboolean res;
1397   gint64 byte_cur;
1398   gint64 original_stop;
1399   guint32 seqnum;
1400
1401   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1402
1403   gst_event_parse_seek (event, &rate, &format, &flags,
1404       &cur_type, &cur, &stop_type, &stop);
1405   seqnum = gst_event_get_seqnum (event);
1406
1407   /* only forward streaming and seeking is possible */
1408   if (rate <= 0)
1409     goto unsupported_seek;
1410
1411   /* convert to TIME if needed and possible */
1412   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1413           stop_type, &stop))
1414     goto no_format;
1415
1416   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1417    * the original stop position to use when upstream pushes the new segment
1418    * for this seek */
1419   original_stop = stop;
1420   stop = -1;
1421
1422   /* find reasonable corresponding BYTE position,
1423    * also try to mind about keyframes, since we can not go back a bit for them
1424    * later on */
1425   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1426
1427   if (byte_cur == -1)
1428     goto abort_seek;
1429
1430   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1431       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1432       stop);
1433
1434   GST_OBJECT_LOCK (qtdemux);
1435   qtdemux->seek_offset = byte_cur;
1436   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1437     qtdemux->push_seek_start = cur;
1438   } else {
1439     qtdemux->push_seek_start = key_cur;
1440   }
1441
1442   if (stop_type == GST_SEEK_TYPE_NONE) {
1443     qtdemux->push_seek_stop = qtdemux->segment.stop;
1444   } else {
1445     qtdemux->push_seek_stop = original_stop;
1446   }
1447   GST_OBJECT_UNLOCK (qtdemux);
1448
1449   /* BYTE seek event */
1450   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1451       stop_type, stop);
1452   gst_event_set_seqnum (event, seqnum);
1453   res = gst_pad_push_event (qtdemux->sinkpad, event);
1454
1455   return res;
1456
1457   /* ERRORS */
1458 abort_seek:
1459   {
1460     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1461         "seek aborted.");
1462     return FALSE;
1463   }
1464 unsupported_seek:
1465   {
1466     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1467     return FALSE;
1468   }
1469 no_format:
1470   {
1471     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1472     return FALSE;
1473   }
1474 }
1475
1476 /* perform the seek.
1477  *
1478  * We set all segment_indexes in the streams to unknown and
1479  * adjust the time_position to the desired position. this is enough
1480  * to trigger a segment switch in the streaming thread to start
1481  * streaming from the desired position.
1482  *
1483  * Keyframe seeking is a little more complicated when dealing with
1484  * segments. Ideally we want to move to the previous keyframe in
1485  * the segment but there might not be a keyframe in the segment. In
1486  * fact, none of the segments could contain a keyframe. We take a
1487  * practical approach: seek to the previous keyframe in the segment,
1488  * if there is none, seek to the beginning of the segment.
1489  *
1490  * Called with STREAM_LOCK
1491  */
1492 static gboolean
1493 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1494     guint32 seqnum, GstSeekFlags flags)
1495 {
1496   gint64 desired_offset;
1497   gint n;
1498
1499   desired_offset = segment->position;
1500
1501   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1502       GST_TIME_ARGS (desired_offset));
1503
1504   /* may not have enough fragmented info to do this adjustment,
1505    * and we can't scan (and probably should not) at this time with
1506    * possibly flushing upstream */
1507   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1508     gint64 min_offset;
1509
1510     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1511     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1512         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1513     desired_offset = min_offset;
1514   }
1515
1516   /* and set all streams to the final position */
1517   gst_flow_combiner_reset (qtdemux->flowcombiner);
1518   qtdemux->segment_seqnum = seqnum;
1519   for (n = 0; n < qtdemux->n_streams; n++) {
1520     QtDemuxStream *stream = qtdemux->streams[n];
1521
1522     stream->time_position = desired_offset;
1523     stream->accumulated_base = 0;
1524     stream->sample_index = -1;
1525     stream->offset_in_sample = 0;
1526     stream->segment_index = -1;
1527     stream->sent_eos = FALSE;
1528
1529     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1530       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1531   }
1532   segment->position = desired_offset;
1533   segment->time = desired_offset;
1534   if (segment->rate >= 0) {
1535     segment->start = desired_offset;
1536
1537     /* we stop at the end */
1538     if (segment->stop == -1)
1539       segment->stop = segment->duration;
1540   } else {
1541     segment->stop = desired_offset;
1542   }
1543
1544   if (qtdemux->fragmented)
1545     qtdemux->fragmented_seek_pending = TRUE;
1546
1547   return TRUE;
1548 }
1549
1550 /* do a seek in pull based mode */
1551 static gboolean
1552 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1553 {
1554   gdouble rate;
1555   GstFormat format;
1556   GstSeekFlags flags;
1557   GstSeekType cur_type, stop_type;
1558   gint64 cur, stop;
1559   gboolean flush;
1560   gboolean update;
1561   GstSegment seeksegment;
1562   guint32 seqnum = 0;
1563   GstEvent *flush_event;
1564
1565   if (event) {
1566     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1567
1568     gst_event_parse_seek (event, &rate, &format, &flags,
1569         &cur_type, &cur, &stop_type, &stop);
1570     seqnum = gst_event_get_seqnum (event);
1571
1572     /* we have to have a format as the segment format. Try to convert
1573      * if not. */
1574     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1575             stop_type, &stop))
1576       goto no_format;
1577
1578     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1579   } else {
1580     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1581     flags = 0;
1582   }
1583
1584   flush = flags & GST_SEEK_FLAG_FLUSH;
1585
1586   /* stop streaming, either by flushing or by pausing the task */
1587   if (flush) {
1588     flush_event = gst_event_new_flush_start ();
1589     if (seqnum)
1590       gst_event_set_seqnum (flush_event, seqnum);
1591     /* unlock upstream pull_range */
1592     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1593     /* make sure out loop function exits */
1594     gst_qtdemux_push_event (qtdemux, flush_event);
1595   } else {
1596     /* non flushing seek, pause the task */
1597     gst_pad_pause_task (qtdemux->sinkpad);
1598   }
1599
1600   /* wait for streaming to finish */
1601   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1602
1603   /* copy segment, we need this because we still need the old
1604    * segment when we close the current segment. */
1605   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1606
1607   if (event) {
1608     /* configure the segment with the seek variables */
1609     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1610     gst_segment_do_seek (&seeksegment, rate, format, flags,
1611         cur_type, cur, stop_type, stop, &update);
1612   }
1613
1614   /* now do the seek, this actually never returns FALSE */
1615   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1616
1617   /* prepare for streaming again */
1618   if (flush) {
1619     flush_event = gst_event_new_flush_stop (TRUE);
1620     if (seqnum)
1621       gst_event_set_seqnum (flush_event, seqnum);
1622
1623     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1624     gst_qtdemux_push_event (qtdemux, flush_event);
1625   }
1626
1627   /* commit the new segment */
1628   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1629
1630   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1631     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1632         qtdemux->segment.format, qtdemux->segment.position);
1633     if (seqnum)
1634       gst_message_set_seqnum (msg, seqnum);
1635     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1636   }
1637
1638   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1639   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1640       qtdemux->sinkpad, NULL);
1641
1642   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1643
1644   return TRUE;
1645
1646   /* ERRORS */
1647 no_format:
1648   {
1649     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1650     return FALSE;
1651   }
1652 }
1653
1654 static gboolean
1655 qtdemux_ensure_index (GstQTDemux * qtdemux)
1656 {
1657   guint i;
1658
1659   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1660
1661   /* Build complete index */
1662   for (i = 0; i < qtdemux->n_streams; i++) {
1663     QtDemuxStream *stream = qtdemux->streams[i];
1664
1665     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1666       goto parse_error;
1667   }
1668   return TRUE;
1669
1670   /* ERRORS */
1671 parse_error:
1672   {
1673     GST_LOG_OBJECT (qtdemux,
1674         "Building complete index of stream %u for seeking failed!", i);
1675     return FALSE;
1676   }
1677 }
1678
1679 static gboolean
1680 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1681     GstEvent * event)
1682 {
1683   gboolean res = TRUE;
1684   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1685
1686   switch (GST_EVENT_TYPE (event)) {
1687     case GST_EVENT_SEEK:
1688     {
1689 #ifndef GST_DISABLE_GST_DEBUG
1690       GstClockTime ts = gst_util_get_timestamp ();
1691 #endif
1692
1693       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1694         /* seek should be handled by upstream, we might need to re-download fragments */
1695         GST_DEBUG_OBJECT (qtdemux,
1696             "let upstream handle seek for fragmented playback");
1697         goto upstream;
1698       }
1699
1700       /* Build complete index for seeking;
1701        * if not a fragmented file at least */
1702       if (!qtdemux->fragmented)
1703         if (!qtdemux_ensure_index (qtdemux))
1704           goto index_failed;
1705 #ifndef GST_DISABLE_GST_DEBUG
1706       ts = gst_util_get_timestamp () - ts;
1707       GST_INFO_OBJECT (qtdemux,
1708           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1709 #endif
1710     }
1711       if (qtdemux->pullbased) {
1712         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1713       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1714         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1715         res = TRUE;
1716       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1717           && !qtdemux->fragmented) {
1718         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1719       } else {
1720         GST_DEBUG_OBJECT (qtdemux,
1721             "ignoring seek in push mode in current state");
1722         res = FALSE;
1723       }
1724       gst_event_unref (event);
1725       break;
1726     default:
1727     upstream:
1728       res = gst_pad_event_default (pad, parent, event);
1729       break;
1730   }
1731
1732 done:
1733   return res;
1734
1735   /* ERRORS */
1736 index_failed:
1737   {
1738     GST_ERROR_OBJECT (qtdemux, "Index failed");
1739     gst_event_unref (event);
1740     res = FALSE;
1741     goto done;
1742   }
1743 }
1744
1745 /* stream/index return sample that is min/max w.r.t. byte position,
1746  * time is min/max w.r.t. time of samples,
1747  * the latter need not be time of the former sample */
1748 static void
1749 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1750     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1751 {
1752   gint i, n, index;
1753   gint64 time, min_time;
1754   QtDemuxStream *stream;
1755
1756   min_time = -1;
1757   stream = NULL;
1758   index = -1;
1759
1760   for (n = 0; n < qtdemux->n_streams; ++n) {
1761     QtDemuxStream *str;
1762     gint inc;
1763     gboolean set_sample;
1764
1765     str = qtdemux->streams[n];
1766     set_sample = !set;
1767
1768     if (fw) {
1769       i = 0;
1770       inc = 1;
1771     } else {
1772       i = str->n_samples - 1;
1773       inc = -1;
1774     }
1775
1776     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1777       if (str->samples[i].size == 0)
1778         continue;
1779
1780       if (fw && (str->samples[i].offset < byte_pos))
1781         continue;
1782
1783       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1784         continue;
1785
1786       /* move stream to first available sample */
1787       if (set) {
1788         gst_qtdemux_move_stream (qtdemux, str, i);
1789         set_sample = TRUE;
1790       }
1791
1792       /* avoid index from sparse streams since they might be far away */
1793       if (!str->sparse) {
1794         /* determine min/max time */
1795         time = QTSAMPLE_PTS (str, &str->samples[i]);
1796         if (min_time == -1 || (!fw && time > min_time) ||
1797             (fw && time < min_time)) {
1798           min_time = time;
1799         }
1800
1801         /* determine stream with leading sample, to get its position */
1802         if (!stream ||
1803             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1804             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1805           stream = str;
1806           index = i;
1807         }
1808       }
1809       break;
1810     }
1811
1812     /* no sample for this stream, mark eos */
1813     if (!set_sample)
1814       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1815   }
1816
1817   if (_time)
1818     *_time = min_time;
1819   if (_stream)
1820     *_stream = stream;
1821   if (_index)
1822     *_index = index;
1823 }
1824
1825 static QtDemuxStream *
1826 _create_stream (void)
1827 {
1828   QtDemuxStream *stream;
1829
1830   stream = g_new0 (QtDemuxStream, 1);
1831   /* new streams always need a discont */
1832   stream->discont = TRUE;
1833   /* we enable clipping for raw audio/video streams */
1834   stream->need_clip = FALSE;
1835   stream->need_process = FALSE;
1836   stream->segment_index = -1;
1837   stream->time_position = 0;
1838   stream->sample_index = -1;
1839   stream->offset_in_sample = 0;
1840   stream->new_stream = TRUE;
1841   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1842   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1843   stream->protected = FALSE;
1844   stream->protection_scheme_type = 0;
1845   stream->protection_scheme_version = 0;
1846   stream->protection_scheme_info = NULL;
1847   stream->n_samples_moof = 0;
1848   stream->duration_moof = 0;
1849   stream->duration_last_moof = 0;
1850   g_queue_init (&stream->protection_scheme_event_queue);
1851   return stream;
1852 }
1853
1854 static gboolean
1855 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1856 {
1857   GstStructure *structure;
1858   const gchar *variant;
1859   const GstCaps *mediacaps = NULL;
1860
1861   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1862
1863   structure = gst_caps_get_structure (caps, 0);
1864   variant = gst_structure_get_string (structure, "variant");
1865
1866   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1867     QtDemuxStream *stream;
1868     const GValue *value;
1869
1870     demux->fragmented = TRUE;
1871     demux->mss_mode = TRUE;
1872
1873     if (demux->n_streams > 1) {
1874       /* can't do this, we can only renegotiate for another mss format */
1875       return FALSE;
1876     }
1877
1878     value = gst_structure_get_value (structure, "media-caps");
1879     /* create stream */
1880     if (value) {
1881       const GValue *timescale_v;
1882
1883       /* TODO update when stream changes during playback */
1884
1885       if (demux->n_streams == 0) {
1886         stream = _create_stream ();
1887         demux->streams[demux->n_streams] = stream;
1888         demux->n_streams = 1;
1889       } else {
1890         stream = demux->streams[0];
1891       }
1892
1893       timescale_v = gst_structure_get_value (structure, "timescale");
1894       if (timescale_v) {
1895         stream->timescale = g_value_get_uint64 (timescale_v);
1896       } else {
1897         /* default mss timescale */
1898         stream->timescale = 10000000;
1899       }
1900       demux->timescale = stream->timescale;
1901
1902       mediacaps = gst_value_get_caps (value);
1903       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1904         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1905             mediacaps);
1906         stream->new_caps = TRUE;
1907       }
1908       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1909       structure = gst_caps_get_structure (mediacaps, 0);
1910       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1911         stream->subtype = FOURCC_vide;
1912
1913         gst_structure_get_int (structure, "width", &stream->width);
1914         gst_structure_get_int (structure, "height", &stream->height);
1915         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1916             &stream->fps_d);
1917       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1918         gint rate = 0;
1919         stream->subtype = FOURCC_soun;
1920         gst_structure_get_int (structure, "channels", &stream->n_channels);
1921         gst_structure_get_int (structure, "rate", &rate);
1922         stream->rate = rate;
1923       }
1924     }
1925     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1926   } else {
1927     demux->mss_mode = FALSE;
1928   }
1929
1930   return TRUE;
1931 }
1932
1933 static void
1934 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1935 {
1936   gint n;
1937
1938   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1939   gst_pad_stop_task (qtdemux->sinkpad);
1940
1941   if (hard || qtdemux->upstream_format_is_time) {
1942     qtdemux->state = QTDEMUX_STATE_INITIAL;
1943     qtdemux->neededbytes = 16;
1944     qtdemux->todrop = 0;
1945     qtdemux->pullbased = FALSE;
1946     qtdemux->posted_redirect = FALSE;
1947     qtdemux->first_mdat = -1;
1948     qtdemux->header_size = 0;
1949     qtdemux->mdatoffset = -1;
1950     qtdemux->restoredata_offset = -1;
1951     if (qtdemux->mdatbuffer)
1952       gst_buffer_unref (qtdemux->mdatbuffer);
1953     if (qtdemux->restoredata_buffer)
1954       gst_buffer_unref (qtdemux->restoredata_buffer);
1955     qtdemux->mdatbuffer = NULL;
1956     qtdemux->restoredata_buffer = NULL;
1957     qtdemux->mdatleft = 0;
1958     if (qtdemux->comp_brands)
1959       gst_buffer_unref (qtdemux->comp_brands);
1960     qtdemux->comp_brands = NULL;
1961     qtdemux->last_moov_offset = -1;
1962     if (qtdemux->moov_node)
1963       g_node_destroy (qtdemux->moov_node);
1964     qtdemux->moov_node = NULL;
1965     qtdemux->moov_node_compressed = NULL;
1966     if (qtdemux->tag_list)
1967       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1968     qtdemux->tag_list = NULL;
1969 #if 0
1970     if (qtdemux->element_index)
1971       gst_object_unref (qtdemux->element_index);
1972     qtdemux->element_index = NULL;
1973 #endif
1974     qtdemux->major_brand = 0;
1975     if (qtdemux->pending_newsegment)
1976       gst_event_unref (qtdemux->pending_newsegment);
1977     qtdemux->pending_newsegment = NULL;
1978     qtdemux->upstream_format_is_time = FALSE;
1979     qtdemux->upstream_seekable = FALSE;
1980     qtdemux->upstream_size = 0;
1981
1982     qtdemux->fragment_start = -1;
1983     qtdemux->fragment_start_offset = -1;
1984     qtdemux->duration = 0;
1985     qtdemux->moof_offset = 0;
1986     qtdemux->chapters_track_id = 0;
1987     qtdemux->have_group_id = FALSE;
1988     qtdemux->group_id = G_MAXUINT;
1989
1990     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1991         NULL);
1992     g_queue_clear (&qtdemux->protection_event_queue);
1993   }
1994   qtdemux->offset = 0;
1995   gst_adapter_clear (qtdemux->adapter);
1996   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1997   qtdemux->segment_seqnum = 0;
1998
1999   if (hard) {
2000     for (n = 0; n < qtdemux->n_streams; n++) {
2001       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2002       qtdemux->streams[n] = NULL;
2003     }
2004     qtdemux->n_streams = 0;
2005     qtdemux->n_video_streams = 0;
2006     qtdemux->n_audio_streams = 0;
2007     qtdemux->n_sub_streams = 0;
2008     qtdemux->exposed = FALSE;
2009     qtdemux->fragmented = FALSE;
2010     qtdemux->mss_mode = FALSE;
2011     gst_caps_replace (&qtdemux->media_caps, NULL);
2012     qtdemux->timescale = 0;
2013     qtdemux->got_moov = FALSE;
2014     if (qtdemux->protection_system_ids) {
2015       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2016       qtdemux->protection_system_ids = NULL;
2017     }
2018   } else if (qtdemux->mss_mode) {
2019     gst_flow_combiner_reset (qtdemux->flowcombiner);
2020     for (n = 0; n < qtdemux->n_streams; n++)
2021       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2022   } else {
2023     gst_flow_combiner_reset (qtdemux->flowcombiner);
2024     for (n = 0; n < qtdemux->n_streams; n++) {
2025       qtdemux->streams[n]->sent_eos = FALSE;
2026       qtdemux->streams[n]->time_position = 0;
2027       qtdemux->streams[n]->accumulated_base = 0;
2028     }
2029     if (!qtdemux->pending_newsegment) {
2030       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2031       if (qtdemux->segment_seqnum)
2032         gst_event_set_seqnum (qtdemux->pending_newsegment,
2033             qtdemux->segment_seqnum);
2034     }
2035   }
2036 }
2037
2038
2039 /* Maps the @segment to the qt edts internal segments and pushes
2040  * the correspnding segment event.
2041  *
2042  * If it ends up being at a empty segment, a gap will be pushed and the next
2043  * edts segment will be activated in sequence.
2044  *
2045  * To be used in push-mode only */
2046 static void
2047 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2048 {
2049   gint n, i;
2050
2051   for (n = 0; n < qtdemux->n_streams; n++) {
2052     QtDemuxStream *stream = qtdemux->streams[n];
2053
2054     stream->time_position = segment->start;
2055
2056     /* in push mode we should be guaranteed that we will have empty segments
2057      * at the beginning and then one segment after, other scenarios are not
2058      * supported and are discarded when parsing the edts */
2059     for (i = 0; i < stream->n_segments; i++) {
2060       if (stream->segments[i].stop_time > segment->start) {
2061         gst_qtdemux_activate_segment (qtdemux, stream, i,
2062             stream->time_position);
2063         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2064           /* push the empty segment and move to the next one */
2065           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2066               stream->time_position);
2067           continue;
2068         }
2069
2070         g_assert (i == stream->n_segments - 1);
2071       }
2072     }
2073   }
2074 }
2075
2076 static gboolean
2077 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2078     GstEvent * event)
2079 {
2080   GstQTDemux *demux = GST_QTDEMUX (parent);
2081   gboolean res = TRUE;
2082
2083   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2084
2085   switch (GST_EVENT_TYPE (event)) {
2086     case GST_EVENT_SEGMENT:
2087     {
2088       gint64 offset = 0;
2089       QtDemuxStream *stream;
2090       gint idx;
2091       GstSegment segment;
2092
2093       /* some debug output */
2094       gst_event_copy_segment (event, &segment);
2095       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2096           &segment);
2097
2098       /* erase any previously set segment */
2099       gst_event_replace (&demux->pending_newsegment, NULL);
2100
2101       if (segment.format == GST_FORMAT_TIME) {
2102         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2103         gst_event_replace (&demux->pending_newsegment, event);
2104         demux->upstream_format_is_time = TRUE;
2105       } else {
2106         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2107             "not in time format");
2108
2109         /* chain will send initial newsegment after pads have been added */
2110         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2111           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2112           goto exit;
2113         }
2114       }
2115
2116       /* check if this matches a time seek we received previously
2117        * FIXME for backwards compatibility reasons we use the
2118        * seek_offset here to compare. In the future we might want to
2119        * change this to use the seqnum as it uniquely should identify
2120        * the segment that corresponds to the seek. */
2121       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2122           ", received segment offset %" G_GINT64_FORMAT,
2123           demux->seek_offset, segment.start);
2124       if (segment.format == GST_FORMAT_BYTES
2125           && demux->seek_offset == segment.start) {
2126         GST_OBJECT_LOCK (demux);
2127         offset = segment.start;
2128
2129         segment.format = GST_FORMAT_TIME;
2130         segment.start = demux->push_seek_start;
2131         segment.stop = demux->push_seek_stop;
2132         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2133             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2134             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2135         GST_OBJECT_UNLOCK (demux);
2136       }
2137
2138       /* we only expect a BYTE segment, e.g. following a seek */
2139       if (segment.format == GST_FORMAT_BYTES) {
2140         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2141           offset = segment.start;
2142
2143           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2144               NULL, (gint64 *) & segment.start);
2145           if ((gint64) segment.start < 0)
2146             segment.start = 0;
2147         }
2148         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2149           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2150               NULL, (gint64 *) & segment.stop);
2151           /* keyframe seeking should already arrange for start >= stop,
2152            * but make sure in other rare cases */
2153           segment.stop = MAX (segment.stop, segment.start);
2154         }
2155       } else if (segment.format == GST_FORMAT_TIME) {
2156         /* push all data on the adapter before starting this
2157          * new segment */
2158         gst_qtdemux_process_adapter (demux, TRUE);
2159       } else {
2160         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2161         goto exit;
2162       }
2163
2164       /* We shouldn't modify upstream driven TIME FORMAT segment */
2165       if (!demux->upstream_format_is_time) {
2166         /* accept upstream's notion of segment and distribute along */
2167         segment.format = GST_FORMAT_TIME;
2168         segment.position = segment.time = segment.start;
2169         segment.duration = demux->segment.duration;
2170         segment.base = gst_segment_to_running_time (&demux->segment,
2171             GST_FORMAT_TIME, demux->segment.position);
2172       }
2173
2174       gst_segment_copy_into (&segment, &demux->segment);
2175       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2176
2177       /* map segment to internal qt segments and push on each stream */
2178       if (demux->n_streams) {
2179         if (demux->fragmented) {
2180           GstEvent *segment_event = gst_event_new_segment (&segment);
2181
2182           gst_event_replace (&demux->pending_newsegment, NULL);
2183           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2184           gst_qtdemux_push_event (demux, segment_event);
2185         } else {
2186           gst_event_replace (&demux->pending_newsegment, NULL);
2187           gst_qtdemux_map_and_push_segments (demux, &segment);
2188         }
2189       }
2190
2191       /* clear leftover in current segment, if any */
2192       gst_adapter_clear (demux->adapter);
2193
2194       /* set up streaming thread */
2195       demux->offset = offset;
2196       if (demux->upstream_format_is_time) {
2197         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2198             "set values to restart reading from a new atom");
2199         demux->neededbytes = 16;
2200         demux->todrop = 0;
2201       } else {
2202         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2203             NULL);
2204         if (stream) {
2205           demux->todrop = stream->samples[idx].offset - offset;
2206           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2207         } else {
2208           /* set up for EOS */
2209           demux->neededbytes = -1;
2210           demux->todrop = 0;
2211         }
2212       }
2213     exit:
2214       gst_event_unref (event);
2215       res = TRUE;
2216       goto drop;
2217     }
2218     case GST_EVENT_FLUSH_START:
2219     {
2220       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2221         gst_event_unref (event);
2222         goto drop;
2223       }
2224       break;
2225     }
2226     case GST_EVENT_FLUSH_STOP:
2227     {
2228       guint64 dur;
2229
2230       dur = demux->segment.duration;
2231       gst_qtdemux_reset (demux, FALSE);
2232       demux->segment.duration = dur;
2233
2234       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2235         gst_event_unref (event);
2236         goto drop;
2237       }
2238       break;
2239     }
2240     case GST_EVENT_EOS:
2241       /* If we are in push mode, and get an EOS before we've seen any streams,
2242        * then error out - we have nowhere to send the EOS */
2243       if (!demux->pullbased) {
2244         gint i;
2245         gboolean has_valid_stream = FALSE;
2246         for (i = 0; i < demux->n_streams; i++) {
2247           if (demux->streams[i]->pad != NULL) {
2248             has_valid_stream = TRUE;
2249             break;
2250           }
2251         }
2252         if (!has_valid_stream)
2253           gst_qtdemux_post_no_playable_stream_error (demux);
2254         else {
2255           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2256               (guint) gst_adapter_available (demux->adapter));
2257           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2258             res = FALSE;
2259           }
2260         }
2261       }
2262       break;
2263     case GST_EVENT_CAPS:{
2264       GstCaps *caps = NULL;
2265
2266       gst_event_parse_caps (event, &caps);
2267       gst_qtdemux_setcaps (demux, caps);
2268       res = TRUE;
2269       gst_event_unref (event);
2270       goto drop;
2271     }
2272     case GST_EVENT_PROTECTION:
2273     {
2274       const gchar *system_id = NULL;
2275
2276       gst_event_parse_protection (event, &system_id, NULL, NULL);
2277       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2278           system_id);
2279       gst_qtdemux_append_protection_system_id (demux, system_id);
2280       /* save the event for later, for source pads that have not been created */
2281       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2282       /* send it to all pads that already exist */
2283       gst_qtdemux_push_event (demux, event);
2284       res = TRUE;
2285       goto drop;
2286     }
2287     default:
2288       break;
2289   }
2290
2291   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2292
2293 drop:
2294   return res;
2295 }
2296
2297 #if 0
2298 static void
2299 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2300 {
2301   GstQTDemux *demux = GST_QTDEMUX (element);
2302
2303   GST_OBJECT_LOCK (demux);
2304   if (demux->element_index)
2305     gst_object_unref (demux->element_index);
2306   if (index) {
2307     demux->element_index = gst_object_ref (index);
2308   } else {
2309     demux->element_index = NULL;
2310   }
2311   GST_OBJECT_UNLOCK (demux);
2312   /* object lock might be taken again */
2313   if (index)
2314     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2315   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2316       demux->element_index, demux->index_id);
2317 }
2318
2319 static GstIndex *
2320 gst_qtdemux_get_index (GstElement * element)
2321 {
2322   GstIndex *result = NULL;
2323   GstQTDemux *demux = GST_QTDEMUX (element);
2324
2325   GST_OBJECT_LOCK (demux);
2326   if (demux->element_index)
2327     result = gst_object_ref (demux->element_index);
2328   GST_OBJECT_UNLOCK (demux);
2329
2330   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2331
2332   return result;
2333 }
2334 #endif
2335
2336 static void
2337 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2338 {
2339   g_free ((gpointer) stream->stco.data);
2340   stream->stco.data = NULL;
2341   g_free ((gpointer) stream->stsz.data);
2342   stream->stsz.data = NULL;
2343   g_free ((gpointer) stream->stsc.data);
2344   stream->stsc.data = NULL;
2345   g_free ((gpointer) stream->stts.data);
2346   stream->stts.data = NULL;
2347   g_free ((gpointer) stream->stss.data);
2348   stream->stss.data = NULL;
2349   g_free ((gpointer) stream->stps.data);
2350   stream->stps.data = NULL;
2351   g_free ((gpointer) stream->ctts.data);
2352   stream->ctts.data = NULL;
2353 }
2354
2355 static void
2356 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2357     QtDemuxStream * stream)
2358 {
2359   g_free (stream->segments);
2360   stream->segments = NULL;
2361   stream->segment_index = -1;
2362   stream->accumulated_base = 0;
2363 }
2364
2365 static void
2366 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2367     QtDemuxStream * stream)
2368 {
2369   g_free (stream->samples);
2370   stream->samples = NULL;
2371   gst_qtdemux_stbl_free (stream);
2372
2373   /* fragments */
2374   g_free (stream->ra_entries);
2375   stream->ra_entries = NULL;
2376   stream->n_ra_entries = 0;
2377
2378   stream->sample_index = -1;
2379   stream->stbl_index = -1;
2380   stream->n_samples = 0;
2381   stream->time_position = 0;
2382
2383   stream->n_samples_moof = 0;
2384   stream->duration_moof = 0;
2385   stream->duration_last_moof = 0;
2386 }
2387
2388 static void
2389 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2390 {
2391   if (stream->allocator)
2392     gst_object_unref (stream->allocator);
2393   while (stream->buffers) {
2394     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2395     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2396   }
2397   if (stream->rgb8_palette) {
2398     gst_memory_unref (stream->rgb8_palette);
2399     stream->rgb8_palette = NULL;
2400   }
2401
2402   if (stream->pending_tags)
2403     gst_tag_list_unref (stream->pending_tags);
2404   stream->pending_tags = NULL;
2405   g_free (stream->redirect_uri);
2406   stream->redirect_uri = NULL;
2407   stream->sent_eos = FALSE;
2408   stream->sparse = FALSE;
2409   stream->protected = FALSE;
2410   if (stream->protection_scheme_info) {
2411     if (stream->protection_scheme_type == FOURCC_cenc) {
2412       QtDemuxCencSampleSetInfo *info =
2413           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2414       if (info->default_properties)
2415         gst_structure_free (info->default_properties);
2416       if (info->crypto_info)
2417         g_ptr_array_free (info->crypto_info, TRUE);
2418     }
2419     g_free (stream->protection_scheme_info);
2420     stream->protection_scheme_info = NULL;
2421   }
2422   stream->protection_scheme_type = 0;
2423   stream->protection_scheme_version = 0;
2424   g_queue_foreach (&stream->protection_scheme_event_queue,
2425       (GFunc) gst_event_unref, NULL);
2426   g_queue_clear (&stream->protection_scheme_event_queue);
2427   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2428   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2429 }
2430
2431 static void
2432 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2433 {
2434   gst_qtdemux_stream_clear (qtdemux, stream);
2435   if (stream->caps)
2436     gst_caps_unref (stream->caps);
2437   stream->caps = NULL;
2438   if (stream->pad) {
2439     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2440     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2441   }
2442   g_free (stream);
2443 }
2444
2445 static void
2446 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2447 {
2448   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2449
2450   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2451   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2452   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2453   qtdemux->n_streams--;
2454 }
2455
2456 static GstStateChangeReturn
2457 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2458 {
2459   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2460   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2461
2462   switch (transition) {
2463     case GST_STATE_CHANGE_PAUSED_TO_READY:
2464       break;
2465     default:
2466       break;
2467   }
2468
2469   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2470
2471   switch (transition) {
2472     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2473       gst_qtdemux_reset (qtdemux, TRUE);
2474       break;
2475     }
2476     default:
2477       break;
2478   }
2479
2480   return result;
2481 }
2482
2483 static void
2484 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2485 {
2486   /* counts as header data */
2487   qtdemux->header_size += length;
2488
2489   /* only consider at least a sufficiently complete ftyp atom */
2490   if (length >= 20) {
2491     GstBuffer *buf;
2492
2493     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2494     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2495         GST_FOURCC_ARGS (qtdemux->major_brand));
2496     if (qtdemux->comp_brands)
2497       gst_buffer_unref (qtdemux->comp_brands);
2498     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2499     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2500   }
2501 }
2502
2503 static void
2504 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2505     GstTagList * xmptaglist)
2506 {
2507   /* Strip out bogus fields */
2508   if (xmptaglist) {
2509     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2510       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2511       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2512     } else {
2513       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2514     }
2515
2516     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2517
2518     /* prioritize native tags using _KEEP mode */
2519     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2520     gst_tag_list_unref (xmptaglist);
2521   }
2522 }
2523
2524 static void
2525 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2526     guint offset)
2527 {
2528   GstByteReader br;
2529   guint8 version;
2530   guint32 flags = 0;
2531   guint i;
2532   guint8 iv_size = 8;
2533   QtDemuxStream *stream;
2534   GstStructure *structure;
2535   QtDemuxCencSampleSetInfo *ss_info = NULL;
2536   const gchar *system_id;
2537   gboolean uses_sub_sample_encryption = FALSE;
2538
2539   if (qtdemux->n_streams == 0)
2540     return;
2541
2542   stream = qtdemux->streams[0];
2543
2544   structure = gst_caps_get_structure (stream->caps, 0);
2545   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2546     GST_WARNING_OBJECT (qtdemux,
2547         "Attempting PIFF box parsing on an unencrypted stream.");
2548     return;
2549   }
2550
2551   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2552       G_TYPE_STRING, &system_id, NULL);
2553   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2554
2555   stream->protected = TRUE;
2556   stream->protection_scheme_type = FOURCC_cenc;
2557
2558   if (!stream->protection_scheme_info)
2559     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2560
2561   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2562
2563   if (ss_info->default_properties)
2564     gst_structure_free (ss_info->default_properties);
2565
2566   ss_info->default_properties =
2567       gst_structure_new ("application/x-cenc",
2568       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2569
2570   if (ss_info->crypto_info) {
2571     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2572     g_ptr_array_free (ss_info->crypto_info, TRUE);
2573     ss_info->crypto_info = NULL;
2574   }
2575
2576   /* skip UUID */
2577   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2578
2579   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2580     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2581     return;
2582   }
2583
2584   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2585     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2586     return;
2587   }
2588
2589   if ((flags & 0x000001)) {
2590     guint32 algorithm_id = 0;
2591     const guint8 *kid;
2592     GstBuffer *kid_buf;
2593     gboolean is_encrypted = TRUE;
2594
2595     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2596       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2597       return;
2598     }
2599
2600     algorithm_id >>= 8;
2601     if (algorithm_id == 0) {
2602       is_encrypted = FALSE;
2603     } else if (algorithm_id == 1) {
2604       /* FIXME: maybe store this in properties? */
2605       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2606     } else if (algorithm_id == 2) {
2607       /* FIXME: maybe store this in properties? */
2608       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2609     }
2610
2611     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2612       return;
2613
2614     if (!gst_byte_reader_get_data (&br, 16, &kid))
2615       return;
2616
2617     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2618     gst_buffer_fill (kid_buf, 0, kid, 16);
2619     if (ss_info->default_properties)
2620       gst_structure_free (ss_info->default_properties);
2621     ss_info->default_properties =
2622         gst_structure_new ("application/x-cenc",
2623         "iv_size", G_TYPE_UINT, iv_size,
2624         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2625         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2626     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2627         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2628     gst_buffer_unref (kid_buf);
2629   } else if ((flags & 0x000002)) {
2630     uses_sub_sample_encryption = TRUE;
2631   }
2632
2633   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2634     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2635     return;
2636   }
2637
2638   ss_info->crypto_info =
2639       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2640       (GDestroyNotify) qtdemux_gst_structure_free);
2641
2642   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2643     GstStructure *properties;
2644     guint8 *data;
2645     GstBuffer *buf;
2646
2647     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2648     if (properties == NULL) {
2649       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2650       return;
2651     }
2652
2653     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2654       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2655       gst_structure_free (properties);
2656       return;
2657     }
2658     buf = gst_buffer_new_wrapped (data, iv_size);
2659     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2660     gst_buffer_unref (buf);
2661
2662     if (uses_sub_sample_encryption) {
2663       guint16 n_subsamples;
2664
2665       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2666           || n_subsamples == 0) {
2667         GST_ERROR_OBJECT (qtdemux,
2668             "failed to get subsample count for sample %u", i);
2669         gst_structure_free (properties);
2670         return;
2671       }
2672       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2673       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2674         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2675             i);
2676         gst_structure_free (properties);
2677         return;
2678       }
2679       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2680       gst_structure_set (properties,
2681           "subsample_count", G_TYPE_UINT, n_subsamples,
2682           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2683       gst_buffer_unref (buf);
2684     } else {
2685       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2686     }
2687
2688     g_ptr_array_add (ss_info->crypto_info, properties);
2689   }
2690 }
2691
2692 static void
2693 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2694 {
2695   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2696     0x97, 0xA9, 0x42, 0xE8,
2697     0x9C, 0x71, 0x99, 0x94,
2698     0x91, 0xE3, 0xAF, 0xAC
2699   };
2700   static const guint8 playready_uuid[] = {
2701     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2702     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2703   };
2704
2705   static const guint8 piff_sample_encryption_uuid[] = {
2706     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2707     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2708   };
2709
2710   guint offset;
2711
2712   /* counts as header data */
2713   qtdemux->header_size += length;
2714
2715   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2716
2717   if (length <= offset + 16) {
2718     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2719     return;
2720   }
2721
2722   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2723     GstBuffer *buf;
2724     GstTagList *taglist;
2725
2726     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2727         length - offset - 16, NULL);
2728     taglist = gst_tag_list_from_xmp_buffer (buf);
2729     gst_buffer_unref (buf);
2730
2731     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2732
2733   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2734     int len;
2735     const gunichar2 *s_utf16;
2736     char *contents;
2737
2738     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2739     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2740     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2741     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2742
2743     g_free (contents);
2744
2745     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2746         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2747         (NULL));
2748   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2749     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2750   } else {
2751     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2752         GST_READ_UINT32_LE (buffer + offset),
2753         GST_READ_UINT32_LE (buffer + offset + 4),
2754         GST_READ_UINT32_LE (buffer + offset + 8),
2755         GST_READ_UINT32_LE (buffer + offset + 12));
2756   }
2757 }
2758
2759 static void
2760 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2761 {
2762   GstSidxParser sidx_parser;
2763   GstIsoffParserResult res;
2764   guint consumed;
2765
2766   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2767
2768   res =
2769       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2770       &consumed);
2771   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2772   if (res == GST_ISOFF_QT_PARSER_DONE) {
2773     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2774   }
2775   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2776 }
2777
2778 /* caller verifies at least 8 bytes in buf */
2779 static void
2780 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2781     guint64 * plength, guint32 * pfourcc)
2782 {
2783   guint64 length;
2784   guint32 fourcc;
2785
2786   length = QT_UINT32 (data);
2787   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2788   fourcc = QT_FOURCC (data + 4);
2789   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2790
2791   if (length == 0) {
2792     length = G_MAXUINT64;
2793   } else if (length == 1 && size >= 16) {
2794     /* this means we have an extended size, which is the 64 bit value of
2795      * the next 8 bytes */
2796     length = QT_UINT64 (data + 8);
2797     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2798   }
2799
2800   if (plength)
2801     *plength = length;
2802   if (pfourcc)
2803     *pfourcc = fourcc;
2804 }
2805
2806 static gboolean
2807 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2808 {
2809   guint32 version = 0;
2810   GstClockTime duration = 0;
2811
2812   if (!gst_byte_reader_get_uint32_be (br, &version))
2813     goto failed;
2814
2815   version >>= 24;
2816   if (version == 1) {
2817     if (!gst_byte_reader_get_uint64_be (br, &duration))
2818       goto failed;
2819   } else {
2820     guint32 dur = 0;
2821
2822     if (!gst_byte_reader_get_uint32_be (br, &dur))
2823       goto failed;
2824     duration = dur;
2825   }
2826
2827   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2828   qtdemux->duration = duration;
2829
2830   return TRUE;
2831
2832 failed:
2833   {
2834     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2835     return FALSE;
2836   }
2837 }
2838
2839 static gboolean
2840 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2841     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2842 {
2843   if (!stream->parsed_trex && qtdemux->moov_node) {
2844     GNode *mvex, *trex;
2845     GstByteReader trex_data;
2846
2847     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2848     if (mvex) {
2849       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2850           &trex_data);
2851       while (trex) {
2852         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2853
2854         /* skip version/flags */
2855         if (!gst_byte_reader_skip (&trex_data, 4))
2856           goto next;
2857         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2858           goto next;
2859         if (id != stream->track_id)
2860           goto next;
2861         /* sample description index; ignore */
2862         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2863           goto next;
2864         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2865           goto next;
2866         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2867           goto next;
2868         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2869           goto next;
2870
2871         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2872             "duration %d,  size %d, flags 0x%x", stream->track_id,
2873             dur, size, flags);
2874
2875         stream->parsed_trex = TRUE;
2876         stream->def_sample_duration = dur;
2877         stream->def_sample_size = size;
2878         stream->def_sample_flags = flags;
2879
2880       next:
2881         /* iterate all siblings */
2882         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2883             &trex_data);
2884       }
2885     }
2886   }
2887
2888   *ds_duration = stream->def_sample_duration;
2889   *ds_size = stream->def_sample_size;
2890   *ds_flags = stream->def_sample_flags;
2891
2892   /* even then, above values are better than random ... */
2893   if (G_UNLIKELY (!stream->parsed_trex)) {
2894     GST_WARNING_OBJECT (qtdemux,
2895         "failed to find fragment defaults for stream %d", stream->track_id);
2896     return FALSE;
2897   }
2898
2899   return TRUE;
2900 }
2901
2902 /* This method should be called whenever a more accurate duration might
2903  * have been found. It will update all relevant variables if/where needed
2904  */
2905 static void
2906 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2907 {
2908   guint i;
2909   guint64 movdur;
2910   GstClockTime prevdur;
2911
2912   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2913
2914   if (movdur > qtdemux->duration) {
2915     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2916     GST_DEBUG_OBJECT (qtdemux,
2917         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2918         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2919     qtdemux->duration = movdur;
2920     GST_DEBUG_OBJECT (qtdemux,
2921         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2922         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2923         GST_TIME_ARGS (qtdemux->segment.stop));
2924     if (qtdemux->segment.duration == prevdur) {
2925       /* If the current segment has duration/stop identical to previous duration
2926        * update them also (because they were set at that point in time with
2927        * the wrong duration */
2928       /* We convert the value *from* the timescale version to avoid rounding errors */
2929       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2930       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2931       qtdemux->segment.duration = fixeddur;
2932       qtdemux->segment.stop = fixeddur;
2933     }
2934   }
2935   for (i = 0; i < qtdemux->n_streams; i++) {
2936     QtDemuxStream *stream = qtdemux->streams[i];
2937     if (stream) {
2938       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2939       if (movdur > stream->duration) {
2940         GST_DEBUG_OBJECT (qtdemux,
2941             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2942             GST_TIME_ARGS (duration));
2943         stream->duration = movdur;
2944         if (stream->dummy_segment) {
2945           /* Update all dummy values to new duration */
2946           stream->segments[0].stop_time = duration;
2947           stream->segments[0].duration = duration;
2948           stream->segments[0].media_stop = duration;
2949
2950           /* let downstream know we possibly have a new stop time */
2951           if (stream->segment_index != -1) {
2952             GstClockTime pos;
2953
2954             if (qtdemux->segment.rate >= 0) {
2955               pos = stream->segment.start;
2956             } else {
2957               pos = stream->segment.stop;
2958             }
2959
2960             gst_qtdemux_stream_update_segment (qtdemux, stream,
2961                 stream->segment_index, pos, NULL, NULL);
2962           }
2963         }
2964       }
2965     }
2966   }
2967 }
2968
2969 static gboolean
2970 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2971     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2972     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2973     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2974 {
2975   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2976   guint64 timestamp;
2977   gint32 data_offset = 0;
2978   guint32 flags = 0, first_flags = 0, samples_count = 0;
2979   gint i;
2980   guint8 *data;
2981   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2982   QtDemuxSample *sample;
2983   gboolean ismv = FALSE;
2984   gint64 initial_offset;
2985
2986   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2987       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2988       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2989       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2990
2991   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2992     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2993     return TRUE;
2994   }
2995
2996   /* presence of stss or not can't really tell us much,
2997    * and flags and so on tend to be marginally reliable in these files */
2998   if (stream->subtype == FOURCC_soun) {
2999     GST_DEBUG_OBJECT (qtdemux,
3000         "sound track in fragmented file; marking all keyframes");
3001     stream->all_keyframe = TRUE;
3002   }
3003
3004   if (!gst_byte_reader_skip (trun, 1) ||
3005       !gst_byte_reader_get_uint24_be (trun, &flags))
3006     goto fail;
3007
3008   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3009     goto fail;
3010
3011   if (flags & TR_DATA_OFFSET) {
3012     /* note this is really signed */
3013     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3014       goto fail;
3015     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3016     /* default base offset = first byte of moof */
3017     if (*base_offset == -1) {
3018       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3019       *base_offset = moof_offset;
3020     }
3021     *running_offset = *base_offset + data_offset;
3022   } else {
3023     /* if no offset at all, that would mean data starts at moof start,
3024      * which is a bit wrong and is ismv crappy way, so compensate
3025      * assuming data is in mdat following moof */
3026     if (*base_offset == -1) {
3027       *base_offset = moof_offset + moof_length + 8;
3028       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3029       ismv = TRUE;
3030     }
3031     if (*running_offset == -1)
3032       *running_offset = *base_offset;
3033   }
3034
3035   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3036       *running_offset);
3037   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3038       data_offset, flags, samples_count);
3039
3040   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3041     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3042       GST_DEBUG_OBJECT (qtdemux,
3043           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3044       flags ^= TR_FIRST_SAMPLE_FLAGS;
3045     } else {
3046       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3047         goto fail;
3048       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3049     }
3050   }
3051
3052   /* FIXME ? spec says other bits should also be checked to determine
3053    * entry size (and prefix size for that matter) */
3054   entry_size = 0;
3055   dur_offset = size_offset = 0;
3056   if (flags & TR_SAMPLE_DURATION) {
3057     GST_LOG_OBJECT (qtdemux, "entry duration present");
3058     dur_offset = entry_size;
3059     entry_size += 4;
3060   }
3061   if (flags & TR_SAMPLE_SIZE) {
3062     GST_LOG_OBJECT (qtdemux, "entry size present");
3063     size_offset = entry_size;
3064     entry_size += 4;
3065   }
3066   if (flags & TR_SAMPLE_FLAGS) {
3067     GST_LOG_OBJECT (qtdemux, "entry flags present");
3068     flags_offset = entry_size;
3069     entry_size += 4;
3070   }
3071   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3072     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3073     ct_offset = entry_size;
3074     entry_size += 4;
3075   }
3076
3077   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3078     goto fail;
3079   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3080
3081   if (stream->n_samples + samples_count >=
3082       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3083     goto index_too_big;
3084
3085   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3086       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3087       (stream->n_samples + samples_count) *
3088       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3089
3090   /* create a new array of samples if it's the first sample parsed */
3091   if (stream->n_samples == 0) {
3092     g_assert (stream->samples == NULL);
3093     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3094     /* or try to reallocate it with space enough to insert the new samples */
3095   } else
3096     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3097         stream->n_samples + samples_count);
3098   if (stream->samples == NULL)
3099     goto out_of_memory;
3100
3101   if (qtdemux->fragment_start != -1) {
3102     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3103     qtdemux->fragment_start = -1;
3104   } else {
3105     if (stream->n_samples == 0) {
3106       if (decode_ts > 0) {
3107         timestamp = decode_ts;
3108       } else if (stream->pending_seek != NULL) {
3109         /* if we don't have a timestamp from a tfdt box, we'll use the one
3110          * from the mfra seek table */
3111         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3112             GST_TIME_ARGS (stream->pending_seek->ts));
3113
3114         /* FIXME: this is not fully correct, the timestamp refers to the random
3115          * access sample refered to in the tfra entry, which may not necessarily
3116          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3117         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3118       } else {
3119         timestamp = 0;
3120       }
3121
3122       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3123       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3124           GST_TIME_ARGS (gst_ts));
3125     } else {
3126       /* subsequent fragments extend stream */
3127       timestamp =
3128           stream->samples[stream->n_samples - 1].timestamp +
3129           stream->samples[stream->n_samples - 1].duration;
3130
3131       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3132        * difference (1 sec.) between decode_ts and timestamp, prefer the
3133        * former */
3134       if (!qtdemux->upstream_format_is_time
3135           && ABSDIFF (decode_ts, timestamp) >
3136           MAX (stream->duration_last_moof / 2,
3137               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3138         GST_INFO_OBJECT (qtdemux,
3139             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3140             ") are significantly different (more than %" GST_TIME_FORMAT
3141             "), using decode_ts",
3142             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3143             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3144             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3145                     MAX (stream->duration_last_moof / 2,
3146                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3147         timestamp = decode_ts;
3148       }
3149
3150       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3151       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3152           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3153     }
3154   }
3155
3156   initial_offset = *running_offset;
3157
3158   sample = stream->samples + stream->n_samples;
3159   for (i = 0; i < samples_count; i++) {
3160     guint32 dur, size, sflags, ct;
3161
3162     /* first read sample data */
3163     if (flags & TR_SAMPLE_DURATION) {
3164       dur = QT_UINT32 (data + dur_offset);
3165     } else {
3166       dur = d_sample_duration;
3167     }
3168     if (flags & TR_SAMPLE_SIZE) {
3169       size = QT_UINT32 (data + size_offset);
3170     } else {
3171       size = d_sample_size;
3172     }
3173     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3174       if (i == 0) {
3175         sflags = first_flags;
3176       } else {
3177         sflags = d_sample_flags;
3178       }
3179     } else if (flags & TR_SAMPLE_FLAGS) {
3180       sflags = QT_UINT32 (data + flags_offset);
3181     } else {
3182       sflags = d_sample_flags;
3183     }
3184     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3185       ct = QT_UINT32 (data + ct_offset);
3186     } else {
3187       ct = 0;
3188     }
3189     data += entry_size;
3190
3191     /* fill the sample information */
3192     sample->offset = *running_offset;
3193     sample->pts_offset = ct;
3194     sample->size = size;
3195     sample->timestamp = timestamp;
3196     sample->duration = dur;
3197     /* sample-is-difference-sample */
3198     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3199      * now idea how it relates to bitfield other than massive LE/BE confusion */
3200     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3201     *running_offset += size;
3202     timestamp += dur;
3203     stream->duration_moof += dur;
3204     sample++;
3205   }
3206
3207   /* Update total duration if needed */
3208   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3209
3210   /* Pre-emptively figure out size of mdat based on trun information.
3211    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3212    * size, else we will still be able to use this when dealing with gap'ed
3213    * input */
3214   qtdemux->mdatleft = *running_offset - initial_offset;
3215
3216   stream->n_samples += samples_count;
3217   stream->n_samples_moof += samples_count;
3218
3219   if (stream->pending_seek != NULL)
3220     stream->pending_seek = NULL;
3221
3222   return TRUE;
3223
3224 fail:
3225   {
3226     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3227     return FALSE;
3228   }
3229 out_of_memory:
3230   {
3231     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3232         stream->n_samples);
3233     return FALSE;
3234   }
3235 index_too_big:
3236   {
3237     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3238         "be larger than %uMB (broken file?)", stream->n_samples,
3239         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3240     return FALSE;
3241   }
3242 }
3243
3244 /* find stream with @id */
3245 static inline QtDemuxStream *
3246 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3247 {
3248   QtDemuxStream *stream;
3249   gint i;
3250
3251   /* check */
3252   if (G_UNLIKELY (!id)) {
3253     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3254     return NULL;
3255   }
3256
3257   /* try to get it fast and simple */
3258   if (G_LIKELY (id <= qtdemux->n_streams)) {
3259     stream = qtdemux->streams[id - 1];
3260     if (G_LIKELY (stream->track_id == id))
3261       return stream;
3262   }
3263
3264   /* linear search otherwise */
3265   for (i = 0; i < qtdemux->n_streams; i++) {
3266     stream = qtdemux->streams[i];
3267     if (stream->track_id == id)
3268       return stream;
3269   }
3270   if (qtdemux->mss_mode) {
3271     /* mss should have only 1 stream anyway */
3272     return qtdemux->streams[0];
3273   }
3274
3275   return NULL;
3276 }
3277
3278 static gboolean
3279 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3280     guint32 * fragment_number)
3281 {
3282   if (!gst_byte_reader_skip (mfhd, 4))
3283     goto fail;
3284   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3285     goto fail;
3286   return TRUE;
3287 fail:
3288   {
3289     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3290     return FALSE;
3291   }
3292 }
3293
3294 static gboolean
3295 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3296     QtDemuxStream ** stream, guint32 * default_sample_duration,
3297     guint32 * default_sample_size, guint32 * default_sample_flags,
3298     gint64 * base_offset)
3299 {
3300   guint32 flags = 0;
3301   guint32 track_id = 0;
3302
3303   if (!gst_byte_reader_skip (tfhd, 1) ||
3304       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3305     goto invalid_track;
3306
3307   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3308     goto invalid_track;
3309
3310   *stream = qtdemux_find_stream (qtdemux, track_id);
3311   if (G_UNLIKELY (!*stream))
3312     goto unknown_stream;
3313
3314   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3315     *base_offset = qtdemux->moof_offset;
3316
3317   if (flags & TF_BASE_DATA_OFFSET)
3318     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3319       goto invalid_track;
3320
3321   /* obtain stream defaults */
3322   qtdemux_parse_trex (qtdemux, *stream,
3323       default_sample_duration, default_sample_size, default_sample_flags);
3324
3325   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3326   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3327     if (!gst_byte_reader_skip (tfhd, 4))
3328       goto invalid_track;
3329
3330   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3331     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3332       goto invalid_track;
3333
3334   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3335     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3336       goto invalid_track;
3337
3338   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3339     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3340       goto invalid_track;
3341
3342   return TRUE;
3343
3344 invalid_track:
3345   {
3346     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3347     return FALSE;
3348   }
3349 unknown_stream:
3350   {
3351     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3352     return TRUE;
3353   }
3354 }
3355
3356 static gboolean
3357 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3358     guint64 * decode_time)
3359 {
3360   guint32 version = 0;
3361
3362   if (!gst_byte_reader_get_uint32_be (br, &version))
3363     return FALSE;
3364
3365   version >>= 24;
3366   if (version == 1) {
3367     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3368       goto failed;
3369   } else {
3370     guint32 dec_time = 0;
3371     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3372       goto failed;
3373     *decode_time = dec_time;
3374   }
3375
3376   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3377       *decode_time);
3378
3379   return TRUE;
3380
3381 failed:
3382   {
3383     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3384     return FALSE;
3385   }
3386 }
3387
3388 /* Returns a pointer to a GstStructure containing the properties of
3389  * the stream sample identified by @sample_index. The caller must unref
3390  * the returned object after use. Returns NULL if unsuccessful. */
3391 static GstStructure *
3392 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3393     QtDemuxStream * stream, guint sample_index)
3394 {
3395   QtDemuxCencSampleSetInfo *info = NULL;
3396
3397   g_return_val_if_fail (stream != NULL, NULL);
3398   g_return_val_if_fail (stream->protected, NULL);
3399   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3400
3401   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3402
3403   /* Currently, cenc properties for groups of samples are not supported, so
3404    * simply return a copy of the default sample properties */
3405   return gst_structure_copy (info->default_properties);
3406 }
3407
3408 /* Parses the sizes of sample auxiliary information contained within a stream,
3409  * as given in a saiz box. Returns array of sample_count guint8 size values,
3410  * or NULL on failure */
3411 static guint8 *
3412 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3413     GstByteReader * br, guint32 * sample_count)
3414 {
3415   guint32 flags = 0;
3416   guint8 *info_sizes;
3417   guint8 default_info_size;
3418
3419   g_return_val_if_fail (qtdemux != NULL, NULL);
3420   g_return_val_if_fail (stream != NULL, NULL);
3421   g_return_val_if_fail (br != NULL, NULL);
3422   g_return_val_if_fail (sample_count != NULL, NULL);
3423
3424   if (!gst_byte_reader_get_uint32_be (br, &flags))
3425     return NULL;
3426
3427   if (flags & 0x1) {
3428     /* aux_info_type and aux_info_type_parameter are ignored */
3429     if (!gst_byte_reader_skip (br, 8))
3430       return NULL;
3431   }
3432
3433   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3434     return NULL;
3435   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3436
3437   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3438     return NULL;
3439   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3440
3441
3442   if (default_info_size == 0) {
3443     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3444       return NULL;
3445     }
3446   } else {
3447     info_sizes = g_new (guint8, *sample_count);
3448     memset (info_sizes, default_info_size, *sample_count);
3449   }
3450
3451   return info_sizes;
3452 }
3453
3454 /* Parses the offset of sample auxiliary information contained within a stream,
3455  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3456 static gboolean
3457 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3458     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3459     guint64 * offset)
3460 {
3461   guint8 version = 0;
3462   guint32 flags = 0;
3463   guint32 aux_info_type = 0;
3464   guint32 aux_info_type_parameter = 0;
3465   guint32 entry_count;
3466   guint32 off_32;
3467   guint64 off_64;
3468   const guint8 *aux_info_type_data = NULL;
3469
3470   g_return_val_if_fail (qtdemux != NULL, FALSE);
3471   g_return_val_if_fail (stream != NULL, FALSE);
3472   g_return_val_if_fail (br != NULL, FALSE);
3473   g_return_val_if_fail (offset != NULL, FALSE);
3474
3475   if (!gst_byte_reader_get_uint8 (br, &version))
3476     return FALSE;
3477
3478   if (!gst_byte_reader_get_uint24_be (br, &flags))
3479     return FALSE;
3480
3481   if (flags & 0x1) {
3482
3483     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3484       return FALSE;
3485     aux_info_type = QT_FOURCC (aux_info_type_data);
3486
3487     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3488       return FALSE;
3489   } else if (stream->protected) {
3490     aux_info_type = stream->protection_scheme_type;
3491   } else {
3492     aux_info_type = stream->fourcc;
3493   }
3494
3495   if (info_type)
3496     *info_type = aux_info_type;
3497   if (info_type_parameter)
3498     *info_type_parameter = aux_info_type_parameter;
3499
3500   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3501       "aux_info_type_parameter:  %#06x",
3502       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3503
3504   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3505     return FALSE;
3506
3507   if (entry_count != 1) {
3508     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3509     return FALSE;
3510   }
3511
3512   if (version == 0) {
3513     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3514       return FALSE;
3515     *offset = (guint64) off_32;
3516   } else {
3517     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3518       return FALSE;
3519     *offset = off_64;
3520   }
3521
3522   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3523   return TRUE;
3524 }
3525
3526 static void
3527 qtdemux_gst_structure_free (GstStructure * gststructure)
3528 {
3529   if (gststructure) {
3530     gst_structure_free (gststructure);
3531   }
3532 }
3533
3534 /* Parses auxiliary information relating to samples protected using Common
3535  * Encryption (cenc); the format of this information is defined in
3536  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3537 static gboolean
3538 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3539     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3540 {
3541   QtDemuxCencSampleSetInfo *ss_info = NULL;
3542   guint8 size;
3543   gint i;
3544
3545   g_return_val_if_fail (qtdemux != NULL, FALSE);
3546   g_return_val_if_fail (stream != NULL, FALSE);
3547   g_return_val_if_fail (br != NULL, FALSE);
3548   g_return_val_if_fail (stream->protected, FALSE);
3549   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3550
3551   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3552
3553   if (ss_info->crypto_info) {
3554     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3555     g_ptr_array_free (ss_info->crypto_info, TRUE);
3556   }
3557
3558   ss_info->crypto_info =
3559       g_ptr_array_new_full (sample_count,
3560       (GDestroyNotify) qtdemux_gst_structure_free);
3561
3562   for (i = 0; i < sample_count; ++i) {
3563     GstStructure *properties;
3564     guint16 n_subsamples = 0;
3565     guint8 *data;
3566     guint iv_size;
3567     GstBuffer *buf;
3568
3569     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3570     if (properties == NULL) {
3571       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3572       return FALSE;
3573     }
3574     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3575       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3576       gst_structure_free (properties);
3577       return FALSE;
3578     }
3579     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3580       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3581       gst_structure_free (properties);
3582       return FALSE;
3583     }
3584     buf = gst_buffer_new_wrapped (data, iv_size);
3585     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3586     gst_buffer_unref (buf);
3587     size = info_sizes[i];
3588     if (size > iv_size) {
3589       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3590           || !(n_subsamples > 0)) {
3591         gst_structure_free (properties);
3592         GST_ERROR_OBJECT (qtdemux,
3593             "failed to get subsample count for sample %u", i);
3594         return FALSE;
3595       }
3596       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3597       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3598         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3599             i);
3600         gst_structure_free (properties);
3601         return FALSE;
3602       }
3603       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3604       if (!buf) {
3605         gst_structure_free (properties);
3606         return FALSE;
3607       }
3608       gst_structure_set (properties,
3609           "subsample_count", G_TYPE_UINT, n_subsamples,
3610           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3611       gst_buffer_unref (buf);
3612     } else {
3613       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3614     }
3615     g_ptr_array_add (ss_info->crypto_info, properties);
3616   }
3617   return TRUE;
3618 }
3619
3620 /* Converts a UUID in raw byte form to a string representation, as defined in
3621  * RFC 4122. The caller takes ownership of the returned string and is
3622  * responsible for freeing it after use. */
3623 static gchar *
3624 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3625 {
3626   const guint8 *uuid = (const guint8 *) uuid_bytes;
3627
3628   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3629       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3630       uuid[0], uuid[1], uuid[2], uuid[3],
3631       uuid[4], uuid[5], uuid[6], uuid[7],
3632       uuid[8], uuid[9], uuid[10], uuid[11],
3633       uuid[12], uuid[13], uuid[14], uuid[15]);
3634 }
3635
3636 /* Parses a Protection System Specific Header box (pssh), as defined in the
3637  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3638  * information needed by a specific content protection system in order to
3639  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3640  * otherwise. */
3641 static gboolean
3642 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3643 {
3644   gchar *sysid_string;
3645   guint32 pssh_size = QT_UINT32 (node->data);
3646   GstBuffer *pssh = NULL;
3647   GstEvent *event = NULL;
3648   guint32 parent_box_type;
3649   gint i;
3650
3651   if (G_UNLIKELY (pssh_size < 32U)) {
3652     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3653     return FALSE;
3654   }
3655
3656   sysid_string =
3657       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3658
3659   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3660
3661   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3662   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3663       gst_buffer_get_size (pssh));
3664
3665   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3666
3667   /* Push an event containing the pssh box onto the queues of all streams. */
3668   event = gst_event_new_protection (sysid_string, pssh,
3669       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3670   for (i = 0; i < qtdemux->n_streams; ++i) {
3671     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3672         gst_event_ref (event));
3673   }
3674   g_free (sysid_string);
3675   gst_event_unref (event);
3676   gst_buffer_unref (pssh);
3677   return TRUE;
3678 }
3679
3680 static gboolean
3681 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3682     guint64 moof_offset, QtDemuxStream * stream)
3683 {
3684   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3685   GNode *uuid_node;
3686   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3687   GNode *saiz_node, *saio_node, *pssh_node;
3688   GstByteReader saiz_data, saio_data;
3689   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3690   gint64 base_offset, running_offset;
3691   guint32 frag_num;
3692
3693   /* NOTE @stream ignored */
3694
3695   moof_node = g_node_new ((guint8 *) buffer);
3696   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3697   qtdemux_node_dump (qtdemux, moof_node);
3698
3699   /* Get fragment number from mfhd and check it's valid */
3700   mfhd_node =
3701       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3702   if (mfhd_node == NULL)
3703     goto missing_mfhd;
3704   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3705     goto fail;
3706   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3707
3708   /* unknown base_offset to start with */
3709   base_offset = running_offset = -1;
3710   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3711   while (traf_node) {
3712     guint64 decode_time = 0;
3713
3714     /* Fragment Header node */
3715     tfhd_node =
3716         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3717         &tfhd_data);
3718     if (!tfhd_node)
3719       goto missing_tfhd;
3720     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3721             &ds_size, &ds_flags, &base_offset))
3722       goto missing_tfhd;
3723
3724     /* The following code assumes at most a single set of sample auxiliary
3725      * data in the fragment (consisting of a saiz box and a corresponding saio
3726      * box); in theory, however, there could be multiple sets of sample
3727      * auxiliary data in a fragment. */
3728     saiz_node =
3729         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3730         &saiz_data);
3731     if (saiz_node) {
3732       guint32 info_type = 0;
3733       guint64 offset = 0;
3734       guint32 info_type_parameter = 0;
3735
3736       g_free (qtdemux->cenc_aux_info_sizes);
3737
3738       qtdemux->cenc_aux_info_sizes =
3739           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3740           &qtdemux->cenc_aux_sample_count);
3741       if (qtdemux->cenc_aux_info_sizes == NULL) {
3742         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3743         goto fail;
3744       }
3745       saio_node =
3746           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3747           &saio_data);
3748       if (!saio_node) {
3749         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3750         g_free (qtdemux->cenc_aux_info_sizes);
3751         qtdemux->cenc_aux_info_sizes = NULL;
3752         goto fail;
3753       }
3754
3755       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3756                   &info_type, &info_type_parameter, &offset))) {
3757         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3758         g_free (qtdemux->cenc_aux_info_sizes);
3759         qtdemux->cenc_aux_info_sizes = NULL;
3760         goto fail;
3761       }
3762       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3763         offset += (guint64) (base_offset - qtdemux->moof_offset);
3764       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3765         GstByteReader br;
3766         if (offset > length) {
3767           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3768           qtdemux->cenc_aux_info_offset = offset;
3769         } else {
3770           gst_byte_reader_init (&br, buffer + offset, length - offset);
3771           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3772                   qtdemux->cenc_aux_info_sizes,
3773                   qtdemux->cenc_aux_sample_count)) {
3774             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3775             g_free (qtdemux->cenc_aux_info_sizes);
3776             qtdemux->cenc_aux_info_sizes = NULL;
3777             goto fail;
3778           }
3779         }
3780       }
3781     }
3782
3783     tfdt_node =
3784         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3785         &tfdt_data);
3786     if (tfdt_node) {
3787       /* We'll use decode_time to interpolate timestamps
3788        * in case the input timestamps are missing */
3789       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3790
3791       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3792           " (%" GST_TIME_FORMAT ")", decode_time,
3793           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3794
3795       /* Discard the fragment buffer timestamp info to avoid using it.
3796        * Rely on tfdt instead as it is more accurate than the timestamp
3797        * that is fetched from a manifest/playlist and is usually
3798        * less accurate. */
3799       qtdemux->fragment_start = -1;
3800     }
3801
3802     if (G_UNLIKELY (!stream)) {
3803       /* we lost track of offset, we'll need to regain it,
3804        * but can delay complaining until later or avoid doing so altogether */
3805       base_offset = -2;
3806       goto next;
3807     }
3808     if (G_UNLIKELY (base_offset < -1))
3809       goto lost_offset;
3810
3811     if (qtdemux->upstream_format_is_time)
3812       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3813
3814     /* initialise moof sample data */
3815     stream->n_samples_moof = 0;
3816     stream->duration_last_moof = stream->duration_moof;
3817     stream->duration_moof = 0;
3818
3819     /* Track Run node */
3820     trun_node =
3821         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3822         &trun_data);
3823     while (trun_node) {
3824       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3825           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3826           &running_offset, decode_time);
3827       /* iterate all siblings */
3828       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3829           &trun_data);
3830     }
3831
3832     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3833     if (uuid_node) {
3834       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3835       guint32 box_length = QT_UINT32 (uuid_buffer);
3836
3837       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3838     }
3839
3840     /* if no new base_offset provided for next traf,
3841      * base is end of current traf */
3842     base_offset = running_offset;
3843     running_offset = -1;
3844
3845     if (stream->n_samples_moof && stream->duration_moof)
3846       stream->new_caps = TRUE;
3847
3848   next:
3849     /* iterate all siblings */
3850     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3851   }
3852
3853   /* parse any protection system info */
3854   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3855   while (pssh_node) {
3856     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3857     qtdemux_parse_pssh (qtdemux, pssh_node);
3858     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3859   }
3860
3861   g_node_destroy (moof_node);
3862   return TRUE;
3863
3864 missing_tfhd:
3865   {
3866     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3867     goto fail;
3868   }
3869 missing_mfhd:
3870   {
3871     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3872     goto fail;
3873   }
3874 lost_offset:
3875   {
3876     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3877     goto fail;
3878   }
3879 fail:
3880   {
3881     g_node_destroy (moof_node);
3882     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3883         (_("This file is corrupt and cannot be played.")), (NULL));
3884     return FALSE;
3885   }
3886 }
3887
3888 #if 0
3889 /* might be used if some day we actually use mfra & co
3890  * for random access to fragments,
3891  * but that will require quite some modifications and much less relying
3892  * on a sample array */
3893 #endif
3894
3895 static gboolean
3896 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3897 {
3898   QtDemuxStream *stream;
3899   guint32 ver_flags, track_id, len, num_entries, i;
3900   guint value_size, traf_size, trun_size, sample_size;
3901   guint64 time = 0, moof_offset = 0;
3902 #if 0
3903   GstBuffer *buf = NULL;
3904   GstFlowReturn ret;
3905 #endif
3906   GstByteReader tfra;
3907
3908   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3909
3910   if (!gst_byte_reader_skip (&tfra, 8))
3911     return FALSE;
3912
3913   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3914     return FALSE;
3915
3916   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3917       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3918       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3919     return FALSE;
3920
3921   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3922
3923   stream = qtdemux_find_stream (qtdemux, track_id);
3924   if (stream == NULL)
3925     goto unknown_trackid;
3926
3927   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3928   sample_size = (len & 3) + 1;
3929   trun_size = ((len & 12) >> 2) + 1;
3930   traf_size = ((len & 48) >> 4) + 1;
3931
3932   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3933       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3934
3935   if (num_entries == 0)
3936     goto no_samples;
3937
3938   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3939           value_size + value_size + traf_size + trun_size + sample_size))
3940     goto corrupt_file;
3941
3942   g_free (stream->ra_entries);
3943   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3944   stream->n_ra_entries = num_entries;
3945
3946   for (i = 0; i < num_entries; i++) {
3947     qt_atom_parser_get_offset (&tfra, value_size, &time);
3948     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3949     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3950     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3951     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3952
3953     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3954
3955     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3956         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3957
3958     stream->ra_entries[i].ts = time;
3959     stream->ra_entries[i].moof_offset = moof_offset;
3960
3961     /* don't want to go through the entire file and read all moofs at startup */
3962 #if 0
3963     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3964     if (ret != GST_FLOW_OK)
3965       goto corrupt_file;
3966     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3967         moof_offset, stream);
3968     gst_buffer_unref (buf);
3969 #endif
3970   }
3971
3972   check_update_duration (qtdemux, time);
3973
3974   return TRUE;
3975
3976 /* ERRORS */
3977 unknown_trackid:
3978   {
3979     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3980     return FALSE;
3981   }
3982 corrupt_file:
3983   {
3984     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3985     return FALSE;
3986   }
3987 no_samples:
3988   {
3989     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3990     return FALSE;
3991   }
3992 }
3993
3994 static gboolean
3995 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3996 {
3997   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3998   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3999   GstBuffer *mfro = NULL, *mfra = NULL;
4000   GstFlowReturn flow;
4001   gboolean ret = FALSE;
4002   GNode *mfra_node, *tfra_node;
4003   guint64 mfra_offset = 0;
4004   guint32 fourcc, mfra_size;
4005   gint64 len;
4006
4007   /* query upstream size in bytes */
4008   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4009     goto size_query_failed;
4010
4011   /* mfro box should be at the very end of the file */
4012   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4013   if (flow != GST_FLOW_OK)
4014     goto exit;
4015
4016   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4017
4018   fourcc = QT_FOURCC (mfro_map.data + 4);
4019   if (fourcc != FOURCC_mfro)
4020     goto exit;
4021
4022   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4023   if (mfro_map.size < 16)
4024     goto invalid_mfro_size;
4025
4026   mfra_size = QT_UINT32 (mfro_map.data + 12);
4027   if (mfra_size >= len)
4028     goto invalid_mfra_size;
4029
4030   mfra_offset = len - mfra_size;
4031
4032   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4033       mfra_offset, mfra_size);
4034
4035   /* now get and parse mfra box */
4036   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4037   if (flow != GST_FLOW_OK)
4038     goto broken_file;
4039
4040   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4041
4042   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4043   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4044
4045   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4046
4047   while (tfra_node) {
4048     qtdemux_parse_tfra (qtdemux, tfra_node);
4049     /* iterate all siblings */
4050     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4051   }
4052   g_node_destroy (mfra_node);
4053
4054   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4055   ret = TRUE;
4056
4057 exit:
4058
4059   if (mfro) {
4060     if (mfro_map.memory != NULL)
4061       gst_buffer_unmap (mfro, &mfro_map);
4062     gst_buffer_unref (mfro);
4063   }
4064   if (mfra) {
4065     if (mfra_map.memory != NULL)
4066       gst_buffer_unmap (mfra, &mfra_map);
4067     gst_buffer_unref (mfra);
4068   }
4069   return ret;
4070
4071 /* ERRORS */
4072 size_query_failed:
4073   {
4074     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4075     goto exit;
4076   }
4077 invalid_mfro_size:
4078   {
4079     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4080     goto exit;
4081   }
4082 invalid_mfra_size:
4083   {
4084     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4085     goto exit;
4086   }
4087 broken_file:
4088   {
4089     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4090     goto exit;
4091   }
4092 }
4093
4094 static guint64
4095 add_offset (guint64 offset, guint64 advance)
4096 {
4097   /* Avoid 64-bit overflow by clamping */
4098   if (offset > G_MAXUINT64 - advance)
4099     return G_MAXUINT64;
4100   return offset + advance;
4101 }
4102
4103 static GstFlowReturn
4104 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4105 {
4106   guint64 length = 0;
4107   guint32 fourcc = 0;
4108   GstBuffer *buf = NULL;
4109   GstFlowReturn ret = GST_FLOW_OK;
4110   guint64 cur_offset = qtdemux->offset;
4111   GstMapInfo map;
4112
4113   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4114   if (G_UNLIKELY (ret != GST_FLOW_OK))
4115     goto beach;
4116   gst_buffer_map (buf, &map, GST_MAP_READ);
4117   if (G_LIKELY (map.size >= 8))
4118     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4119   gst_buffer_unmap (buf, &map);
4120   gst_buffer_unref (buf);
4121
4122   /* maybe we already got most we needed, so only consider this eof */
4123   if (G_UNLIKELY (length == 0)) {
4124     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4125         (_("Invalid atom size.")),
4126         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4127             GST_FOURCC_ARGS (fourcc)));
4128     ret = GST_FLOW_EOS;
4129     goto beach;
4130   }
4131
4132   switch (fourcc) {
4133     case FOURCC_moof:
4134       /* record for later parsing when needed */
4135       if (!qtdemux->moof_offset) {
4136         qtdemux->moof_offset = qtdemux->offset;
4137       }
4138       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4139         /* FIXME */
4140       } else {
4141         qtdemux->offset += length;      /* skip moof and keep going */
4142       }
4143       if (qtdemux->got_moov) {
4144         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4145         ret = GST_FLOW_EOS;
4146         goto beach;
4147       }
4148       break;
4149     case FOURCC_mdat:
4150     case FOURCC_free:
4151     case FOURCC_wide:
4152     case FOURCC_PICT:
4153     case FOURCC_pnot:
4154     {
4155       GST_LOG_OBJECT (qtdemux,
4156           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4157           GST_FOURCC_ARGS (fourcc), cur_offset);
4158       qtdemux->offset = add_offset (qtdemux->offset, length);
4159       break;
4160     }
4161     case FOURCC_moov:
4162     {
4163       GstBuffer *moov = NULL;
4164
4165       if (qtdemux->got_moov) {
4166         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4167         qtdemux->offset = add_offset (qtdemux->offset, length);
4168         goto beach;
4169       }
4170
4171       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4172       if (ret != GST_FLOW_OK)
4173         goto beach;
4174       gst_buffer_map (moov, &map, GST_MAP_READ);
4175
4176       if (length != map.size) {
4177         /* Some files have a 'moov' atom at the end of the file which contains
4178          * a terminal 'free' atom where the body of the atom is missing.
4179          * Check for, and permit, this special case.
4180          */
4181         if (map.size >= 8) {
4182           guint8 *final_data = map.data + (map.size - 8);
4183           guint32 final_length = QT_UINT32 (final_data);
4184           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4185
4186           if (final_fourcc == FOURCC_free
4187               && map.size + final_length - 8 == length) {
4188             /* Ok, we've found that special case. Allocate a new buffer with
4189              * that free atom actually present. */
4190             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4191             gst_buffer_fill (newmoov, 0, map.data, map.size);
4192             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4193             gst_buffer_unmap (moov, &map);
4194             gst_buffer_unref (moov);
4195             moov = newmoov;
4196             gst_buffer_map (moov, &map, GST_MAP_READ);
4197           }
4198         }
4199       }
4200
4201       if (length != map.size) {
4202         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4203             (_("This file is incomplete and cannot be played.")),
4204             ("We got less than expected (received %" G_GSIZE_FORMAT
4205                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4206                 (guint) length, cur_offset));
4207         gst_buffer_unmap (moov, &map);
4208         gst_buffer_unref (moov);
4209         ret = GST_FLOW_ERROR;
4210         goto beach;
4211       }
4212       qtdemux->offset += length;
4213
4214       qtdemux_parse_moov (qtdemux, map.data, length);
4215       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4216
4217       qtdemux_parse_tree (qtdemux);
4218       g_node_destroy (qtdemux->moov_node);
4219       gst_buffer_unmap (moov, &map);
4220       gst_buffer_unref (moov);
4221       qtdemux->moov_node = NULL;
4222       qtdemux->got_moov = TRUE;
4223
4224       break;
4225     }
4226     case FOURCC_ftyp:
4227     {
4228       GstBuffer *ftyp = NULL;
4229
4230       /* extract major brand; might come in handy for ISO vs QT issues */
4231       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4232       if (ret != GST_FLOW_OK)
4233         goto beach;
4234       qtdemux->offset += length;
4235       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4236       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4237       gst_buffer_unmap (ftyp, &map);
4238       gst_buffer_unref (ftyp);
4239       break;
4240     }
4241     case FOURCC_uuid:
4242     {
4243       GstBuffer *uuid = NULL;
4244
4245       /* uuid are extension atoms */
4246       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4247       if (ret != GST_FLOW_OK)
4248         goto beach;
4249       qtdemux->offset += length;
4250       gst_buffer_map (uuid, &map, GST_MAP_READ);
4251       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4252       gst_buffer_unmap (uuid, &map);
4253       gst_buffer_unref (uuid);
4254       break;
4255     }
4256     case FOURCC_sidx:
4257     {
4258       GstBuffer *sidx = NULL;
4259       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4260       if (ret != GST_FLOW_OK)
4261         goto beach;
4262       qtdemux->offset += length;
4263       gst_buffer_map (sidx, &map, GST_MAP_READ);
4264       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4265       gst_buffer_unmap (sidx, &map);
4266       gst_buffer_unref (sidx);
4267       break;
4268     }
4269     default:
4270     {
4271       GstBuffer *unknown = NULL;
4272
4273       GST_LOG_OBJECT (qtdemux,
4274           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4275           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4276           cur_offset);
4277       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4278       if (ret != GST_FLOW_OK)
4279         goto beach;
4280       gst_buffer_map (unknown, &map, GST_MAP_READ);
4281       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4282       gst_buffer_unmap (unknown, &map);
4283       gst_buffer_unref (unknown);
4284       qtdemux->offset += length;
4285       break;
4286     }
4287   }
4288
4289 beach:
4290   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4291     /* digested all data, show what we have */
4292     qtdemux_prepare_streams (qtdemux);
4293     ret = qtdemux_expose_streams (qtdemux);
4294
4295     qtdemux->state = QTDEMUX_STATE_MOVIE;
4296     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4297         qtdemux->state);
4298     return ret;
4299   }
4300   return ret;
4301 }
4302
4303 /* Seeks to the previous keyframe of the indexed stream and
4304  * aligns other streams with respect to the keyframe timestamp
4305  * of indexed stream. Only called in case of Reverse Playback
4306  */
4307 static GstFlowReturn
4308 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4309 {
4310   guint8 n = 0;
4311   guint32 seg_idx = 0, k_index = 0;
4312   guint32 ref_seg_idx, ref_k_index;
4313   GstClockTime k_pos = 0, last_stop = 0;
4314   QtDemuxSegment *seg = NULL;
4315   QtDemuxStream *ref_str = NULL;
4316   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4317   guint64 target_ts;
4318
4319   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4320    * and finally align all the other streams on that timestamp with their
4321    * respective keyframes */
4322   for (n = 0; n < qtdemux->n_streams; n++) {
4323     QtDemuxStream *str = qtdemux->streams[n];
4324
4325     /* No candidate yet, take the first stream */
4326     if (!ref_str) {
4327       ref_str = str;
4328       continue;
4329     }
4330
4331     /* So that stream has a segment, we prefer video streams */
4332     if (str->subtype == FOURCC_vide) {
4333       ref_str = str;
4334       break;
4335     }
4336   }
4337
4338   if (G_UNLIKELY (!ref_str)) {
4339     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4340     goto eos;
4341   }
4342
4343   if (G_UNLIKELY (!ref_str->from_sample)) {
4344     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4345     goto eos;
4346   }
4347
4348   /* So that stream has been playing from from_sample to to_sample. We will
4349    * get the timestamp of the previous sample and search for a keyframe before
4350    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4351   if (ref_str->subtype == FOURCC_vide) {
4352     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4353         ref_str->from_sample - 1);
4354   } else {
4355     if (ref_str->from_sample >= 10)
4356       k_index = ref_str->from_sample - 10;
4357     else
4358       k_index = 0;
4359   }
4360
4361   target_ts =
4362       ref_str->samples[k_index].timestamp +
4363       ref_str->samples[k_index].pts_offset;
4364
4365   /* get current segment for that stream */
4366   seg = &ref_str->segments[ref_str->segment_index];
4367   /* Use segment start in original timescale for comparisons */
4368   seg_media_start_mov = seg->trak_media_start;
4369
4370   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4371       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4372       k_index, target_ts, seg_media_start_mov,
4373       GST_TIME_ARGS (seg->media_start));
4374
4375   /* Crawl back through segments to find the one containing this I frame */
4376   while (target_ts < seg_media_start_mov) {
4377     GST_DEBUG_OBJECT (qtdemux,
4378         "keyframe position (sample %u) is out of segment %u " " target %"
4379         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4380         ref_str->segment_index, target_ts, seg_media_start_mov);
4381
4382     if (G_UNLIKELY (!ref_str->segment_index)) {
4383       /* Reached first segment, let's consider it's EOS */
4384       goto eos;
4385     }
4386     ref_str->segment_index--;
4387     seg = &ref_str->segments[ref_str->segment_index];
4388     /* Use segment start in original timescale for comparisons */
4389     seg_media_start_mov = seg->trak_media_start;
4390   }
4391   /* Calculate time position of the keyframe and where we should stop */
4392   k_pos =
4393       QTSTREAMTIME_TO_GSTTIME (ref_str,
4394       target_ts - seg->trak_media_start) + seg->time;
4395   last_stop =
4396       QTSTREAMTIME_TO_GSTTIME (ref_str,
4397       ref_str->samples[ref_str->from_sample].timestamp -
4398       seg->trak_media_start) + seg->time;
4399
4400   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4401       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4402       k_index, GST_TIME_ARGS (k_pos));
4403
4404   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4405   qtdemux->segment.position = last_stop;
4406   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4407       GST_TIME_ARGS (last_stop));
4408
4409   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4410     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4411     goto eos;
4412   }
4413
4414   ref_seg_idx = ref_str->segment_index;
4415   ref_k_index = k_index;
4416
4417   /* Align them all on this */
4418   for (n = 0; n < qtdemux->n_streams; n++) {
4419     guint32 index = 0;
4420     GstClockTime seg_time = 0;
4421     QtDemuxStream *str = qtdemux->streams[n];
4422
4423     /* aligning reference stream again might lead to backing up to yet another
4424      * keyframe (due to timestamp rounding issues),
4425      * potentially putting more load on downstream; so let's try to avoid */
4426     if (str == ref_str) {
4427       seg_idx = ref_seg_idx;
4428       seg = &str->segments[seg_idx];
4429       k_index = ref_k_index;
4430       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4431           "sample at index %d", n, ref_str->segment_index, k_index);
4432     } else {
4433       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4434       GST_DEBUG_OBJECT (qtdemux,
4435           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4436           seg_idx, GST_TIME_ARGS (k_pos));
4437
4438       /* get segment and time in the segment */
4439       seg = &str->segments[seg_idx];
4440       seg_time = k_pos - seg->time;
4441
4442       /* get the media time in the segment.
4443        * No adjustment for empty "filler" segments */
4444       if (seg->media_start != GST_CLOCK_TIME_NONE)
4445         seg_time += seg->media_start;
4446
4447       /* get the index of the sample with media time */
4448       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4449       GST_DEBUG_OBJECT (qtdemux,
4450           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4451           GST_TIME_ARGS (seg_time), index);
4452
4453       /* find previous keyframe */
4454       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4455     }
4456
4457     /* Remember until where we want to go */
4458     str->to_sample = str->from_sample - 1;
4459     /* Define our time position */
4460     target_ts =
4461         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4462     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4463     if (seg->media_start != GST_CLOCK_TIME_NONE)
4464       str->time_position -= seg->media_start;
4465
4466     /* Now seek back in time */
4467     gst_qtdemux_move_stream (qtdemux, str, k_index);
4468     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4469         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4470         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4471   }
4472
4473   return GST_FLOW_OK;
4474
4475 eos:
4476   return GST_FLOW_EOS;
4477 }
4478
4479 /*
4480  * Gets the current qt segment start, stop and position for the
4481  * given time offset. This is used in update_segment()
4482  */
4483 static void
4484 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4485     QtDemuxStream * stream, GstClockTime offset,
4486     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4487 {
4488   GstClockTime seg_time;
4489   GstClockTime start, stop, time;
4490   QtDemuxSegment *segment;
4491
4492   segment = &stream->segments[stream->segment_index];
4493
4494   /* get time in this segment */
4495   seg_time = (offset - segment->time) * segment->rate;
4496
4497   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4498       GST_TIME_ARGS (seg_time));
4499
4500   if (G_UNLIKELY (seg_time > segment->duration)) {
4501     GST_LOG_OBJECT (stream->pad,
4502         "seg_time > segment->duration %" GST_TIME_FORMAT,
4503         GST_TIME_ARGS (segment->duration));
4504     seg_time = segment->duration;
4505   }
4506
4507   /* qtdemux->segment.stop is in outside-time-realm, whereas
4508    * segment->media_stop is in track-time-realm.
4509    *
4510    * In order to compare the two, we need to bring segment.stop
4511    * into the track-time-realm
4512    *
4513    * FIXME - does this comment still hold? Don't see any conversion here */
4514
4515   stop = qtdemux->segment.stop;
4516   if (stop == GST_CLOCK_TIME_NONE)
4517     stop = qtdemux->segment.duration;
4518   if (stop == GST_CLOCK_TIME_NONE)
4519     stop = segment->media_stop;
4520   else
4521     stop =
4522         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4523
4524   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4525     start = segment->time + seg_time;
4526     time = offset;
4527     stop = start - seg_time + segment->duration;
4528   } else if (qtdemux->segment.rate >= 0) {
4529     start = MIN (segment->media_start + seg_time, stop);
4530     time = offset;
4531   } else {
4532     if (segment->media_start >= qtdemux->segment.start) {
4533       time = segment->time;
4534     } else {
4535       time = segment->time + (qtdemux->segment.start - segment->media_start);
4536     }
4537
4538     start = MAX (segment->media_start, qtdemux->segment.start);
4539     stop = MIN (segment->media_start + seg_time, stop);
4540   }
4541
4542   *_start = start;
4543   *_stop = stop;
4544   *_time = time;
4545 }
4546
4547 /*
4548  * Updates the qt segment used for the stream and pushes a new segment event
4549  * downstream on this stream's pad.
4550  */
4551 static gboolean
4552 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4553     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4554     GstClockTime * _stop)
4555 {
4556   QtDemuxSegment *segment;
4557   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4558   gdouble rate;
4559   GstEvent *event;
4560
4561   /* update the current segment */
4562   stream->segment_index = seg_idx;
4563
4564   /* get the segment */
4565   segment = &stream->segments[seg_idx];
4566
4567   if (G_UNLIKELY (offset < segment->time)) {
4568     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4569         GST_TIME_ARGS (segment->time));
4570     return FALSE;
4571   }
4572
4573   /* segment lies beyond total indicated duration */
4574   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4575           segment->time > qtdemux->segment.duration)) {
4576     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4577         " < segment->time %" GST_TIME_FORMAT,
4578         GST_TIME_ARGS (qtdemux->segment.duration),
4579         GST_TIME_ARGS (segment->time));
4580     return FALSE;
4581   }
4582
4583   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4584       &start, &stop, &time);
4585
4586   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4587       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4588       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4589
4590   /* combine global rate with that of the segment */
4591   rate = segment->rate * qtdemux->segment.rate;
4592
4593   /* Copy flags from main segment */
4594   stream->segment.flags = qtdemux->segment.flags;
4595
4596   /* update the segment values used for clipping */
4597   stream->segment.offset = qtdemux->segment.offset;
4598   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4599   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4600   stream->segment.rate = rate;
4601   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4602       stream->cslg_shift);
4603   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4604       stream->cslg_shift);
4605   stream->segment.time = time;
4606   stream->segment.position = stream->segment.start;
4607
4608   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4609       &stream->segment);
4610
4611   /* now prepare and send the segment */
4612   if (stream->pad) {
4613     event = gst_event_new_segment (&stream->segment);
4614     if (qtdemux->segment_seqnum) {
4615       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4616     }
4617     gst_pad_push_event (stream->pad, event);
4618     /* assume we can send more data now */
4619     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4620     /* clear to send tags on this pad now */
4621     gst_qtdemux_push_tags (qtdemux, stream);
4622   }
4623
4624   if (_start)
4625     *_start = start;
4626   if (_stop)
4627     *_stop = stop;
4628
4629   return TRUE;
4630 }
4631
4632 /* activate the given segment number @seg_idx of @stream at time @offset.
4633  * @offset is an absolute global position over all the segments.
4634  *
4635  * This will push out a NEWSEGMENT event with the right values and
4636  * position the stream index to the first decodable sample before
4637  * @offset.
4638  */
4639 static gboolean
4640 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4641     guint32 seg_idx, GstClockTime offset)
4642 {
4643   QtDemuxSegment *segment;
4644   guint32 index, kf_index;
4645   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4646
4647   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4648       seg_idx, GST_TIME_ARGS (offset));
4649
4650   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4651           &start, &stop))
4652     return FALSE;
4653
4654   segment = &stream->segments[stream->segment_index];
4655
4656   /* in the fragmented case, we pick a fragment that starts before our
4657    * desired position and rely on downstream to wait for a keyframe
4658    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4659    * tfra entries tells us which trun/sample the key unit is in, but we don't
4660    * make use of this additional information at the moment) */
4661   if (qtdemux->fragmented) {
4662     stream->to_sample = G_MAXUINT32;
4663     return TRUE;
4664   }
4665
4666   /* We don't need to look for a sample in push-based */
4667   if (!qtdemux->pullbased)
4668     return TRUE;
4669
4670   /* and move to the keyframe before the indicated media time of the
4671    * segment */
4672   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4673     if (qtdemux->segment.rate >= 0) {
4674       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4675       stream->to_sample = G_MAXUINT32;
4676       GST_DEBUG_OBJECT (stream->pad,
4677           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4678           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4679           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4680     } else {
4681       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4682       stream->to_sample = index;
4683       GST_DEBUG_OBJECT (stream->pad,
4684           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4685           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4686           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4687     }
4688   } else {
4689     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4690         "this is an empty segment");
4691     return TRUE;
4692   }
4693
4694   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4695    * encountered an error and printed a message so we return appropriately */
4696   if (index == -1)
4697     return FALSE;
4698
4699   /* we're at the right spot */
4700   if (index == stream->sample_index) {
4701     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4702     return TRUE;
4703   }
4704
4705   /* find keyframe of the target index */
4706   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4707
4708 /* *INDENT-OFF* */
4709 /* indent does stupid stuff with stream->samples[].timestamp */
4710
4711   /* if we move forwards, we don't have to go back to the previous
4712    * keyframe since we already sent that. We can also just jump to
4713    * the keyframe right before the target index if there is one. */
4714   if (index > stream->sample_index) {
4715     /* moving forwards check if we move past a keyframe */
4716     if (kf_index > stream->sample_index) {
4717       GST_DEBUG_OBJECT (stream->pad,
4718            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4719            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4720            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4721       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4722     } else {
4723       GST_DEBUG_OBJECT (stream->pad,
4724           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4725           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4726           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4727     }
4728   } else {
4729     GST_DEBUG_OBJECT (stream->pad,
4730         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4731         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4732         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4733     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4734   }
4735
4736 /* *INDENT-ON* */
4737
4738   return TRUE;
4739 }
4740
4741 /* prepare to get the current sample of @stream, getting essential values.
4742  *
4743  * This function will also prepare and send the segment when needed.
4744  *
4745  * Return FALSE if the stream is EOS.
4746  *
4747  * PULL-BASED
4748  */
4749 static gboolean
4750 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4751     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4752     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4753     gboolean * keyframe)
4754 {
4755   QtDemuxSample *sample;
4756   GstClockTime time_position;
4757   guint32 seg_idx;
4758
4759   g_return_val_if_fail (stream != NULL, FALSE);
4760
4761   time_position = stream->time_position;
4762   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4763     goto eos;
4764
4765   seg_idx = stream->segment_index;
4766   if (G_UNLIKELY (seg_idx == -1)) {
4767     /* find segment corresponding to time_position if we are looking
4768      * for a segment. */
4769     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4770   }
4771
4772   /* different segment, activate it, sample_index will be set. */
4773   if (G_UNLIKELY (stream->segment_index != seg_idx))
4774     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4775
4776   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4777                   segment_index]))) {
4778     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4779
4780     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4781         " prepare empty sample");
4782
4783     *empty = TRUE;
4784     *pts = *dts = time_position;
4785     *duration = seg->duration - (time_position - seg->time);
4786
4787     return TRUE;
4788   }
4789
4790   *empty = FALSE;
4791
4792   if (stream->sample_index == -1)
4793     stream->sample_index = 0;
4794
4795   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4796       stream->sample_index, stream->n_samples);
4797
4798   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4799     if (!qtdemux->fragmented)
4800       goto eos;
4801
4802     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4803     do {
4804       GstFlowReturn flow;
4805
4806       GST_OBJECT_LOCK (qtdemux);
4807       flow = qtdemux_add_fragmented_samples (qtdemux);
4808       GST_OBJECT_UNLOCK (qtdemux);
4809
4810       if (flow != GST_FLOW_OK)
4811         goto eos;
4812     }
4813     while (stream->sample_index >= stream->n_samples);
4814   }
4815
4816   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4817     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4818         stream->sample_index);
4819     return FALSE;
4820   }
4821
4822   /* now get the info for the sample we're at */
4823   sample = &stream->samples[stream->sample_index];
4824
4825   *dts = QTSAMPLE_DTS (stream, sample);
4826   *pts = QTSAMPLE_PTS (stream, sample);
4827   *offset = sample->offset;
4828   *size = sample->size;
4829   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4830   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4831
4832   return TRUE;
4833
4834   /* special cases */
4835 eos:
4836   {
4837     stream->time_position = GST_CLOCK_TIME_NONE;
4838     return FALSE;
4839   }
4840 }
4841
4842 /* move to the next sample in @stream.
4843  *
4844  * Moves to the next segment when needed.
4845  */
4846 static void
4847 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4848 {
4849   QtDemuxSample *sample;
4850   QtDemuxSegment *segment;
4851
4852   /* get current segment */
4853   segment = &stream->segments[stream->segment_index];
4854
4855   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4856     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4857     goto next_segment;
4858   }
4859
4860   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4861     /* Mark the stream as EOS */
4862     GST_DEBUG_OBJECT (qtdemux,
4863         "reached max allowed sample %u, mark EOS", stream->to_sample);
4864     stream->time_position = GST_CLOCK_TIME_NONE;
4865     return;
4866   }
4867
4868   /* move to next sample */
4869   stream->sample_index++;
4870   stream->offset_in_sample = 0;
4871
4872   /* reached the last sample, we need the next segment */
4873   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4874     goto next_segment;
4875
4876   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4877     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4878         stream->sample_index);
4879     return;
4880   }
4881
4882   /* get next sample */
4883   sample = &stream->samples[stream->sample_index];
4884
4885   /* see if we are past the segment */
4886   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4887     goto next_segment;
4888
4889   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4890     /* inside the segment, update time_position, looks very familiar to
4891      * GStreamer segments, doesn't it? */
4892     stream->time_position =
4893         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4894   } else {
4895     /* not yet in segment, time does not yet increment. This means
4896      * that we are still prerolling keyframes to the decoder so it can
4897      * decode the first sample of the segment. */
4898     stream->time_position = segment->time;
4899   }
4900   return;
4901
4902   /* move to the next segment */
4903 next_segment:
4904   {
4905     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4906
4907     if (stream->segment_index == stream->n_segments - 1) {
4908       /* are we at the end of the last segment, we're EOS */
4909       stream->time_position = GST_CLOCK_TIME_NONE;
4910     } else {
4911       /* else we're only at the end of the current segment */
4912       stream->time_position = segment->stop_time;
4913     }
4914     /* make sure we select a new segment */
4915
4916     /* accumulate previous segments */
4917     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4918       stream->accumulated_base +=
4919           (stream->segment.stop -
4920           stream->segment.start) / ABS (stream->segment.rate);
4921
4922     stream->segment_index = -1;
4923   }
4924 }
4925
4926 static void
4927 gst_qtdemux_sync_streams (GstQTDemux * demux)
4928 {
4929   gint i;
4930
4931   if (demux->n_streams <= 1)
4932     return;
4933
4934   for (i = 0; i < demux->n_streams; i++) {
4935     QtDemuxStream *stream;
4936     GstClockTime end_time;
4937
4938     stream = demux->streams[i];
4939
4940     if (!stream->pad)
4941       continue;
4942
4943     /* TODO advance time on subtitle streams here, if any some day */
4944
4945     /* some clips/trailers may have unbalanced streams at the end,
4946      * so send EOS on shorter stream to prevent stalling others */
4947
4948     /* do not mess with EOS if SEGMENT seeking */
4949     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4950       continue;
4951
4952     if (demux->pullbased) {
4953       /* loop mode is sample time based */
4954       if (!STREAM_IS_EOS (stream))
4955         continue;
4956     } else {
4957       /* push mode is byte position based */
4958       if (stream->n_samples &&
4959           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4960         continue;
4961     }
4962
4963     if (stream->sent_eos)
4964       continue;
4965
4966     /* only act if some gap */
4967     end_time = stream->segments[stream->n_segments - 1].stop_time;
4968     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4969         ", stream end: %" GST_TIME_FORMAT,
4970         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4971     if (GST_CLOCK_TIME_IS_VALID (end_time)
4972         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4973       GstEvent *event;
4974
4975       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4976           GST_PAD_NAME (stream->pad));
4977       stream->sent_eos = TRUE;
4978       event = gst_event_new_eos ();
4979       if (demux->segment_seqnum)
4980         gst_event_set_seqnum (event, demux->segment_seqnum);
4981       gst_pad_push_event (stream->pad, event);
4982     }
4983   }
4984 }
4985
4986 /* EOS and NOT_LINKED need to be combined. This means that we return:
4987  *
4988  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4989  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4990  */
4991 static GstFlowReturn
4992 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4993     GstFlowReturn ret)
4994 {
4995   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4996
4997   if (stream->pad)
4998     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4999         ret);
5000   else
5001     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5002
5003   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5004   return ret;
5005 }
5006
5007 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5008  * completely clipped
5009  *
5010  * Should be used only with raw buffers */
5011 static GstBuffer *
5012 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5013     GstBuffer * buf)
5014 {
5015   guint64 start, stop, cstart, cstop, diff;
5016   GstClockTime pts, duration;
5017   gsize size, osize;
5018   gint num_rate, denom_rate;
5019   gint frame_size;
5020   gboolean clip_data;
5021   guint offset;
5022
5023   osize = size = gst_buffer_get_size (buf);
5024   offset = 0;
5025
5026   /* depending on the type, setup the clip parameters */
5027   if (stream->subtype == FOURCC_soun) {
5028     frame_size = stream->bytes_per_frame;
5029     num_rate = GST_SECOND;
5030     denom_rate = (gint) stream->rate;
5031     clip_data = TRUE;
5032   } else if (stream->subtype == FOURCC_vide) {
5033     frame_size = size;
5034     num_rate = stream->fps_n;
5035     denom_rate = stream->fps_d;
5036     clip_data = FALSE;
5037   } else
5038     goto wrong_type;
5039
5040   if (frame_size <= 0)
5041     goto bad_frame_size;
5042
5043   /* we can only clip if we have a valid pts */
5044   pts = GST_BUFFER_PTS (buf);
5045   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5046     goto no_pts;
5047
5048   duration = GST_BUFFER_DURATION (buf);
5049
5050   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5051     duration =
5052         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5053   }
5054
5055   start = pts;
5056   stop = start + duration;
5057
5058   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5059               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5060     goto clipped;
5061
5062   /* see if some clipping happened */
5063   diff = cstart - start;
5064   if (diff > 0) {
5065     pts += diff;
5066     duration -= diff;
5067
5068     if (clip_data) {
5069       /* bring clipped time to samples and to bytes */
5070       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5071       diff *= frame_size;
5072
5073       GST_DEBUG_OBJECT (qtdemux,
5074           "clipping start to %" GST_TIME_FORMAT " %"
5075           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5076
5077       offset = diff;
5078       size -= diff;
5079     }
5080   }
5081   diff = stop - cstop;
5082   if (diff > 0) {
5083     duration -= diff;
5084
5085     if (clip_data) {
5086       /* bring clipped time to samples and then to bytes */
5087       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5088       diff *= frame_size;
5089       GST_DEBUG_OBJECT (qtdemux,
5090           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5091           " bytes", GST_TIME_ARGS (cstop), diff);
5092       size -= diff;
5093     }
5094   }
5095
5096   if (offset != 0 || size != osize)
5097     gst_buffer_resize (buf, offset, size);
5098
5099   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5100   GST_BUFFER_PTS (buf) = pts;
5101   GST_BUFFER_DURATION (buf) = duration;
5102
5103   return buf;
5104
5105   /* dropped buffer */
5106 wrong_type:
5107   {
5108     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5109     return buf;
5110   }
5111 bad_frame_size:
5112   {
5113     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5114     return buf;
5115   }
5116 no_pts:
5117   {
5118     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5119     return buf;
5120   }
5121 clipped:
5122   {
5123     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5124     gst_buffer_unref (buf);
5125     return NULL;
5126   }
5127 }
5128
5129 /* the input buffer metadata must be writable,
5130  * but time/duration etc not yet set and need not be preserved */
5131 static GstBuffer *
5132 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5133     GstBuffer * buf)
5134 {
5135   GstMapInfo map;
5136   guint nsize = 0;
5137   gchar *str;
5138
5139   /* not many cases for now */
5140   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5141     /* send a one time dvd clut event */
5142     if (stream->pending_event && stream->pad)
5143       gst_pad_push_event (stream->pad, stream->pending_event);
5144     stream->pending_event = NULL;
5145   }
5146
5147   if (G_UNLIKELY (stream->subtype != FOURCC_text
5148           && stream->subtype != FOURCC_sbtl &&
5149           stream->subtype != FOURCC_subp)) {
5150     return buf;
5151   }
5152
5153   gst_buffer_map (buf, &map, GST_MAP_READ);
5154
5155   /* empty buffer is sent to terminate previous subtitle */
5156   if (map.size <= 2) {
5157     gst_buffer_unmap (buf, &map);
5158     gst_buffer_unref (buf);
5159     return NULL;
5160   }
5161   if (stream->subtype == FOURCC_subp) {
5162     /* That's all the processing needed for subpictures */
5163     gst_buffer_unmap (buf, &map);
5164     return buf;
5165   }
5166
5167   nsize = GST_READ_UINT16_BE (map.data);
5168   nsize = MIN (nsize, map.size - 2);
5169
5170   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5171       nsize, map.size);
5172
5173   /* takes care of UTF-8 validation or UTF-16 recognition,
5174    * no other encoding expected */
5175   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5176   gst_buffer_unmap (buf, &map);
5177   if (str) {
5178     gst_buffer_unref (buf);
5179     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5180   } else {
5181     /* this should not really happen unless the subtitle is corrupted */
5182     gst_buffer_unref (buf);
5183     buf = NULL;
5184   }
5185
5186   /* FIXME ? convert optional subsequent style info to markup */
5187
5188   return buf;
5189 }
5190
5191 /* Sets a buffer's attributes properly and pushes it downstream.
5192  * Also checks for additional actions and custom processing that may
5193  * need to be done first.
5194  */
5195 static GstFlowReturn
5196 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5197     QtDemuxStream * stream, GstBuffer * buf,
5198     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5199     gboolean keyframe, GstClockTime position, guint64 byte_position)
5200 {
5201   GstFlowReturn ret = GST_FLOW_OK;
5202
5203   /* offset the timestamps according to the edit list */
5204
5205   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5206     gchar *url;
5207     GstMapInfo map;
5208
5209     gst_buffer_map (buf, &map, GST_MAP_READ);
5210     url = g_strndup ((gchar *) map.data, map.size);
5211     gst_buffer_unmap (buf, &map);
5212     if (url != NULL && strlen (url) != 0) {
5213       /* we have RTSP redirect now */
5214       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5215           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5216               gst_structure_new ("redirect",
5217                   "new-location", G_TYPE_STRING, url, NULL)));
5218       qtdemux->posted_redirect = TRUE;
5219     } else {
5220       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5221           "posting");
5222     }
5223     g_free (url);
5224   }
5225
5226   /* position reporting */
5227   if (qtdemux->segment.rate >= 0) {
5228     qtdemux->segment.position = position;
5229     gst_qtdemux_sync_streams (qtdemux);
5230   }
5231
5232   if (G_UNLIKELY (!stream->pad)) {
5233     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5234     gst_buffer_unref (buf);
5235     goto exit;
5236   }
5237
5238   /* send out pending buffers */
5239   while (stream->buffers) {
5240     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5241
5242     if (G_UNLIKELY (stream->discont)) {
5243       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5244       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5245       stream->discont = FALSE;
5246     } else {
5247       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5248     }
5249
5250     gst_pad_push (stream->pad, buffer);
5251
5252     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5253   }
5254
5255   /* we're going to modify the metadata */
5256   buf = gst_buffer_make_writable (buf);
5257
5258   if (G_UNLIKELY (stream->need_process))
5259     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5260
5261   if (!buf) {
5262     goto exit;
5263   }
5264
5265   GST_BUFFER_DTS (buf) = dts;
5266   GST_BUFFER_PTS (buf) = pts;
5267   GST_BUFFER_DURATION (buf) = duration;
5268   GST_BUFFER_OFFSET (buf) = -1;
5269   GST_BUFFER_OFFSET_END (buf) = -1;
5270
5271   if (G_UNLIKELY (stream->rgb8_palette))
5272     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5273
5274   if (G_UNLIKELY (stream->padding)) {
5275     gst_buffer_resize (buf, stream->padding, -1);
5276   }
5277 #if 0
5278   if (G_UNLIKELY (qtdemux->element_index)) {
5279     GstClockTime stream_time;
5280
5281     stream_time =
5282         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5283         timestamp);
5284     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5285       GST_LOG_OBJECT (qtdemux,
5286           "adding association %" GST_TIME_FORMAT "-> %"
5287           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5288       gst_index_add_association (qtdemux->element_index,
5289           qtdemux->index_id,
5290           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5291           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5292           GST_FORMAT_BYTES, byte_position, NULL);
5293     }
5294   }
5295 #endif
5296
5297   if (stream->need_clip)
5298     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5299
5300   if (G_UNLIKELY (buf == NULL))
5301     goto exit;
5302
5303   if (G_UNLIKELY (stream->discont)) {
5304     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5305     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5306     stream->discont = FALSE;
5307   } else {
5308     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5309   }
5310
5311   if (!keyframe) {
5312     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5313     stream->on_keyframe = FALSE;
5314   } else {
5315     stream->on_keyframe = TRUE;
5316   }
5317
5318
5319   GST_LOG_OBJECT (qtdemux,
5320       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5321       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5322       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5323       GST_PAD_NAME (stream->pad));
5324
5325   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5326     GstStructure *crypto_info;
5327     QtDemuxCencSampleSetInfo *info =
5328         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5329     gint index;
5330     GstEvent *event;
5331
5332     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5333       gst_pad_push_event (stream->pad, event);
5334     }
5335
5336     if (info->crypto_info == NULL) {
5337       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5338       gst_buffer_unref (buf);
5339       goto exit;
5340     }
5341
5342     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
5343     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5344       /* steal structure from array */
5345       crypto_info = g_ptr_array_index (info->crypto_info, index);
5346       g_ptr_array_index (info->crypto_info, index) = NULL;
5347       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
5348       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5349         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5350     }
5351   }
5352
5353   ret = gst_pad_push (stream->pad, buf);
5354
5355   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5356     /* mark position in stream, we'll need this to know when to send GAP event */
5357     stream->segment.position = pts + duration;
5358   }
5359
5360 exit:
5361   return ret;
5362 }
5363
5364 static const QtDemuxRandomAccessEntry *
5365 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5366     GstClockTime pos, gboolean after)
5367 {
5368   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5369   guint n_entries = stream->n_ra_entries;
5370   guint i;
5371
5372   /* we assume the table is sorted */
5373   for (i = 0; i < n_entries; ++i) {
5374     if (entries[i].ts > pos)
5375       break;
5376   }
5377
5378   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5379    * probably okay to assume that the index lists the very first fragment */
5380   if (i == 0)
5381     return &entries[0];
5382
5383   if (after)
5384     return &entries[i];
5385   else
5386     return &entries[i - 1];
5387 }
5388
5389 static gboolean
5390 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5391 {
5392   const QtDemuxRandomAccessEntry *best_entry = NULL;
5393   guint i;
5394
5395   GST_OBJECT_LOCK (qtdemux);
5396
5397   g_assert (qtdemux->n_streams > 0);
5398
5399   for (i = 0; i < qtdemux->n_streams; i++) {
5400     const QtDemuxRandomAccessEntry *entry;
5401     QtDemuxStream *stream;
5402     gboolean is_audio_or_video;
5403
5404     stream = qtdemux->streams[i];
5405
5406     g_free (stream->samples);
5407     stream->samples = NULL;
5408     stream->n_samples = 0;
5409     stream->stbl_index = -1;    /* no samples have yet been parsed */
5410     stream->sample_index = -1;
5411
5412     if (stream->ra_entries == NULL)
5413       continue;
5414
5415     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5416       is_audio_or_video = TRUE;
5417     else
5418       is_audio_or_video = FALSE;
5419
5420     entry =
5421         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5422         stream->time_position, !is_audio_or_video);
5423
5424     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5425         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5426
5427     stream->pending_seek = entry;
5428
5429     /* decide position to jump to just based on audio/video tracks, not subs */
5430     if (!is_audio_or_video)
5431       continue;
5432
5433     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5434       best_entry = entry;
5435   }
5436
5437   if (best_entry == NULL) {
5438     GST_OBJECT_UNLOCK (qtdemux);
5439     return FALSE;
5440   }
5441
5442   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5443       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5444       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5445       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5446
5447   qtdemux->moof_offset = best_entry->moof_offset;
5448
5449   qtdemux_add_fragmented_samples (qtdemux);
5450
5451   GST_OBJECT_UNLOCK (qtdemux);
5452   return TRUE;
5453 }
5454
5455 static GstFlowReturn
5456 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5457 {
5458   GstFlowReturn ret = GST_FLOW_OK;
5459   GstBuffer *buf = NULL;
5460   QtDemuxStream *stream;
5461   GstClockTime min_time;
5462   guint64 offset = 0;
5463   GstClockTime dts = GST_CLOCK_TIME_NONE;
5464   GstClockTime pts = GST_CLOCK_TIME_NONE;
5465   GstClockTime duration = 0;
5466   gboolean keyframe = FALSE;
5467   guint sample_size = 0;
5468   gboolean empty = 0;
5469   guint size;
5470   gint index;
5471   gint i;
5472
5473   gst_qtdemux_push_pending_newsegment (qtdemux);
5474
5475   if (qtdemux->fragmented_seek_pending) {
5476     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5477     gst_qtdemux_do_fragmented_seek (qtdemux);
5478     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5479     qtdemux->fragmented_seek_pending = FALSE;
5480   }
5481
5482   /* Figure out the next stream sample to output, min_time is expressed in
5483    * global time and runs over the edit list segments. */
5484   min_time = G_MAXUINT64;
5485   index = -1;
5486   for (i = 0; i < qtdemux->n_streams; i++) {
5487     GstClockTime position;
5488
5489     stream = qtdemux->streams[i];
5490     position = stream->time_position;
5491
5492     /* position of -1 is EOS */
5493     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5494       min_time = position;
5495       index = i;
5496     }
5497   }
5498   /* all are EOS */
5499   if (G_UNLIKELY (index == -1)) {
5500     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5501     goto eos;
5502   }
5503
5504   /* check for segment end */
5505   if (G_UNLIKELY (qtdemux->segment.stop != -1
5506           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5507               || (qtdemux->segment.rate < 0
5508                   && qtdemux->segment.start > min_time))
5509           && qtdemux->streams[index]->on_keyframe)) {
5510     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5511     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5512     goto eos_stream;
5513   }
5514
5515   /* gap events for subtitle streams */
5516   for (i = 0; i < qtdemux->n_streams; i++) {
5517     stream = qtdemux->streams[i];
5518     if (stream->pad && (stream->subtype == FOURCC_subp
5519             || stream->subtype == FOURCC_text
5520             || stream->subtype == FOURCC_sbtl)) {
5521       /* send one second gap events until the stream catches up */
5522       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5523       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5524           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5525           stream->segment.position + GST_SECOND < min_time) {
5526         GstEvent *gap =
5527             gst_event_new_gap (stream->segment.position, GST_SECOND);
5528         gst_pad_push_event (stream->pad, gap);
5529         stream->segment.position += GST_SECOND;
5530       }
5531     }
5532   }
5533
5534   stream = qtdemux->streams[index];
5535   if (stream->new_caps) {
5536     gst_qtdemux_configure_stream (qtdemux, stream);
5537     qtdemux_do_allocation (qtdemux, stream);
5538   }
5539
5540   /* fetch info for the current sample of this stream */
5541   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5542               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5543     goto eos_stream;
5544
5545   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5546   if (G_UNLIKELY (qtdemux->
5547           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5548     if (stream->subtype == FOURCC_vide && !keyframe) {
5549       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5550       goto next;
5551     }
5552   }
5553
5554   GST_DEBUG_OBJECT (qtdemux,
5555       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5556       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5557       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5558       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5559
5560   if (G_UNLIKELY (empty)) {
5561     /* empty segment, push a gap and move to the next one */
5562     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5563     stream->segment.position = pts + duration;
5564     goto next;
5565   }
5566
5567   /* hmm, empty sample, skip and move to next sample */
5568   if (G_UNLIKELY (sample_size <= 0))
5569     goto next;
5570
5571   /* last pushed sample was out of boundary, goto next sample */
5572   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5573     goto next;
5574
5575   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5576     size = sample_size;
5577   } else {
5578     GST_DEBUG_OBJECT (qtdemux,
5579         "size %d larger than stream max_buffer_size %d, trimming",
5580         sample_size, stream->max_buffer_size);
5581     size =
5582         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5583   }
5584
5585   if (qtdemux->cenc_aux_info_offset > 0) {
5586     GstMapInfo map;
5587     GstByteReader br;
5588     GstBuffer *aux_info = NULL;
5589
5590     /* pull the data stored before the sample */
5591     ret =
5592         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5593         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5594     if (G_UNLIKELY (ret != GST_FLOW_OK))
5595       goto beach;
5596     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5597     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5598     gst_byte_reader_init (&br, map.data + 8, map.size);
5599     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5600             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5601       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5602       gst_buffer_unmap (aux_info, &map);
5603       gst_buffer_unref (aux_info);
5604       ret = GST_FLOW_ERROR;
5605       goto beach;
5606     }
5607     gst_buffer_unmap (aux_info, &map);
5608     gst_buffer_unref (aux_info);
5609   }
5610
5611   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5612       offset);
5613
5614   if (stream->use_allocator) {
5615     /* if we have a per-stream allocator, use it */
5616     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5617   }
5618
5619   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5620       size, &buf);
5621   if (G_UNLIKELY (ret != GST_FLOW_OK))
5622     goto beach;
5623
5624   if (size != sample_size) {
5625     pts += gst_util_uint64_scale_int (GST_SECOND,
5626         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5627     dts += gst_util_uint64_scale_int (GST_SECOND,
5628         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5629     duration = gst_util_uint64_scale_int (GST_SECOND,
5630         size / stream->bytes_per_frame, stream->timescale);
5631   }
5632
5633   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5634       dts, pts, duration, keyframe, min_time, offset);
5635
5636   if (size != sample_size) {
5637     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5638     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5639
5640     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5641         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5642     if (time_position >= segment->media_start) {
5643       /* inside the segment, update time_position, looks very familiar to
5644        * GStreamer segments, doesn't it? */
5645       stream->time_position = (time_position - segment->media_start) +
5646           segment->time;
5647     } else {
5648       /* not yet in segment, time does not yet increment. This means
5649        * that we are still prerolling keyframes to the decoder so it can
5650        * decode the first sample of the segment. */
5651       stream->time_position = segment->time;
5652     }
5653   }
5654
5655   /* combine flows */
5656   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5657   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5658    * we have no more data for the pad to push */
5659   if (ret == GST_FLOW_EOS)
5660     ret = GST_FLOW_OK;
5661
5662   stream->offset_in_sample += size;
5663   if (stream->offset_in_sample >= sample_size) {
5664     gst_qtdemux_advance_sample (qtdemux, stream);
5665   }
5666   goto beach;
5667
5668 next:
5669   gst_qtdemux_advance_sample (qtdemux, stream);
5670
5671 beach:
5672   return ret;
5673
5674   /* special cases */
5675 eos:
5676   {
5677     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5678     ret = GST_FLOW_EOS;
5679     goto beach;
5680   }
5681 eos_stream:
5682   {
5683     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5684     /* EOS will be raised if all are EOS */
5685     ret = GST_FLOW_OK;
5686     goto beach;
5687   }
5688 }
5689
5690 static void
5691 gst_qtdemux_loop (GstPad * pad)
5692 {
5693   GstQTDemux *qtdemux;
5694   guint64 cur_offset;
5695   GstFlowReturn ret;
5696
5697   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5698
5699   cur_offset = qtdemux->offset;
5700   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5701       cur_offset, qt_demux_state_string (qtdemux->state));
5702
5703   switch (qtdemux->state) {
5704     case QTDEMUX_STATE_INITIAL:
5705     case QTDEMUX_STATE_HEADER:
5706       ret = gst_qtdemux_loop_state_header (qtdemux);
5707       break;
5708     case QTDEMUX_STATE_MOVIE:
5709       ret = gst_qtdemux_loop_state_movie (qtdemux);
5710       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5711         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5712       }
5713       break;
5714     default:
5715       /* ouch */
5716       goto invalid_state;
5717   }
5718
5719   /* if something went wrong, pause */
5720   if (ret != GST_FLOW_OK)
5721     goto pause;
5722
5723 done:
5724   gst_object_unref (qtdemux);
5725   return;
5726
5727   /* ERRORS */
5728 invalid_state:
5729   {
5730     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5731         (NULL), ("streaming stopped, invalid state"));
5732     gst_pad_pause_task (pad);
5733     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5734     goto done;
5735   }
5736 pause:
5737   {
5738     const gchar *reason = gst_flow_get_name (ret);
5739
5740     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5741
5742     gst_pad_pause_task (pad);
5743
5744     /* fatal errors need special actions */
5745     /* check EOS */
5746     if (ret == GST_FLOW_EOS) {
5747       if (qtdemux->n_streams == 0) {
5748         /* we have no streams, post an error */
5749         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5750       }
5751       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5752         gint64 stop;
5753
5754         if ((stop = qtdemux->segment.stop) == -1)
5755           stop = qtdemux->segment.duration;
5756
5757         if (qtdemux->segment.rate >= 0) {
5758           GstMessage *message;
5759           GstEvent *event;
5760
5761           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5762           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5763               GST_FORMAT_TIME, stop);
5764           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5765           if (qtdemux->segment_seqnum) {
5766             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5767             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5768           }
5769           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5770           gst_qtdemux_push_event (qtdemux, event);
5771         } else {
5772           GstMessage *message;
5773           GstEvent *event;
5774
5775           /*  For Reverse Playback */
5776           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5777           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5778               GST_FORMAT_TIME, qtdemux->segment.start);
5779           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5780               qtdemux->segment.start);
5781           if (qtdemux->segment_seqnum) {
5782             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5783             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5784           }
5785           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5786           gst_qtdemux_push_event (qtdemux, event);
5787         }
5788       } else {
5789         GstEvent *event;
5790
5791         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5792         event = gst_event_new_eos ();
5793         if (qtdemux->segment_seqnum)
5794           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5795         gst_qtdemux_push_event (qtdemux, event);
5796       }
5797     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5798       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
5799       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5800     }
5801     goto done;
5802   }
5803 }
5804
5805 /*
5806  * has_next_entry
5807  *
5808  * Returns if there are samples to be played.
5809  */
5810 static gboolean
5811 has_next_entry (GstQTDemux * demux)
5812 {
5813   QtDemuxStream *stream;
5814   int i;
5815
5816   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5817
5818   for (i = 0; i < demux->n_streams; i++) {
5819     stream = demux->streams[i];
5820
5821     if (stream->sample_index == -1) {
5822       stream->sample_index = 0;
5823       stream->offset_in_sample = 0;
5824     }
5825
5826     if (stream->sample_index >= stream->n_samples) {
5827       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5828       continue;
5829     }
5830     GST_DEBUG_OBJECT (demux, "Found a sample");
5831     return TRUE;
5832   }
5833
5834   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5835   return FALSE;
5836 }
5837
5838 /*
5839  * next_entry_size
5840  *
5841  * Returns the size of the first entry at the current offset.
5842  * If -1, there are none (which means EOS or empty file).
5843  */
5844 static guint64
5845 next_entry_size (GstQTDemux * demux)
5846 {
5847   QtDemuxStream *stream;
5848   int i;
5849   int smallidx = -1;
5850   guint64 smalloffs = (guint64) - 1;
5851   QtDemuxSample *sample;
5852
5853   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5854       demux->offset);
5855
5856   for (i = 0; i < demux->n_streams; i++) {
5857     stream = demux->streams[i];
5858
5859     if (stream->sample_index == -1) {
5860       stream->sample_index = 0;
5861       stream->offset_in_sample = 0;
5862     }
5863
5864     if (stream->sample_index >= stream->n_samples) {
5865       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5866       continue;
5867     }
5868
5869     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5870       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5871           stream->sample_index);
5872       return -1;
5873     }
5874
5875     sample = &stream->samples[stream->sample_index];
5876
5877     GST_LOG_OBJECT (demux,
5878         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5879         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5880         sample->offset, sample->size);
5881
5882     if (((smalloffs == -1)
5883             || (sample->offset < smalloffs)) && (sample->size)) {
5884       smallidx = i;
5885       smalloffs = sample->offset;
5886     }
5887   }
5888
5889   GST_LOG_OBJECT (demux,
5890       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5891       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5892
5893   if (smallidx == -1)
5894     return -1;
5895
5896   stream = demux->streams[smallidx];
5897   sample = &stream->samples[stream->sample_index];
5898
5899   if (sample->offset >= demux->offset) {
5900     demux->todrop = sample->offset - demux->offset;
5901     return sample->size + demux->todrop;
5902   }
5903
5904   GST_DEBUG_OBJECT (demux,
5905       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5906   return -1;
5907 }
5908
5909 static void
5910 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5911 {
5912   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5913
5914   gst_element_post_message (GST_ELEMENT_CAST (demux),
5915       gst_message_new_element (GST_OBJECT_CAST (demux),
5916           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5917 }
5918
5919 static gboolean
5920 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5921 {
5922   GstEvent *event;
5923   gboolean res = 0;
5924
5925   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5926
5927   event =
5928       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5929       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5930       GST_SEEK_TYPE_NONE, -1);
5931
5932   /* store seqnum to drop flush events, they don't need to reach downstream */
5933   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5934   res = gst_pad_push_event (demux->sinkpad, event);
5935   demux->offset_seek_seqnum = 0;
5936
5937   return res;
5938 }
5939
5940 /* check for seekable upstream, above and beyond a mere query */
5941 static void
5942 gst_qtdemux_check_seekability (GstQTDemux * demux)
5943 {
5944   GstQuery *query;
5945   gboolean seekable = FALSE;
5946   gint64 start = -1, stop = -1;
5947
5948   if (demux->upstream_size)
5949     return;
5950
5951   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5952   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5953     GST_DEBUG_OBJECT (demux, "seeking query failed");
5954     goto done;
5955   }
5956
5957   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5958
5959   /* try harder to query upstream size if we didn't get it the first time */
5960   if (seekable && stop == -1) {
5961     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5962     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5963   }
5964
5965   /* if upstream doesn't know the size, it's likely that it's not seekable in
5966    * practice even if it technically may be seekable */
5967   if (seekable && (start != 0 || stop <= start)) {
5968     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5969     seekable = FALSE;
5970   }
5971
5972 done:
5973   gst_query_unref (query);
5974
5975   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5976       G_GUINT64_FORMAT ")", seekable, start, stop);
5977   demux->upstream_seekable = seekable;
5978   demux->upstream_size = seekable ? stop : -1;
5979 }
5980
5981 static void
5982 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5983 {
5984   g_return_if_fail (bytes <= demux->todrop);
5985
5986   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5987   gst_adapter_flush (demux->adapter, bytes);
5988   demux->neededbytes -= bytes;
5989   demux->offset += bytes;
5990   demux->todrop -= bytes;
5991 }
5992
5993 static void
5994 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5995 {
5996   if (G_UNLIKELY (demux->pending_newsegment)) {
5997     gint i;
5998
5999     gst_qtdemux_push_pending_newsegment (demux);
6000     /* clear to send tags on all streams */
6001     for (i = 0; i < demux->n_streams; i++) {
6002       QtDemuxStream *stream;
6003       stream = demux->streams[i];
6004       gst_qtdemux_push_tags (demux, stream);
6005       if (stream->sparse) {
6006         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6007         gst_pad_push_event (stream->pad,
6008             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6009       }
6010     }
6011   }
6012 }
6013
6014 static void
6015 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6016     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6017 {
6018   GstClockTime ts, dur;
6019   GstEvent *gap;
6020
6021   ts = pos;
6022   dur =
6023       stream->segments[segment_index].duration - (pos -
6024       stream->segments[segment_index].time);
6025   gap = gst_event_new_gap (ts, dur);
6026   stream->time_position += dur;
6027
6028   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6029       "segment: %" GST_PTR_FORMAT, gap);
6030   gst_pad_push_event (stream->pad, gap);
6031 }
6032
6033 static void
6034 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6035     QtDemuxStream * stream)
6036 {
6037   gint i;
6038
6039   /* Push any initial gap segments before proceeding to the
6040    * 'real' data */
6041   for (i = 0; i < stream->n_segments; i++) {
6042     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6043
6044     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6045       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6046           stream->time_position);
6047     } else {
6048       /* Only support empty segment at the beginning followed by
6049        * one non-empty segment, this was checked when parsing the
6050        * edts atom, arriving here is unexpected */
6051       g_assert (i + 1 == stream->n_segments);
6052       break;
6053     }
6054   }
6055 }
6056
6057 static GstFlowReturn
6058 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6059 {
6060   GstQTDemux *demux;
6061
6062   demux = GST_QTDEMUX (parent);
6063
6064   GST_DEBUG_OBJECT (demux,
6065       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6066       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6067       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6068       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6069       gst_buffer_get_size (inbuf), demux->offset);
6070
6071   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6072     gboolean is_gap_input = FALSE;
6073     gint i;
6074
6075     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6076
6077     for (i = 0; i < demux->n_streams; i++) {
6078       demux->streams[i]->discont = TRUE;
6079     }
6080
6081     /* Check if we can land back on our feet in the case where upstream is
6082      * handling the seeking/pushing of samples with gaps in between (like
6083      * in the case of trick-mode DASH for example) */
6084     if (demux->upstream_format_is_time
6085         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6086       gint i;
6087       for (i = 0; i < demux->n_streams; i++) {
6088         guint32 res;
6089         GST_LOG_OBJECT (demux,
6090             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6091             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6092         res =
6093             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6094             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6095         if (res != -1) {
6096           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6097           GST_LOG_OBJECT (demux,
6098               "Checking if sample %d from stream %d is valid (offset:%"
6099               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6100               sample->offset, sample->size);
6101           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6102             GST_LOG_OBJECT (demux,
6103                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6104                 res);
6105             is_gap_input = TRUE;
6106             /* We can go back to standard playback mode */
6107             demux->state = QTDEMUX_STATE_MOVIE;
6108             /* Remember which sample this stream is at */
6109             demux->streams[i]->sample_index = res;
6110             /* Finally update all push-based values to the expected values */
6111             demux->neededbytes = demux->streams[i]->samples[res].size;
6112             demux->todrop = 0;
6113             demux->offset = GST_BUFFER_OFFSET (inbuf);
6114           }
6115         }
6116       }
6117       if (!is_gap_input) {
6118         /* Reset state if it's a real discont */
6119         demux->neededbytes = 16;
6120         demux->state = QTDEMUX_STATE_INITIAL;
6121         demux->offset = GST_BUFFER_OFFSET (inbuf);
6122       }
6123     }
6124     /* Reverse fragmented playback, need to flush all we have before
6125      * consuming a new fragment.
6126      * The samples array have the timestamps calculated by accumulating the
6127      * durations but this won't work for reverse playback of fragments as
6128      * the timestamps of a subsequent fragment should be smaller than the
6129      * previously received one. */
6130     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6131       gst_qtdemux_process_adapter (demux, TRUE);
6132       for (i = 0; i < demux->n_streams; i++)
6133         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6134     }
6135   }
6136
6137   gst_adapter_push (demux->adapter, inbuf);
6138
6139   GST_DEBUG_OBJECT (demux,
6140       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6141       demux->neededbytes, gst_adapter_available (demux->adapter));
6142
6143   return gst_qtdemux_process_adapter (demux, FALSE);
6144 }
6145
6146 static GstFlowReturn
6147 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6148 {
6149   GstFlowReturn ret = GST_FLOW_OK;
6150
6151   /* we never really mean to buffer that much */
6152   if (demux->neededbytes == -1) {
6153     goto eos;
6154   }
6155
6156   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6157       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6158
6159 #ifndef GST_DISABLE_GST_DEBUG
6160     {
6161       guint64 discont_offset, distance_from_discont;
6162
6163       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6164       distance_from_discont =
6165           gst_adapter_distance_from_discont (demux->adapter);
6166
6167       GST_DEBUG_OBJECT (demux,
6168           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6169           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6170           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6171           demux->offset, discont_offset, distance_from_discont);
6172     }
6173 #endif
6174
6175     switch (demux->state) {
6176       case QTDEMUX_STATE_INITIAL:{
6177         const guint8 *data;
6178         guint32 fourcc;
6179         guint64 size;
6180
6181         gst_qtdemux_check_seekability (demux);
6182
6183         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6184
6185         /* get fourcc/length, set neededbytes */
6186         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6187             &size, &fourcc);
6188         gst_adapter_unmap (demux->adapter);
6189         data = NULL;
6190         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6191             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6192         if (size == 0) {
6193           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6194               (_("This file is invalid and cannot be played.")),
6195               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6196                   GST_FOURCC_ARGS (fourcc)));
6197           ret = GST_FLOW_ERROR;
6198           break;
6199         }
6200         if (fourcc == FOURCC_mdat) {
6201           gint next_entry = next_entry_size (demux);
6202           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6203             /* we have the headers, start playback */
6204             demux->state = QTDEMUX_STATE_MOVIE;
6205             demux->neededbytes = next_entry;
6206             demux->mdatleft = size;
6207           } else {
6208             /* no headers yet, try to get them */
6209             guint bs;
6210             gboolean res;
6211             guint64 old, target;
6212
6213           buffer_data:
6214             old = demux->offset;
6215             target = old + size;
6216
6217             /* try to jump over the atom with a seek */
6218             /* only bother if it seems worth doing so,
6219              * and avoids possible upstream/server problems */
6220             if (demux->upstream_seekable &&
6221                 demux->upstream_size > 4 * (1 << 20)) {
6222               res = qtdemux_seek_offset (demux, target);
6223             } else {
6224               GST_DEBUG_OBJECT (demux, "skipping seek");
6225               res = FALSE;
6226             }
6227
6228             if (res) {
6229               GST_DEBUG_OBJECT (demux, "seek success");
6230               /* remember the offset fo the first mdat so we can seek back to it
6231                * after we have the headers */
6232               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6233                 demux->first_mdat = old;
6234                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6235                     demux->first_mdat);
6236               }
6237               /* seek worked, continue reading */
6238               demux->offset = target;
6239               demux->neededbytes = 16;
6240               demux->state = QTDEMUX_STATE_INITIAL;
6241             } else {
6242               /* seek failed, need to buffer */
6243               demux->offset = old;
6244               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6245               /* there may be multiple mdat (or alike) buffers */
6246               /* sanity check */
6247               if (demux->mdatbuffer)
6248                 bs = gst_buffer_get_size (demux->mdatbuffer);
6249               else
6250                 bs = 0;
6251               if (size + bs > 10 * (1 << 20))
6252                 goto no_moov;
6253               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6254               demux->neededbytes = size;
6255               if (!demux->mdatbuffer)
6256                 demux->mdatoffset = demux->offset;
6257             }
6258           }
6259         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6260           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6261               (_("This file is invalid and cannot be played.")),
6262               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6263                   GST_FOURCC_ARGS (fourcc), size));
6264           ret = GST_FLOW_ERROR;
6265           break;
6266         } else {
6267           /* this means we already started buffering and still no moov header,
6268            * let's continue buffering everything till we get moov */
6269           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6270                   || fourcc == FOURCC_moof))
6271             goto buffer_data;
6272           demux->neededbytes = size;
6273           demux->state = QTDEMUX_STATE_HEADER;
6274         }
6275         break;
6276       }
6277       case QTDEMUX_STATE_HEADER:{
6278         const guint8 *data;
6279         guint32 fourcc;
6280
6281         GST_DEBUG_OBJECT (demux, "In header");
6282
6283         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6284
6285         /* parse the header */
6286         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6287             &fourcc);
6288         if (fourcc == FOURCC_moov) {
6289           gint n;
6290
6291           /* in usual fragmented setup we could try to scan for more
6292            * and end up at the the moov (after mdat) again */
6293           if (demux->got_moov && demux->n_streams > 0 &&
6294               (!demux->fragmented
6295                   || demux->last_moov_offset == demux->offset)) {
6296             GST_DEBUG_OBJECT (demux,
6297                 "Skipping moov atom as we have (this) one already");
6298           } else {
6299             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6300
6301             if (demux->got_moov && demux->fragmented) {
6302               GST_DEBUG_OBJECT (demux,
6303                   "Got a second moov, clean up data from old one");
6304               if (demux->moov_node)
6305                 g_node_destroy (demux->moov_node);
6306               demux->moov_node = NULL;
6307               demux->moov_node_compressed = NULL;
6308             } else {
6309               /* prepare newsegment to send when streaming actually starts */
6310               if (!demux->pending_newsegment) {
6311                 demux->pending_newsegment =
6312                     gst_event_new_segment (&demux->segment);
6313                 if (demux->segment_seqnum)
6314                   gst_event_set_seqnum (demux->pending_newsegment,
6315                       demux->segment_seqnum);
6316               }
6317             }
6318
6319             demux->last_moov_offset = demux->offset;
6320
6321             qtdemux_parse_moov (demux, data, demux->neededbytes);
6322             qtdemux_node_dump (demux, demux->moov_node);
6323             qtdemux_parse_tree (demux);
6324             qtdemux_prepare_streams (demux);
6325             if (!demux->got_moov)
6326               qtdemux_expose_streams (demux);
6327             else {
6328
6329               for (n = 0; n < demux->n_streams; n++) {
6330                 QtDemuxStream *stream = demux->streams[n];
6331
6332                 gst_qtdemux_configure_stream (demux, stream);
6333               }
6334             }
6335
6336             demux->got_moov = TRUE;
6337             gst_qtdemux_check_send_pending_segment (demux);
6338
6339             /* fragmented streams headers shouldn't contain edts atoms */
6340             if (!demux->fragmented) {
6341               for (n = 0; n < demux->n_streams; n++) {
6342                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6343                     demux->streams[n]);
6344               }
6345             }
6346
6347             g_node_destroy (demux->moov_node);
6348             demux->moov_node = NULL;
6349             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6350           }
6351         } else if (fourcc == FOURCC_moof) {
6352           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6353             guint64 dist = 0;
6354             GstClockTime prev_pts;
6355             guint64 prev_offset;
6356             guint64 adapter_discont_offset, adapter_discont_dist;
6357
6358             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6359
6360             /*
6361              * The timestamp of the moof buffer is relevant as some scenarios
6362              * won't have the initial timestamp in the atoms. Whenever a new
6363              * buffer has started, we get that buffer's PTS and use it as a base
6364              * timestamp for the trun entries.
6365              *
6366              * To keep track of the current buffer timestamp and starting point
6367              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6368              * from the beggining of the buffer, with the distance and demux->offset
6369              * we know if it is still the same buffer or not.
6370              */
6371             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6372             prev_offset = demux->offset - dist;
6373             if (demux->fragment_start_offset == -1
6374                 || prev_offset > demux->fragment_start_offset) {
6375               demux->fragment_start_offset = prev_offset;
6376               demux->fragment_start = prev_pts;
6377               GST_DEBUG_OBJECT (demux,
6378                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6379                   GST_TIME_FORMAT, demux->fragment_start_offset,
6380                   GST_TIME_ARGS (demux->fragment_start));
6381             }
6382
6383             /* We can't use prev_offset() here because this would require
6384              * upstream to set consistent and correct offsets on all buffers
6385              * since the discont. Nothing ever did that in the past and we
6386              * would break backwards compatibility here then.
6387              * Instead take the offset we had at the last discont and count
6388              * the bytes from there. This works with old code as there would
6389              * be no discont between moov and moof, and also works with
6390              * adaptivedemux which correctly sets offset and will set the
6391              * DISCONT flag accordingly when needed.
6392              *
6393              * We also only do this for upstream TIME segments as otherwise
6394              * there are potential backwards compatibility problems with
6395              * seeking in PUSH mode and upstream providing inconsistent
6396              * timestamps. */
6397             adapter_discont_offset =
6398                 gst_adapter_offset_at_discont (demux->adapter);
6399             adapter_discont_dist =
6400                 gst_adapter_distance_from_discont (demux->adapter);
6401
6402             GST_DEBUG_OBJECT (demux,
6403                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6404                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6405                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6406
6407             if (demux->upstream_format_is_time) {
6408               demux->moof_offset = adapter_discont_offset;
6409               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6410                 demux->moof_offset += adapter_discont_dist;
6411               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6412                 demux->moof_offset = demux->offset;
6413             } else {
6414               demux->moof_offset = demux->offset;
6415             }
6416
6417             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6418                     demux->moof_offset, NULL)) {
6419               gst_adapter_unmap (demux->adapter);
6420               ret = GST_FLOW_ERROR;
6421               goto done;
6422             }
6423             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6424             if (demux->mss_mode && !demux->exposed) {
6425               if (!demux->pending_newsegment) {
6426                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6427                 demux->pending_newsegment =
6428                     gst_event_new_segment (&demux->segment);
6429                 if (demux->segment_seqnum)
6430                   gst_event_set_seqnum (demux->pending_newsegment,
6431                       demux->segment_seqnum);
6432               }
6433               qtdemux_expose_streams (demux);
6434             }
6435           } else {
6436             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6437           }
6438         } else if (fourcc == FOURCC_ftyp) {
6439           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6440           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6441         } else if (fourcc == FOURCC_uuid) {
6442           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6443           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6444         } else if (fourcc == FOURCC_sidx) {
6445           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6446           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6447         } else {
6448           GST_WARNING_OBJECT (demux,
6449               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6450               GST_FOURCC_ARGS (fourcc));
6451           /* Let's jump that one and go back to initial state */
6452         }
6453         gst_adapter_unmap (demux->adapter);
6454         data = NULL;
6455
6456         if (demux->mdatbuffer && demux->n_streams) {
6457           gsize remaining_data_size = 0;
6458
6459           /* the mdat was before the header */
6460           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6461               demux->n_streams, demux->mdatbuffer);
6462           /* restore our adapter/offset view of things with upstream;
6463            * put preceding buffered data ahead of current moov data.
6464            * This should also handle evil mdat, moov, mdat cases and alike */
6465           gst_adapter_flush (demux->adapter, demux->neededbytes);
6466
6467           /* Store any remaining data after the mdat for later usage */
6468           remaining_data_size = gst_adapter_available (demux->adapter);
6469           if (remaining_data_size > 0) {
6470             g_assert (demux->restoredata_buffer == NULL);
6471             demux->restoredata_buffer =
6472                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6473             demux->restoredata_offset = demux->offset + demux->neededbytes;
6474             GST_DEBUG_OBJECT (demux,
6475                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6476                 G_GUINT64_FORMAT, remaining_data_size,
6477                 demux->restoredata_offset);
6478           }
6479
6480           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6481           demux->mdatbuffer = NULL;
6482           demux->offset = demux->mdatoffset;
6483           demux->neededbytes = next_entry_size (demux);
6484           demux->state = QTDEMUX_STATE_MOVIE;
6485           demux->mdatleft = gst_adapter_available (demux->adapter);
6486         } else {
6487           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6488           gst_adapter_flush (demux->adapter, demux->neededbytes);
6489
6490           /* only go back to the mdat if there are samples to play */
6491           if (demux->got_moov && demux->first_mdat != -1
6492               && has_next_entry (demux)) {
6493             gboolean res;
6494
6495             /* we need to seek back */
6496             res = qtdemux_seek_offset (demux, demux->first_mdat);
6497             if (res) {
6498               demux->offset = demux->first_mdat;
6499             } else {
6500               GST_DEBUG_OBJECT (demux, "Seek back failed");
6501             }
6502           } else {
6503             demux->offset += demux->neededbytes;
6504           }
6505           demux->neededbytes = 16;
6506           demux->state = QTDEMUX_STATE_INITIAL;
6507         }
6508
6509         break;
6510       }
6511       case QTDEMUX_STATE_BUFFER_MDAT:{
6512         GstBuffer *buf;
6513         guint8 fourcc[4];
6514
6515         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6516             demux->offset);
6517         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6518         gst_buffer_extract (buf, 0, fourcc, 4);
6519         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6520             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6521         if (demux->mdatbuffer)
6522           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6523         else
6524           demux->mdatbuffer = buf;
6525         demux->offset += demux->neededbytes;
6526         demux->neededbytes = 16;
6527         demux->state = QTDEMUX_STATE_INITIAL;
6528         gst_qtdemux_post_progress (demux, 1, 1);
6529
6530         break;
6531       }
6532       case QTDEMUX_STATE_MOVIE:{
6533         QtDemuxStream *stream = NULL;
6534         QtDemuxSample *sample;
6535         int i = -1;
6536         GstClockTime dts, pts, duration;
6537         gboolean keyframe;
6538
6539         GST_DEBUG_OBJECT (demux,
6540             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6541
6542         if (demux->fragmented) {
6543           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6544               demux->mdatleft);
6545           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6546             /* if needed data starts within this atom,
6547              * then it should not exceed this atom */
6548             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6549               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6550                   (_("This file is invalid and cannot be played.")),
6551                   ("sample data crosses atom boundary"));
6552               ret = GST_FLOW_ERROR;
6553               break;
6554             }
6555             demux->mdatleft -= demux->neededbytes;
6556           } else {
6557             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6558             /* so we are dropping more than left in this atom */
6559             gst_qtdemux_drop_data (demux, demux->mdatleft);
6560             demux->mdatleft = 0;
6561
6562             /* need to resume atom parsing so we do not miss any other pieces */
6563             demux->state = QTDEMUX_STATE_INITIAL;
6564             demux->neededbytes = 16;
6565
6566             /* check if there was any stored post mdat data from previous buffers */
6567             if (demux->restoredata_buffer) {
6568               g_assert (gst_adapter_available (demux->adapter) == 0);
6569
6570               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6571               demux->restoredata_buffer = NULL;
6572               demux->offset = demux->restoredata_offset;
6573             }
6574
6575             break;
6576           }
6577         }
6578
6579         if (demux->todrop) {
6580           if (demux->cenc_aux_info_offset > 0) {
6581             GstByteReader br;
6582             const guint8 *data;
6583
6584             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6585             data = gst_adapter_map (demux->adapter, demux->todrop);
6586             gst_byte_reader_init (&br, data + 8, demux->todrop);
6587             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6588                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6589               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6590               ret = GST_FLOW_ERROR;
6591               gst_adapter_unmap (demux->adapter);
6592               g_free (demux->cenc_aux_info_sizes);
6593               demux->cenc_aux_info_sizes = NULL;
6594               goto done;
6595             }
6596             demux->cenc_aux_info_offset = 0;
6597             g_free (demux->cenc_aux_info_sizes);
6598             demux->cenc_aux_info_sizes = NULL;
6599             gst_adapter_unmap (demux->adapter);
6600           }
6601           gst_qtdemux_drop_data (demux, demux->todrop);
6602         }
6603
6604         /* first buffer? */
6605         /* initial newsegment sent here after having added pads,
6606          * possible others in sink_event */
6607         gst_qtdemux_check_send_pending_segment (demux);
6608
6609         /* Figure out which stream this packet belongs to */
6610         for (i = 0; i < demux->n_streams; i++) {
6611           stream = demux->streams[i];
6612           if (stream->sample_index >= stream->n_samples)
6613             continue;
6614           GST_LOG_OBJECT (demux,
6615               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6616               " / size:%d)", i, stream->sample_index,
6617               stream->samples[stream->sample_index].offset,
6618               stream->samples[stream->sample_index].size);
6619
6620           if (stream->samples[stream->sample_index].offset == demux->offset)
6621             break;
6622         }
6623
6624         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6625           goto unknown_stream;
6626
6627         if (stream->new_caps) {
6628           gst_qtdemux_configure_stream (demux, stream);
6629         }
6630
6631         /* Put data in a buffer, set timestamps, caps, ... */
6632         sample = &stream->samples[stream->sample_index];
6633
6634         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6635           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6636               GST_FOURCC_ARGS (stream->fourcc));
6637
6638           dts = QTSAMPLE_DTS (stream, sample);
6639           pts = QTSAMPLE_PTS (stream, sample);
6640           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6641           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6642
6643           /* check for segment end */
6644           if (G_UNLIKELY (demux->segment.stop != -1
6645                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6646             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6647             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6648
6649             /* skip this data, stream is EOS */
6650             gst_adapter_flush (demux->adapter, demux->neededbytes);
6651
6652             /* check if all streams are eos */
6653             ret = GST_FLOW_EOS;
6654             for (i = 0; i < demux->n_streams; i++) {
6655               if (!STREAM_IS_EOS (demux->streams[i])) {
6656                 ret = GST_FLOW_OK;
6657                 break;
6658               }
6659             }
6660
6661             if (ret == GST_FLOW_EOS) {
6662               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6663               goto eos;
6664             }
6665           } else {
6666             GstBuffer *outbuf;
6667
6668             outbuf =
6669                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6670
6671             /* FIXME: should either be an assert or a plain check */
6672             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6673
6674             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6675                 dts, pts, duration, keyframe, dts, demux->offset);
6676           }
6677
6678           /* combine flows */
6679           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6680           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6681             goto non_ok_unlinked_flow;
6682         } else {
6683           /* skip this data, stream is EOS */
6684           gst_adapter_flush (demux->adapter, demux->neededbytes);
6685         }
6686
6687         stream->sample_index++;
6688         stream->offset_in_sample = 0;
6689
6690         /* update current offset and figure out size of next buffer */
6691         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6692             demux->offset, demux->neededbytes);
6693         demux->offset += demux->neededbytes;
6694         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6695             demux->offset);
6696
6697         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6698           if (demux->fragmented) {
6699             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6700             /* there may be more to follow, only finish this atom */
6701             demux->todrop = demux->mdatleft;
6702             demux->neededbytes = demux->todrop;
6703             break;
6704           }
6705           goto eos;
6706         }
6707         break;
6708       }
6709       default:
6710         goto invalid_state;
6711     }
6712   }
6713
6714   /* when buffering movie data, at least show user something is happening */
6715   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6716       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6717     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6718         demux->neededbytes);
6719   }
6720 done:
6721
6722   return ret;
6723
6724   /* ERRORS */
6725 non_ok_unlinked_flow:
6726   {
6727     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6728         gst_flow_get_name (ret));
6729     return ret;
6730   }
6731 unknown_stream:
6732   {
6733     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6734     ret = GST_FLOW_ERROR;
6735     goto done;
6736   }
6737 eos:
6738   {
6739     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6740     ret = GST_FLOW_EOS;
6741     goto done;
6742   }
6743 invalid_state:
6744   {
6745     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6746         (NULL), ("qtdemuxer invalid state %d", demux->state));
6747     ret = GST_FLOW_ERROR;
6748     goto done;
6749   }
6750 no_moov:
6751   {
6752     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6753         (NULL), ("no 'moov' atom within the first 10 MB"));
6754     ret = GST_FLOW_ERROR;
6755     goto done;
6756   }
6757 }
6758
6759 static gboolean
6760 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6761 {
6762   GstQuery *query;
6763   gboolean pull_mode;
6764
6765   query = gst_query_new_scheduling ();
6766
6767   if (!gst_pad_peer_query (sinkpad, query)) {
6768     gst_query_unref (query);
6769     goto activate_push;
6770   }
6771
6772   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6773       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6774   gst_query_unref (query);
6775
6776   if (!pull_mode)
6777     goto activate_push;
6778
6779   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6780   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6781
6782 activate_push:
6783   {
6784     GST_DEBUG_OBJECT (sinkpad, "activating push");
6785     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6786   }
6787 }
6788
6789 static gboolean
6790 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6791     GstPadMode mode, gboolean active)
6792 {
6793   gboolean res;
6794   GstQTDemux *demux = GST_QTDEMUX (parent);
6795
6796   switch (mode) {
6797     case GST_PAD_MODE_PUSH:
6798       demux->pullbased = FALSE;
6799       res = TRUE;
6800       break;
6801     case GST_PAD_MODE_PULL:
6802       if (active) {
6803         demux->pullbased = TRUE;
6804         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6805             sinkpad, NULL);
6806       } else {
6807         res = gst_pad_stop_task (sinkpad);
6808       }
6809       break;
6810     default:
6811       res = FALSE;
6812       break;
6813   }
6814   return res;
6815 }
6816
6817 #ifdef HAVE_ZLIB
6818 static void *
6819 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6820 {
6821   return g_malloc (items * size);
6822 }
6823
6824 static void
6825 qtdemux_zfree (void *opaque, void *addr)
6826 {
6827   g_free (addr);
6828 }
6829
6830 static void *
6831 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6832 {
6833   guint8 *buffer;
6834   z_stream *z;
6835   int ret;
6836
6837   z = g_new0 (z_stream, 1);
6838   z->zalloc = qtdemux_zalloc;
6839   z->zfree = qtdemux_zfree;
6840   z->opaque = NULL;
6841
6842   z->next_in = z_buffer;
6843   z->avail_in = z_length;
6844
6845   buffer = (guint8 *) g_malloc (length);
6846   ret = inflateInit (z);
6847   while (z->avail_in > 0) {
6848     if (z->avail_out == 0) {
6849       length += 1024;
6850       buffer = (guint8 *) g_realloc (buffer, length);
6851       z->next_out = buffer + z->total_out;
6852       z->avail_out = 1024;
6853     }
6854     ret = inflate (z, Z_SYNC_FLUSH);
6855     if (ret != Z_OK)
6856       break;
6857   }
6858   if (ret != Z_STREAM_END) {
6859     g_warning ("inflate() returned %d", ret);
6860   }
6861
6862   g_free (z);
6863   return buffer;
6864 }
6865 #endif /* HAVE_ZLIB */
6866
6867 static gboolean
6868 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6869 {
6870   GNode *cmov;
6871
6872   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6873
6874   /* counts as header data */
6875   qtdemux->header_size += length;
6876
6877   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6878   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6879
6880   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6881   if (cmov) {
6882     guint32 method;
6883     GNode *dcom;
6884     GNode *cmvd;
6885
6886     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6887     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6888     if (dcom == NULL || cmvd == NULL)
6889       goto invalid_compression;
6890
6891     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6892     switch (method) {
6893 #ifdef HAVE_ZLIB
6894       case FOURCC_zlib:{
6895         guint uncompressed_length;
6896         guint compressed_length;
6897         guint8 *buf;
6898
6899         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6900         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6901         GST_LOG ("length = %u", uncompressed_length);
6902
6903         buf =
6904             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6905             compressed_length, uncompressed_length);
6906
6907         qtdemux->moov_node_compressed = qtdemux->moov_node;
6908         qtdemux->moov_node = g_node_new (buf);
6909
6910         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6911             uncompressed_length);
6912         break;
6913       }
6914 #endif /* HAVE_ZLIB */
6915       default:
6916         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6917             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6918         break;
6919     }
6920   }
6921   return TRUE;
6922
6923   /* ERRORS */
6924 invalid_compression:
6925   {
6926     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6927     return FALSE;
6928   }
6929 }
6930
6931 static gboolean
6932 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6933     const guint8 * end)
6934 {
6935   while (G_UNLIKELY (buf < end)) {
6936     GNode *child;
6937     guint32 len;
6938
6939     if (G_UNLIKELY (buf + 4 > end)) {
6940       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6941       break;
6942     }
6943     len = QT_UINT32 (buf);
6944     if (G_UNLIKELY (len == 0)) {
6945       GST_LOG_OBJECT (qtdemux, "empty container");
6946       break;
6947     }
6948     if (G_UNLIKELY (len < 8)) {
6949       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6950       break;
6951     }
6952     if (G_UNLIKELY (len > (end - buf))) {
6953       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6954           (gint) (end - buf));
6955       break;
6956     }
6957
6958     child = g_node_new ((guint8 *) buf);
6959     g_node_append (node, child);
6960     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6961     qtdemux_parse_node (qtdemux, child, buf, len);
6962
6963     buf += len;
6964   }
6965   return TRUE;
6966 }
6967
6968 static gboolean
6969 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6970     GNode * xdxt)
6971 {
6972   int len = QT_UINT32 (xdxt->data);
6973   guint8 *buf = xdxt->data;
6974   guint8 *end = buf + len;
6975   GstBuffer *buffer;
6976
6977   /* skip size and type */
6978   buf += 8;
6979   end -= 8;
6980
6981   while (buf < end) {
6982     gint size;
6983     guint32 type;
6984
6985     size = QT_UINT32 (buf);
6986     type = QT_FOURCC (buf + 4);
6987
6988     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6989
6990     if (buf + size > end || size <= 0)
6991       break;
6992
6993     buf += 8;
6994     size -= 8;
6995
6996     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6997         GST_FOURCC_ARGS (type));
6998
6999     switch (type) {
7000       case FOURCC_tCtH:
7001         buffer = gst_buffer_new_and_alloc (size);
7002         gst_buffer_fill (buffer, 0, buf, size);
7003         stream->buffers = g_slist_append (stream->buffers, buffer);
7004         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7005         break;
7006       case FOURCC_tCt_:
7007         buffer = gst_buffer_new_and_alloc (size);
7008         gst_buffer_fill (buffer, 0, buf, size);
7009         stream->buffers = g_slist_append (stream->buffers, buffer);
7010         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7011         break;
7012       case FOURCC_tCtC:
7013         buffer = gst_buffer_new_and_alloc (size);
7014         gst_buffer_fill (buffer, 0, buf, size);
7015         stream->buffers = g_slist_append (stream->buffers, buffer);
7016         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7017         break;
7018       default:
7019         GST_WARNING_OBJECT (qtdemux,
7020             "unknown theora cookie %" GST_FOURCC_FORMAT,
7021             GST_FOURCC_ARGS (type));
7022         break;
7023     }
7024     buf += size;
7025   }
7026   return TRUE;
7027 }
7028
7029 static gboolean
7030 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7031     guint length)
7032 {
7033   guint32 fourcc = 0;
7034   guint32 node_length = 0;
7035   const QtNodeType *type;
7036   const guint8 *end;
7037
7038   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7039
7040   if (G_UNLIKELY (length < 8))
7041     goto not_enough_data;
7042
7043   node_length = QT_UINT32 (buffer);
7044   fourcc = QT_FOURCC (buffer + 4);
7045
7046   /* ignore empty nodes */
7047   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7048     return TRUE;
7049
7050   type = qtdemux_type_get (fourcc);
7051
7052   end = buffer + length;
7053
7054   GST_LOG_OBJECT (qtdemux,
7055       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7056       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7057
7058   if (node_length > length)
7059     goto broken_atom_size;
7060
7061   if (type->flags & QT_FLAG_CONTAINER) {
7062     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7063   } else {
7064     switch (fourcc) {
7065       case FOURCC_stsd:
7066       {
7067         if (node_length < 20) {
7068           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7069           break;
7070         }
7071         GST_DEBUG_OBJECT (qtdemux,
7072             "parsing stsd (sample table, sample description) atom");
7073         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7074         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7075         break;
7076       }
7077       case FOURCC_mp4a:
7078       case FOURCC_alac:
7079       {
7080         guint32 version;
7081         guint32 offset;
7082         guint min_size;
7083
7084         /* also read alac (or whatever) in stead of mp4a in the following,
7085          * since a similar layout is used in other cases as well */
7086         if (fourcc == FOURCC_mp4a)
7087           min_size = 20;
7088         else
7089           min_size = 40;
7090
7091         /* There are two things we might encounter here: a true mp4a atom, and
7092            an mp4a entry in an stsd atom. The latter is what we're interested
7093            in, and it looks like an atom, but isn't really one. The true mp4a
7094            atom is short, so we detect it based on length here. */
7095         if (length < min_size) {
7096           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7097               GST_FOURCC_ARGS (fourcc));
7098           break;
7099         }
7100
7101         /* 'version' here is the sound sample description version. Types 0 and
7102            1 are documented in the QTFF reference, but type 2 is not: it's
7103            described in Apple header files instead (struct SoundDescriptionV2
7104            in Movies.h) */
7105         version = QT_UINT16 (buffer + 16);
7106
7107         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7108             GST_FOURCC_ARGS (fourcc), version);
7109
7110         /* parse any esds descriptors */
7111         switch (version) {
7112           case 0:
7113             offset = 0x24;
7114             break;
7115           case 1:
7116             offset = 0x34;
7117             break;
7118           case 2:
7119             offset = 0x48;
7120             break;
7121           default:
7122             GST_WARNING_OBJECT (qtdemux,
7123                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7124                 GST_FOURCC_ARGS (fourcc), version);
7125             offset = 0;
7126             break;
7127         }
7128         if (offset)
7129           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7130         break;
7131       }
7132       case FOURCC_mp4v:
7133       case FOURCC_MP4V:
7134       case FOURCC_fmp4:
7135       case FOURCC_FMP4:
7136       case FOURCC_apcs:
7137       case FOURCC_apch:
7138       case FOURCC_apcn:
7139       case FOURCC_apco:
7140       case FOURCC_ap4h:
7141       {
7142         const guint8 *buf;
7143         guint32 version;
7144         int tlen;
7145
7146         /* codec_data is contained inside these atoms, which all have
7147          * the same format. */
7148
7149         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7150             GST_FOURCC_ARGS (fourcc));
7151         version = QT_UINT32 (buffer + 16);
7152         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7153         if (1 || version == 0x00000000) {
7154           buf = buffer + 0x32;
7155
7156           /* FIXME Quicktime uses PASCAL string while
7157            * the iso format uses C strings. Check the file
7158            * type before attempting to parse the string here. */
7159           tlen = QT_UINT8 (buf);
7160           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
7161           buf++;
7162           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
7163           /* the string has a reserved space of 32 bytes so skip
7164            * the remaining 31 */
7165           buf += 31;
7166           buf += 4;             /* and 4 bytes reserved */
7167
7168           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
7169
7170           qtdemux_parse_container (qtdemux, node, buf, end);
7171         }
7172         break;
7173       }
7174       case FOURCC_H264:
7175       {
7176         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
7177         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7178         break;
7179       }
7180       case FOURCC_avc1:
7181       {
7182         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
7183         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7184         break;
7185       }
7186       case FOURCC_avc3:
7187       {
7188         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
7189         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7190         break;
7191       }
7192       case FOURCC_H265:
7193       {
7194         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
7195         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7196         break;
7197       }
7198       case FOURCC_hvc1:
7199       {
7200         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
7201         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7202         break;
7203       }
7204       case FOURCC_hev1:
7205       {
7206         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
7207         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7208         break;
7209       }
7210       case FOURCC_mjp2:
7211       {
7212         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7213         break;
7214       }
7215       case FOURCC_meta:
7216       {
7217         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7218         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7219         break;
7220       }
7221       case FOURCC_mp4s:
7222       {
7223         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7224         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7225         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7226         break;
7227       }
7228       case FOURCC_XiTh:
7229       {
7230         guint32 version;
7231         guint32 offset;
7232
7233         version = QT_UINT32 (buffer + 12);
7234         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7235
7236         switch (version) {
7237           case 0x00000001:
7238             offset = 0x62;
7239             break;
7240           default:
7241             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7242             offset = 0;
7243             break;
7244         }
7245         if (offset)
7246           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7247         break;
7248       }
7249       case FOURCC_in24:
7250       {
7251         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7252         break;
7253       }
7254       case FOURCC_uuid:
7255       {
7256         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7257         break;
7258       }
7259       case FOURCC_encv:
7260       {
7261         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7262         break;
7263       }
7264       case FOURCC_enca:
7265       {
7266         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7267         break;
7268       }
7269       default:
7270         if (!strcmp (type->name, "unknown"))
7271           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7272         break;
7273     }
7274   }
7275   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7276       GST_FOURCC_ARGS (fourcc));
7277   return TRUE;
7278
7279 /* ERRORS */
7280 not_enough_data:
7281   {
7282     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7283         (_("This file is corrupt and cannot be played.")),
7284         ("Not enough data for an atom header, got only %u bytes", length));
7285     return FALSE;
7286   }
7287 broken_atom_size:
7288   {
7289     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7290         (_("This file is corrupt and cannot be played.")),
7291         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7292             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7293             length));
7294     return FALSE;
7295   }
7296 }
7297
7298 static GNode *
7299 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7300 {
7301   GNode *child;
7302   guint8 *buffer;
7303   guint32 child_fourcc;
7304
7305   for (child = g_node_first_child (node); child;
7306       child = g_node_next_sibling (child)) {
7307     buffer = (guint8 *) child->data;
7308
7309     child_fourcc = QT_FOURCC (buffer + 4);
7310
7311     if (G_UNLIKELY (child_fourcc == fourcc)) {
7312       return child;
7313     }
7314   }
7315   return NULL;
7316 }
7317
7318 static GNode *
7319 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7320     GstByteReader * parser)
7321 {
7322   GNode *child;
7323   guint8 *buffer;
7324   guint32 child_fourcc, child_len;
7325
7326   for (child = g_node_first_child (node); child;
7327       child = g_node_next_sibling (child)) {
7328     buffer = (guint8 *) child->data;
7329
7330     child_len = QT_UINT32 (buffer);
7331     child_fourcc = QT_FOURCC (buffer + 4);
7332
7333     if (G_UNLIKELY (child_fourcc == fourcc)) {
7334       if (G_UNLIKELY (child_len < (4 + 4)))
7335         return NULL;
7336       /* FIXME: must verify if atom length < parent atom length */
7337       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7338       return child;
7339     }
7340   }
7341   return NULL;
7342 }
7343
7344 static GNode *
7345 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7346     GstByteReader * parser)
7347 {
7348   GNode *child;
7349   guint8 *buffer;
7350   guint32 child_fourcc, child_len;
7351
7352   for (child = g_node_next_sibling (node); child;
7353       child = g_node_next_sibling (child)) {
7354     buffer = (guint8 *) child->data;
7355
7356     child_fourcc = QT_FOURCC (buffer + 4);
7357
7358     if (child_fourcc == fourcc) {
7359       if (parser) {
7360         child_len = QT_UINT32 (buffer);
7361         if (G_UNLIKELY (child_len < (4 + 4)))
7362           return NULL;
7363         /* FIXME: must verify if atom length < parent atom length */
7364         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7365       }
7366       return child;
7367     }
7368   }
7369   return NULL;
7370 }
7371
7372 static GNode *
7373 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7374 {
7375   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7376 }
7377
7378 static void
7379 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7380 {
7381 /* FIXME: This can only reliably work if demuxers have a
7382  * separate streaming thread per srcpad. This should be
7383  * done in a demuxer base class, which integrates parts
7384  * of multiqueue
7385  *
7386  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7387  */
7388 #if 0
7389   GstQuery *query;
7390
7391   query = gst_query_new_allocation (stream->caps, FALSE);
7392
7393   if (!gst_pad_peer_query (stream->pad, query)) {
7394     /* not a problem, just debug a little */
7395     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7396   }
7397
7398   if (stream->allocator)
7399     gst_object_unref (stream->allocator);
7400
7401   if (gst_query_get_n_allocation_params (query) > 0) {
7402     /* try the allocator */
7403     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7404         &stream->params);
7405     stream->use_allocator = TRUE;
7406   } else {
7407     stream->allocator = NULL;
7408     gst_allocation_params_init (&stream->params);
7409     stream->use_allocator = FALSE;
7410   }
7411   gst_query_unref (query);
7412 #endif
7413 }
7414
7415 static gboolean
7416 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7417     QtDemuxStream * stream)
7418 {
7419   GstStructure *s;
7420   const gchar *selected_system;
7421
7422   g_return_val_if_fail (qtdemux != NULL, FALSE);
7423   g_return_val_if_fail (stream != NULL, FALSE);
7424   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7425
7426   if (stream->protection_scheme_type != FOURCC_cenc) {
7427     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7428     return FALSE;
7429   }
7430   if (qtdemux->protection_system_ids == NULL) {
7431     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7432         "cenc protection system information has been found");
7433     return FALSE;
7434   }
7435   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7436   selected_system = gst_protection_select_system ((const gchar **)
7437       qtdemux->protection_system_ids->pdata);
7438   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7439       qtdemux->protection_system_ids->len - 1);
7440   if (!selected_system) {
7441     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7442         "suitable decryptor element has been found");
7443     return FALSE;
7444   }
7445
7446   s = gst_caps_get_structure (stream->caps, 0);
7447   if (!gst_structure_has_name (s, "application/x-cenc")) {
7448     gst_structure_set (s,
7449         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7450         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7451         NULL);
7452     gst_structure_set_name (s, "application/x-cenc");
7453   }
7454   return TRUE;
7455 }
7456
7457 static gboolean
7458 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7459 {
7460   if (stream->subtype == FOURCC_vide) {
7461     /* fps is calculated base on the duration of the average framerate since
7462      * qt does not have a fixed framerate. */
7463     gboolean fps_available = TRUE;
7464
7465     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7466       /* still frame */
7467       stream->fps_n = 0;
7468       stream->fps_d = 1;
7469     } else {
7470       if (stream->duration == 0 || stream->n_samples < 2) {
7471         stream->fps_n = stream->timescale;
7472         stream->fps_d = 1;
7473         fps_available = FALSE;
7474       } else {
7475         GstClockTime avg_duration;
7476         guint64 duration;
7477         guint32 n_samples;
7478
7479         /* duration and n_samples can be updated for fragmented format
7480          * so, framerate of fragmented format is calculated using data in a moof */
7481         if (qtdemux->fragmented && stream->n_samples_moof > 0
7482             && stream->duration_moof > 0) {
7483           n_samples = stream->n_samples_moof;
7484           duration = stream->duration_moof;
7485         } else {
7486           n_samples = stream->n_samples;
7487           duration = stream->duration;
7488         }
7489
7490         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7491         /* stream->duration is guint64, timescale, n_samples are guint32 */
7492         avg_duration =
7493             gst_util_uint64_scale_round (duration -
7494             stream->first_duration, GST_SECOND,
7495             (guint64) (stream->timescale) * (n_samples - 1));
7496
7497         GST_LOG_OBJECT (qtdemux,
7498             "Calculating avg sample duration based on stream (or moof) duration %"
7499             G_GUINT64_FORMAT
7500             " minus first sample %u, leaving %d samples gives %"
7501             GST_TIME_FORMAT, duration, stream->first_duration,
7502             n_samples - 1, GST_TIME_ARGS (avg_duration));
7503
7504         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7505             &stream->fps_d);
7506
7507         GST_DEBUG_OBJECT (qtdemux,
7508             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7509             stream->timescale, stream->fps_n, stream->fps_d);
7510       }
7511     }
7512
7513     if (stream->caps) {
7514       stream->caps = gst_caps_make_writable (stream->caps);
7515
7516       gst_caps_set_simple (stream->caps,
7517           "width", G_TYPE_INT, stream->width,
7518           "height", G_TYPE_INT, stream->height, NULL);
7519
7520       /* set framerate if calculated framerate is reliable */
7521       if (fps_available) {
7522         gst_caps_set_simple (stream->caps,
7523             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7524       }
7525
7526       /* calculate pixel-aspect-ratio using display width and height */
7527       GST_DEBUG_OBJECT (qtdemux,
7528           "video size %dx%d, target display size %dx%d", stream->width,
7529           stream->height, stream->display_width, stream->display_height);
7530       /* qt file might have pasp atom */
7531       if (stream->par_w > 0 && stream->par_h > 0) {
7532         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7533         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7534             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7535       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7536           stream->width > 0 && stream->height > 0) {
7537         gint n, d;
7538
7539         /* calculate the pixel aspect ratio using the display and pixel w/h */
7540         n = stream->display_width * stream->height;
7541         d = stream->display_height * stream->width;
7542         if (n == d)
7543           n = d = 1;
7544         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7545         stream->par_w = n;
7546         stream->par_h = d;
7547         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7548             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7549       }
7550
7551       /* Create incomplete colorimetry here if needed */
7552       if (stream->colorimetry.range ||
7553           stream->colorimetry.matrix ||
7554           stream->colorimetry.transfer || stream->colorimetry.primaries) {
7555         gchar *colorimetry =
7556             gst_video_colorimetry_to_string (&stream->colorimetry);
7557         gst_caps_set_simple (stream->caps, "colorimetry", G_TYPE_STRING,
7558             colorimetry, NULL);
7559         g_free (colorimetry);
7560       }
7561
7562       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7563         guint par_w = 1, par_h = 1;
7564
7565         if (stream->par_w > 0 && stream->par_h > 0) {
7566           par_w = stream->par_w;
7567           par_h = stream->par_h;
7568         }
7569
7570         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7571                 stream->width, stream->height, par_w, par_h)) {
7572           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7573         }
7574
7575         gst_caps_set_simple (stream->caps,
7576             "multiview-mode", G_TYPE_STRING,
7577             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7578             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7579             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7580       }
7581     }
7582   }
7583
7584   else if (stream->subtype == FOURCC_soun) {
7585     if (stream->caps) {
7586       stream->caps = gst_caps_make_writable (stream->caps);
7587       if (stream->rate > 0)
7588         gst_caps_set_simple (stream->caps,
7589             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7590       if (stream->n_channels > 0)
7591         gst_caps_set_simple (stream->caps,
7592             "channels", G_TYPE_INT, stream->n_channels, NULL);
7593       if (stream->n_channels > 2) {
7594         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7595          * correctly; this is just the minimum we can do - assume
7596          * we don't actually have any channel positions. */
7597         gst_caps_set_simple (stream->caps,
7598             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7599       }
7600     }
7601   }
7602
7603   if (stream->pad) {
7604     GstCaps *prev_caps = NULL;
7605
7606     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7607     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7608     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7609     gst_pad_set_active (stream->pad, TRUE);
7610
7611     gst_pad_use_fixed_caps (stream->pad);
7612
7613     if (stream->protected) {
7614       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7615         GST_ERROR_OBJECT (qtdemux,
7616             "Failed to configure protected stream caps.");
7617         return FALSE;
7618       }
7619     }
7620
7621     if (stream->new_stream) {
7622       gchar *stream_id;
7623       GstEvent *event;
7624       GstStreamFlags stream_flags;
7625
7626       event =
7627           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7628           0);
7629       if (event) {
7630         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7631           qtdemux->have_group_id = TRUE;
7632         else
7633           qtdemux->have_group_id = FALSE;
7634         gst_event_unref (event);
7635       } else if (!qtdemux->have_group_id) {
7636         qtdemux->have_group_id = TRUE;
7637         qtdemux->group_id = gst_util_group_id_next ();
7638       }
7639
7640       stream->new_stream = FALSE;
7641       stream_id =
7642           gst_pad_create_stream_id_printf (stream->pad,
7643           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7644       event = gst_event_new_stream_start (stream_id);
7645       if (qtdemux->have_group_id)
7646         gst_event_set_group_id (event, qtdemux->group_id);
7647       stream_flags = GST_STREAM_FLAG_NONE;
7648       if (stream->disabled)
7649         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7650       if (stream->sparse)
7651         stream_flags |= GST_STREAM_FLAG_SPARSE;
7652       gst_event_set_stream_flags (event, stream_flags);
7653       gst_pad_push_event (stream->pad, event);
7654       g_free (stream_id);
7655     }
7656
7657     prev_caps = gst_pad_get_current_caps (stream->pad);
7658
7659     if (!prev_caps || !gst_caps_is_equal_fixed (prev_caps, stream->caps)) {
7660       GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7661       gst_pad_set_caps (stream->pad, stream->caps);
7662     } else {
7663       GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7664     }
7665
7666     if (prev_caps)
7667       gst_caps_unref (prev_caps);
7668     stream->new_caps = FALSE;
7669   }
7670   return TRUE;
7671 }
7672
7673 static gboolean
7674 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7675     QtDemuxStream * stream, GstTagList * list)
7676 {
7677   gboolean ret = TRUE;
7678   /* consistent default for push based mode */
7679   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7680
7681   if (stream->subtype == FOURCC_vide) {
7682     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7683
7684     stream->pad =
7685         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7686     g_free (name);
7687
7688     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7689       gst_object_unref (stream->pad);
7690       stream->pad = NULL;
7691       ret = FALSE;
7692       goto done;
7693     }
7694
7695     qtdemux->n_video_streams++;
7696   } else if (stream->subtype == FOURCC_soun) {
7697     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7698
7699     stream->pad =
7700         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7701     g_free (name);
7702     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7703       gst_object_unref (stream->pad);
7704       stream->pad = NULL;
7705       ret = FALSE;
7706       goto done;
7707     }
7708     qtdemux->n_audio_streams++;
7709   } else if (stream->subtype == FOURCC_strm) {
7710     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7711   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7712       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7713     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7714
7715     stream->pad =
7716         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7717     g_free (name);
7718     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7719       gst_object_unref (stream->pad);
7720       stream->pad = NULL;
7721       ret = FALSE;
7722       goto done;
7723     }
7724     qtdemux->n_sub_streams++;
7725   } else if (stream->caps) {
7726     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7727
7728     stream->pad =
7729         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7730     g_free (name);
7731     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7732       gst_object_unref (stream->pad);
7733       stream->pad = NULL;
7734       ret = FALSE;
7735       goto done;
7736     }
7737     qtdemux->n_video_streams++;
7738   } else {
7739     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7740     goto done;
7741   }
7742
7743   if (stream->pad) {
7744     GList *l;
7745
7746     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7747         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7748     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7749     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7750
7751     if (stream->pending_tags)
7752       gst_tag_list_unref (stream->pending_tags);
7753     stream->pending_tags = list;
7754     list = NULL;
7755     /* global tags go on each pad anyway */
7756     stream->send_global_tags = TRUE;
7757     /* send upstream GST_EVENT_PROTECTION events that were received before
7758        this source pad was created */
7759     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7760       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7761   }
7762 done:
7763   if (list)
7764     gst_tag_list_unref (list);
7765   return ret;
7766 }
7767
7768 /* find next atom with @fourcc starting at @offset */
7769 static GstFlowReturn
7770 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7771     guint64 * length, guint32 fourcc)
7772 {
7773   GstFlowReturn ret;
7774   guint32 lfourcc;
7775   GstBuffer *buf;
7776
7777   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7778       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7779
7780   while (TRUE) {
7781     GstMapInfo map;
7782
7783     buf = NULL;
7784     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7785     if (G_UNLIKELY (ret != GST_FLOW_OK))
7786       goto locate_failed;
7787     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7788       /* likely EOF */
7789       ret = GST_FLOW_EOS;
7790       gst_buffer_unref (buf);
7791       goto locate_failed;
7792     }
7793     gst_buffer_map (buf, &map, GST_MAP_READ);
7794     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7795     gst_buffer_unmap (buf, &map);
7796     gst_buffer_unref (buf);
7797
7798     if (G_UNLIKELY (*length == 0)) {
7799       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7800       ret = GST_FLOW_ERROR;
7801       goto locate_failed;
7802     }
7803
7804     if (lfourcc == fourcc) {
7805       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7806           *offset);
7807       break;
7808     } else {
7809       GST_LOG_OBJECT (qtdemux,
7810           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7811           GST_FOURCC_ARGS (fourcc), *offset);
7812       *offset += *length;
7813     }
7814   }
7815
7816   return GST_FLOW_OK;
7817
7818 locate_failed:
7819   {
7820     /* might simply have had last one */
7821     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7822     return ret;
7823   }
7824 }
7825
7826 /* should only do something in pull mode */
7827 /* call with OBJECT lock */
7828 static GstFlowReturn
7829 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7830 {
7831   guint64 length, offset;
7832   GstBuffer *buf = NULL;
7833   GstFlowReturn ret = GST_FLOW_OK;
7834   GstFlowReturn res = GST_FLOW_OK;
7835   GstMapInfo map;
7836
7837   offset = qtdemux->moof_offset;
7838   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7839
7840   if (!offset) {
7841     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7842     return GST_FLOW_EOS;
7843   }
7844
7845   /* best not do pull etc with lock held */
7846   GST_OBJECT_UNLOCK (qtdemux);
7847
7848   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7849   if (ret != GST_FLOW_OK)
7850     goto flow_failed;
7851
7852   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7853   if (G_UNLIKELY (ret != GST_FLOW_OK))
7854     goto flow_failed;
7855   gst_buffer_map (buf, &map, GST_MAP_READ);
7856   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7857     gst_buffer_unmap (buf, &map);
7858     gst_buffer_unref (buf);
7859     buf = NULL;
7860     goto parse_failed;
7861   }
7862
7863   gst_buffer_unmap (buf, &map);
7864   gst_buffer_unref (buf);
7865   buf = NULL;
7866
7867   offset += length;
7868   /* look for next moof */
7869   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7870   if (G_UNLIKELY (ret != GST_FLOW_OK))
7871     goto flow_failed;
7872
7873 exit:
7874   GST_OBJECT_LOCK (qtdemux);
7875
7876   qtdemux->moof_offset = offset;
7877
7878   return res;
7879
7880 parse_failed:
7881   {
7882     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7883     offset = 0;
7884     res = GST_FLOW_ERROR;
7885     goto exit;
7886   }
7887 flow_failed:
7888   {
7889     /* maybe upstream temporarily flushing */
7890     if (ret != GST_FLOW_FLUSHING) {
7891       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7892       offset = 0;
7893     } else {
7894       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7895       /* resume at current position next time */
7896     }
7897     res = ret;
7898     goto exit;
7899   }
7900 }
7901
7902 /* initialise bytereaders for stbl sub-atoms */
7903 static gboolean
7904 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7905 {
7906   stream->stbl_index = -1;      /* no samples have yet been parsed */
7907   stream->sample_index = -1;
7908
7909   /* time-to-sample atom */
7910   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7911     goto corrupt_file;
7912
7913   /* copy atom data into a new buffer for later use */
7914   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7915
7916   /* skip version + flags */
7917   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7918       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7919     goto corrupt_file;
7920   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7921
7922   /* make sure there's enough data */
7923   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7924     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7925     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7926         stream->n_sample_times);
7927     if (!stream->n_sample_times)
7928       goto corrupt_file;
7929   }
7930
7931   /* sync sample atom */
7932   stream->stps_present = FALSE;
7933   if ((stream->stss_present =
7934           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7935               &stream->stss) ? TRUE : FALSE) == TRUE) {
7936     /* copy atom data into a new buffer for later use */
7937     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7938
7939     /* skip version + flags */
7940     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7941         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7942       goto corrupt_file;
7943
7944     if (stream->n_sample_syncs) {
7945       /* make sure there's enough data */
7946       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7947         goto corrupt_file;
7948     }
7949
7950     /* partial sync sample atom */
7951     if ((stream->stps_present =
7952             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7953                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7954       /* copy atom data into a new buffer for later use */
7955       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7956
7957       /* skip version + flags */
7958       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7959           !gst_byte_reader_get_uint32_be (&stream->stps,
7960               &stream->n_sample_partial_syncs))
7961         goto corrupt_file;
7962
7963       /* if there are no entries, the stss table contains the real
7964        * sync samples */
7965       if (stream->n_sample_partial_syncs) {
7966         /* make sure there's enough data */
7967         if (!qt_atom_parser_has_chunks (&stream->stps,
7968                 stream->n_sample_partial_syncs, 4))
7969           goto corrupt_file;
7970       }
7971     }
7972   }
7973
7974   /* sample size */
7975   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7976     goto no_samples;
7977
7978   /* copy atom data into a new buffer for later use */
7979   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7980
7981   /* skip version + flags */
7982   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7983       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7984     goto corrupt_file;
7985
7986   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7987     goto corrupt_file;
7988
7989   if (!stream->n_samples)
7990     goto no_samples;
7991
7992   /* sample-to-chunk atom */
7993   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7994     goto corrupt_file;
7995
7996   /* copy atom data into a new buffer for later use */
7997   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7998
7999   /* skip version + flags */
8000   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8001       !gst_byte_reader_get_uint32_be (&stream->stsc,
8002           &stream->n_samples_per_chunk))
8003     goto corrupt_file;
8004
8005   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8006       stream->n_samples_per_chunk);
8007
8008   /* make sure there's enough data */
8009   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8010           12))
8011     goto corrupt_file;
8012
8013
8014   /* chunk offset */
8015   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8016     stream->co_size = sizeof (guint32);
8017   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8018           &stream->stco))
8019     stream->co_size = sizeof (guint64);
8020   else
8021     goto corrupt_file;
8022
8023   /* copy atom data into a new buffer for later use */
8024   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8025
8026   /* skip version + flags */
8027   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8028     goto corrupt_file;
8029
8030   /* chunks_are_samples == TRUE means treat chunks as samples */
8031   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
8032   if (stream->chunks_are_samples) {
8033     /* treat chunks as samples */
8034     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8035       goto corrupt_file;
8036   } else {
8037     /* skip number of entries */
8038     if (!gst_byte_reader_skip (&stream->stco, 4))
8039       goto corrupt_file;
8040
8041     /* make sure there are enough data in the stsz atom */
8042     if (!stream->sample_size) {
8043       /* different sizes for each sample */
8044       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8045         goto corrupt_file;
8046     }
8047   }
8048
8049   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8050       stream->n_samples, (guint) sizeof (QtDemuxSample),
8051       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8052
8053   if (stream->n_samples >=
8054       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8055     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8056         "be larger than %uMB (broken file?)", stream->n_samples,
8057         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8058     return FALSE;
8059   }
8060
8061   g_assert (stream->samples == NULL);
8062   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8063   if (!stream->samples) {
8064     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8065         stream->n_samples);
8066     return FALSE;
8067   }
8068
8069   /* composition time-to-sample */
8070   if ((stream->ctts_present =
8071           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8072               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8073     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8074
8075     /* copy atom data into a new buffer for later use */
8076     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8077
8078     /* skip version + flags */
8079     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8080         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8081             &stream->n_composition_times))
8082       goto corrupt_file;
8083
8084     /* make sure there's enough data */
8085     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8086             4 + 4))
8087       goto corrupt_file;
8088
8089     /* This is optional, if missing we iterate the ctts */
8090     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8091       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8092           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8093         g_free ((gpointer) cslg.data);
8094         goto corrupt_file;
8095       }
8096     } else {
8097       gint32 cslg_least = 0;
8098       guint num_entries, pos;
8099       gint i;
8100
8101       pos = gst_byte_reader_get_pos (&stream->ctts);
8102       num_entries = stream->n_composition_times;
8103
8104       stream->cslg_shift = 0;
8105
8106       for (i = 0; i < num_entries; i++) {
8107         gint32 offset;
8108
8109         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8110         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8111
8112         if (offset < cslg_least)
8113           cslg_least = offset;
8114       }
8115
8116       if (cslg_least < 0)
8117         stream->cslg_shift = ABS (cslg_least);
8118       else
8119         stream->cslg_shift = 0;
8120
8121       /* reset the reader so we can generate sample table */
8122       gst_byte_reader_set_pos (&stream->ctts, pos);
8123     }
8124   } else {
8125     /* Ensure the cslg_shift value is consistent so we can use it
8126      * unconditionnally to produce TS and Segment */
8127     stream->cslg_shift = 0;
8128   }
8129
8130   return TRUE;
8131
8132 corrupt_file:
8133   {
8134     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8135         (_("This file is corrupt and cannot be played.")), (NULL));
8136     return FALSE;
8137   }
8138 no_samples:
8139   {
8140     gst_qtdemux_stbl_free (stream);
8141     if (!qtdemux->fragmented) {
8142       /* not quite good */
8143       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8144       return FALSE;
8145     } else {
8146       /* may pick up samples elsewhere */
8147       return TRUE;
8148     }
8149   }
8150 }
8151
8152 /* collect samples from the next sample to be parsed up to sample @n for @stream
8153  * by reading the info from @stbl
8154  *
8155  * This code can be executed from both the streaming thread and the seeking
8156  * thread so it takes the object lock to protect itself
8157  */
8158 static gboolean
8159 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8160 {
8161   gint i, j, k;
8162   QtDemuxSample *samples, *first, *cur, *last;
8163   guint32 n_samples_per_chunk;
8164   guint32 n_samples;
8165
8166   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8167       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8168       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8169
8170   n_samples = stream->n_samples;
8171
8172   if (n >= n_samples)
8173     goto out_of_samples;
8174
8175   GST_OBJECT_LOCK (qtdemux);
8176   if (n <= stream->stbl_index)
8177     goto already_parsed;
8178
8179   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8180
8181   if (!stream->stsz.data) {
8182     /* so we already parsed and passed all the moov samples;
8183      * onto fragmented ones */
8184     g_assert (qtdemux->fragmented);
8185     goto done;
8186   }
8187
8188   /* pointer to the sample table */
8189   samples = stream->samples;
8190
8191   /* starts from -1, moves to the next sample index to parse */
8192   stream->stbl_index++;
8193
8194   /* keep track of the first and last sample to fill */
8195   first = &samples[stream->stbl_index];
8196   last = &samples[n];
8197
8198   if (!stream->chunks_are_samples) {
8199     /* set the sample sizes */
8200     if (stream->sample_size == 0) {
8201       /* different sizes for each sample */
8202       for (cur = first; cur <= last; cur++) {
8203         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8204         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8205             (guint) (cur - samples), cur->size);
8206       }
8207     } else {
8208       /* samples have the same size */
8209       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8210       for (cur = first; cur <= last; cur++)
8211         cur->size = stream->sample_size;
8212     }
8213   }
8214
8215   n_samples_per_chunk = stream->n_samples_per_chunk;
8216   cur = first;
8217
8218   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8219     guint32 last_chunk;
8220
8221     if (stream->stsc_chunk_index >= stream->last_chunk
8222         || stream->stsc_chunk_index < stream->first_chunk) {
8223       stream->first_chunk =
8224           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8225       stream->samples_per_chunk =
8226           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8227       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8228
8229       /* chunk numbers are counted from 1 it seems */
8230       if (G_UNLIKELY (stream->first_chunk == 0))
8231         goto corrupt_file;
8232
8233       --stream->first_chunk;
8234
8235       /* the last chunk of each entry is calculated by taking the first chunk
8236        * of the next entry; except if there is no next, where we fake it with
8237        * INT_MAX */
8238       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8239         stream->last_chunk = G_MAXUINT32;
8240       } else {
8241         stream->last_chunk =
8242             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8243         if (G_UNLIKELY (stream->last_chunk == 0))
8244           goto corrupt_file;
8245
8246         --stream->last_chunk;
8247       }
8248
8249       GST_LOG_OBJECT (qtdemux,
8250           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8251           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8252
8253       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8254         goto corrupt_file;
8255
8256       if (stream->last_chunk != G_MAXUINT32) {
8257         if (!qt_atom_parser_peek_sub (&stream->stco,
8258                 stream->first_chunk * stream->co_size,
8259                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8260                 &stream->co_chunk))
8261           goto corrupt_file;
8262
8263       } else {
8264         stream->co_chunk = stream->stco;
8265         if (!gst_byte_reader_skip (&stream->co_chunk,
8266                 stream->first_chunk * stream->co_size))
8267           goto corrupt_file;
8268       }
8269
8270       stream->stsc_chunk_index = stream->first_chunk;
8271     }
8272
8273     last_chunk = stream->last_chunk;
8274
8275     if (stream->chunks_are_samples) {
8276       cur = &samples[stream->stsc_chunk_index];
8277
8278       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8279         if (j > n) {
8280           /* save state */
8281           stream->stsc_chunk_index = j;
8282           goto done;
8283         }
8284
8285         cur->offset =
8286             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8287             stream->co_size);
8288
8289         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8290             "%" G_GUINT64_FORMAT, j, cur->offset);
8291
8292         if (stream->samples_per_frame * stream->bytes_per_frame) {
8293           cur->size =
8294               (stream->samples_per_chunk * stream->n_channels) /
8295               stream->samples_per_frame * stream->bytes_per_frame;
8296         } else {
8297           cur->size = stream->samples_per_chunk;
8298         }
8299
8300         GST_DEBUG_OBJECT (qtdemux,
8301             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8302             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8303                     stream->stco_sample_index)), cur->size);
8304
8305         cur->timestamp = stream->stco_sample_index;
8306         cur->duration = stream->samples_per_chunk;
8307         cur->keyframe = TRUE;
8308         cur++;
8309
8310         stream->stco_sample_index += stream->samples_per_chunk;
8311       }
8312       stream->stsc_chunk_index = j;
8313     } else {
8314       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8315         guint32 samples_per_chunk;
8316         guint64 chunk_offset;
8317
8318         if (!stream->stsc_sample_index
8319             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8320                 &stream->chunk_offset))
8321           goto corrupt_file;
8322
8323         samples_per_chunk = stream->samples_per_chunk;
8324         chunk_offset = stream->chunk_offset;
8325
8326         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8327           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8328               G_GUINT64_FORMAT " and size %d",
8329               (guint) (cur - samples), chunk_offset, cur->size);
8330
8331           cur->offset = chunk_offset;
8332           chunk_offset += cur->size;
8333           cur++;
8334
8335           if (G_UNLIKELY (cur > last)) {
8336             /* save state */
8337             stream->stsc_sample_index = k + 1;
8338             stream->chunk_offset = chunk_offset;
8339             stream->stsc_chunk_index = j;
8340             goto done2;
8341           }
8342         }
8343         stream->stsc_sample_index = 0;
8344       }
8345       stream->stsc_chunk_index = j;
8346     }
8347     stream->stsc_index++;
8348   }
8349
8350   if (stream->chunks_are_samples)
8351     goto ctts;
8352 done2:
8353   {
8354     guint32 n_sample_times;
8355
8356     n_sample_times = stream->n_sample_times;
8357     cur = first;
8358
8359     for (i = stream->stts_index; i < n_sample_times; i++) {
8360       guint32 stts_samples;
8361       gint32 stts_duration;
8362       gint64 stts_time;
8363
8364       if (stream->stts_sample_index >= stream->stts_samples
8365           || !stream->stts_sample_index) {
8366
8367         stream->stts_samples =
8368             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8369         stream->stts_duration =
8370             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8371
8372         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8373             i, stream->stts_samples, stream->stts_duration);
8374
8375         stream->stts_sample_index = 0;
8376       }
8377
8378       stts_samples = stream->stts_samples;
8379       stts_duration = stream->stts_duration;
8380       stts_time = stream->stts_time;
8381
8382       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8383         GST_DEBUG_OBJECT (qtdemux,
8384             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8385             (guint) (cur - samples), j,
8386             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8387
8388         cur->timestamp = stts_time;
8389         cur->duration = stts_duration;
8390
8391         /* avoid 32-bit wrap-around,
8392          * but still mind possible 'negative' duration */
8393         stts_time += (gint64) stts_duration;
8394         cur++;
8395
8396         if (G_UNLIKELY (cur > last)) {
8397           /* save values */
8398           stream->stts_time = stts_time;
8399           stream->stts_sample_index = j + 1;
8400           goto done3;
8401         }
8402       }
8403       stream->stts_sample_index = 0;
8404       stream->stts_time = stts_time;
8405       stream->stts_index++;
8406     }
8407     /* fill up empty timestamps with the last timestamp, this can happen when
8408      * the last samples do not decode and so we don't have timestamps for them.
8409      * We however look at the last timestamp to estimate the track length so we
8410      * need something in here. */
8411     for (; cur < last; cur++) {
8412       GST_DEBUG_OBJECT (qtdemux,
8413           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8414           (guint) (cur - samples),
8415           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8416       cur->timestamp = stream->stts_time;
8417       cur->duration = -1;
8418     }
8419   }
8420 done3:
8421   {
8422     /* sample sync, can be NULL */
8423     if (stream->stss_present == TRUE) {
8424       guint32 n_sample_syncs;
8425
8426       n_sample_syncs = stream->n_sample_syncs;
8427
8428       if (!n_sample_syncs) {
8429         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8430         stream->all_keyframe = TRUE;
8431       } else {
8432         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8433           /* note that the first sample is index 1, not 0 */
8434           guint32 index;
8435
8436           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8437
8438           if (G_LIKELY (index > 0 && index <= n_samples)) {
8439             index -= 1;
8440             samples[index].keyframe = TRUE;
8441             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8442             /* and exit if we have enough samples */
8443             if (G_UNLIKELY (index >= n)) {
8444               i++;
8445               break;
8446             }
8447           }
8448         }
8449         /* save state */
8450         stream->stss_index = i;
8451       }
8452
8453       /* stps marks partial sync frames like open GOP I-Frames */
8454       if (stream->stps_present == TRUE) {
8455         guint32 n_sample_partial_syncs;
8456
8457         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8458
8459         /* if there are no entries, the stss table contains the real
8460          * sync samples */
8461         if (n_sample_partial_syncs) {
8462           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8463             /* note that the first sample is index 1, not 0 */
8464             guint32 index;
8465
8466             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8467
8468             if (G_LIKELY (index > 0 && index <= n_samples)) {
8469               index -= 1;
8470               samples[index].keyframe = TRUE;
8471               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8472               /* and exit if we have enough samples */
8473               if (G_UNLIKELY (index >= n)) {
8474                 i++;
8475                 break;
8476               }
8477             }
8478           }
8479           /* save state */
8480           stream->stps_index = i;
8481         }
8482       }
8483     } else {
8484       /* no stss, all samples are keyframes */
8485       stream->all_keyframe = TRUE;
8486       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8487     }
8488   }
8489
8490 ctts:
8491   /* composition time to sample */
8492   if (stream->ctts_present == TRUE) {
8493     guint32 n_composition_times;
8494     guint32 ctts_count;
8495     gint32 ctts_soffset;
8496
8497     /* Fill in the pts_offsets */
8498     cur = first;
8499     n_composition_times = stream->n_composition_times;
8500
8501     for (i = stream->ctts_index; i < n_composition_times; i++) {
8502       if (stream->ctts_sample_index >= stream->ctts_count
8503           || !stream->ctts_sample_index) {
8504         stream->ctts_count =
8505             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8506         stream->ctts_soffset =
8507             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8508         stream->ctts_sample_index = 0;
8509       }
8510
8511       ctts_count = stream->ctts_count;
8512       ctts_soffset = stream->ctts_soffset;
8513
8514       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8515         cur->pts_offset = ctts_soffset;
8516         cur++;
8517
8518         if (G_UNLIKELY (cur > last)) {
8519           /* save state */
8520           stream->ctts_sample_index = j + 1;
8521           goto done;
8522         }
8523       }
8524       stream->ctts_sample_index = 0;
8525       stream->ctts_index++;
8526     }
8527   }
8528 done:
8529   stream->stbl_index = n;
8530   /* if index has been completely parsed, free data that is no-longer needed */
8531   if (n + 1 == stream->n_samples) {
8532     gst_qtdemux_stbl_free (stream);
8533     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8534     if (qtdemux->pullbased) {
8535       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8536       while (n + 1 == stream->n_samples)
8537         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8538           break;
8539     }
8540   }
8541   GST_OBJECT_UNLOCK (qtdemux);
8542
8543   return TRUE;
8544
8545   /* SUCCESS */
8546 already_parsed:
8547   {
8548     GST_LOG_OBJECT (qtdemux,
8549         "Tried to parse up to sample %u but this sample has already been parsed",
8550         n);
8551     /* if fragmented, there may be more */
8552     if (qtdemux->fragmented && n == stream->stbl_index)
8553       goto done;
8554     GST_OBJECT_UNLOCK (qtdemux);
8555     return TRUE;
8556   }
8557   /* ERRORS */
8558 out_of_samples:
8559   {
8560     GST_LOG_OBJECT (qtdemux,
8561         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8562         stream->n_samples);
8563     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8564         (_("This file is corrupt and cannot be played.")), (NULL));
8565     return FALSE;
8566   }
8567 corrupt_file:
8568   {
8569     GST_OBJECT_UNLOCK (qtdemux);
8570     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8571         (_("This file is corrupt and cannot be played.")), (NULL));
8572     return FALSE;
8573   }
8574 }
8575
8576 /* collect all segment info for @stream.
8577  */
8578 static gboolean
8579 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8580     GNode * trak)
8581 {
8582   GNode *edts;
8583   /* accept edts if they contain gaps at start and there is only
8584    * one media segment */
8585   gboolean allow_pushbased_edts = TRUE;
8586   gint media_segments_count = 0;
8587
8588   /* parse and prepare segment info from the edit list */
8589   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8590   stream->n_segments = 0;
8591   stream->segments = NULL;
8592   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8593     GNode *elst;
8594     gint n_segments;
8595     gint i, count, entry_size;
8596     guint64 time;
8597     GstClockTime stime;
8598     guint8 *buffer;
8599     guint8 version;
8600
8601     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8602     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8603       goto done;
8604
8605     buffer = elst->data;
8606
8607     version = QT_UINT8 (buffer + 8);
8608     entry_size = (version == 1) ? 20 : 12;
8609
8610     n_segments = QT_UINT32 (buffer + 12);
8611
8612     /* we might allocate a bit too much, at least allocate 1 segment */
8613     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8614
8615     /* segments always start from 0 */
8616     time = 0;
8617     stime = 0;
8618     count = 0;
8619     for (i = 0; i < n_segments; i++) {
8620       guint64 duration;
8621       guint64 media_time;
8622       gboolean time_valid = TRUE;
8623       QtDemuxSegment *segment;
8624       guint32 rate_int;
8625       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8626
8627       if (version == 1) {
8628         media_time = QT_UINT64 (buffer + 24 + i * entry_size);
8629         duration = QT_UINT64 (buffer + 16 + i * entry_size);
8630         if (media_time == G_MAXUINT64)
8631           time_valid = FALSE;
8632       } else {
8633         media_time = QT_UINT32 (buffer + 20 + i * entry_size);
8634         duration = QT_UINT32 (buffer + 16 + i * entry_size);
8635         if (media_time == G_MAXUINT32)
8636           time_valid = FALSE;
8637       }
8638
8639       if (time_valid)
8640         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8641
8642       segment = &stream->segments[count++];
8643
8644       /* time and duration expressed in global timescale */
8645       segment->time = stime;
8646       /* add non scaled values so we don't cause roundoff errors */
8647       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8648         time += duration;
8649         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8650         segment->duration = stime - segment->time;
8651       } else {
8652         /* zero duration does not imply media_start == media_stop
8653          * but, only specify media_start.*/
8654         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8655         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8656             && stime >= media_start) {
8657           segment->duration = stime - media_start;
8658         } else {
8659           segment->duration = GST_CLOCK_TIME_NONE;
8660         }
8661       }
8662       segment->stop_time = stime;
8663
8664       segment->trak_media_start = media_time;
8665       /* media_time expressed in stream timescale */
8666       if (time_valid) {
8667         segment->media_start = media_start;
8668         segment->media_stop = segment->media_start + segment->duration;
8669         media_segments_count++;
8670       } else {
8671         segment->media_start = GST_CLOCK_TIME_NONE;
8672         segment->media_stop = GST_CLOCK_TIME_NONE;
8673       }
8674       rate_int =
8675           QT_UINT32 (buffer + ((version == 1) ? 32 : 24) + i * entry_size);
8676
8677       if (rate_int <= 1) {
8678         /* 0 is not allowed, some programs write 1 instead of the floating point
8679          * value */
8680         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8681             rate_int);
8682         segment->rate = 1;
8683       } else {
8684         segment->rate = rate_int / 65536.0;
8685       }
8686
8687       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8688           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8689           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8690           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8691           i, GST_TIME_ARGS (segment->time),
8692           GST_TIME_ARGS (segment->duration),
8693           GST_TIME_ARGS (segment->media_start), media_time,
8694           GST_TIME_ARGS (segment->media_stop),
8695           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8696           stream->timescale);
8697       if (segment->stop_time > qtdemux->segment.stop) {
8698         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8699             " extends to %" GST_TIME_FORMAT
8700             " past the end of the file duration %" GST_TIME_FORMAT
8701             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8702             GST_TIME_ARGS (qtdemux->segment.stop));
8703         qtdemux->segment.stop = segment->stop_time;
8704       }
8705     }
8706     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8707     stream->n_segments = count;
8708     if (media_segments_count != 1)
8709       allow_pushbased_edts = FALSE;
8710   }
8711 done:
8712
8713   /* push based does not handle segments, so act accordingly here,
8714    * and warn if applicable */
8715   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8716     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8717     /* remove and use default one below, we stream like it anyway */
8718     g_free (stream->segments);
8719     stream->segments = NULL;
8720     stream->n_segments = 0;
8721   }
8722
8723   /* no segments, create one to play the complete trak */
8724   if (stream->n_segments == 0) {
8725     GstClockTime stream_duration =
8726         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8727
8728     if (stream->segments == NULL)
8729       stream->segments = g_new (QtDemuxSegment, 1);
8730
8731     /* represent unknown our way */
8732     if (stream_duration == 0)
8733       stream_duration = GST_CLOCK_TIME_NONE;
8734
8735     stream->segments[0].time = 0;
8736     stream->segments[0].stop_time = stream_duration;
8737     stream->segments[0].duration = stream_duration;
8738     stream->segments[0].media_start = 0;
8739     stream->segments[0].media_stop = stream_duration;
8740     stream->segments[0].rate = 1.0;
8741     stream->segments[0].trak_media_start = 0;
8742
8743     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8744         GST_TIME_ARGS (stream_duration));
8745     stream->n_segments = 1;
8746     stream->dummy_segment = TRUE;
8747   }
8748   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8749
8750   return TRUE;
8751 }
8752
8753 /*
8754  * Parses the stsd atom of a svq3 trak looking for
8755  * the SMI and gama atoms.
8756  */
8757 static void
8758 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8759     guint8 ** gamma, GstBuffer ** seqh)
8760 {
8761   guint8 *_gamma = NULL;
8762   GstBuffer *_seqh = NULL;
8763   guint8 *stsd_data = stsd->data;
8764   guint32 length = QT_UINT32 (stsd_data);
8765   guint16 version;
8766
8767   if (length < 32) {
8768     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8769     goto end;
8770   }
8771
8772   stsd_data += 32;
8773   length -= 32;
8774   version = QT_UINT16 (stsd_data);
8775   if (version == 3) {
8776     if (length >= 70) {
8777       length -= 70;
8778       stsd_data += 70;
8779       while (length > 8) {
8780         guint32 fourcc, size;
8781         guint8 *data;
8782         size = QT_UINT32 (stsd_data);
8783         fourcc = QT_FOURCC (stsd_data + 4);
8784         data = stsd_data + 8;
8785
8786         if (size == 0) {
8787           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8788               "svq3 atom parsing");
8789           goto end;
8790         }
8791
8792         switch (fourcc) {
8793           case FOURCC_gama:{
8794             if (size == 12) {
8795               _gamma = data;
8796             } else {
8797               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8798                   " for gama atom, expected 12", size);
8799             }
8800             break;
8801           }
8802           case FOURCC_SMI_:{
8803             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8804               guint32 seqh_size;
8805               if (_seqh != NULL) {
8806                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8807                     " found, ignoring");
8808               } else {
8809                 seqh_size = QT_UINT32 (data + 4);
8810                 if (seqh_size > 0) {
8811                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8812                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8813                 }
8814               }
8815             }
8816             break;
8817           }
8818           default:{
8819             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8820                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8821           }
8822         }
8823
8824         if (size <= length) {
8825           length -= size;
8826           stsd_data += size;
8827         }
8828       }
8829     } else {
8830       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8831     }
8832   } else {
8833     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8834         G_GUINT16_FORMAT, version);
8835     goto end;
8836   }
8837
8838 end:
8839   if (gamma) {
8840     *gamma = _gamma;
8841   }
8842   if (seqh) {
8843     *seqh = _seqh;
8844   } else if (_seqh) {
8845     gst_buffer_unref (_seqh);
8846   }
8847 }
8848
8849 static gchar *
8850 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8851 {
8852   GNode *dinf;
8853   GstByteReader dref;
8854   gchar *uri = NULL;
8855
8856   /*
8857    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8858    * atom that might contain a 'data' atom with the rtsp uri.
8859    * This case was reported in bug #597497, some info about
8860    * the hndl atom can be found in TN1195
8861    */
8862   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8863   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8864
8865   if (dinf) {
8866     guint32 dref_num_entries = 0;
8867     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8868         gst_byte_reader_skip (&dref, 4) &&
8869         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8870       gint i;
8871
8872       /* search dref entries for hndl atom */
8873       for (i = 0; i < dref_num_entries; i++) {
8874         guint32 size = 0, type;
8875         guint8 string_len = 0;
8876         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8877             qt_atom_parser_get_fourcc (&dref, &type)) {
8878           if (type == FOURCC_hndl) {
8879             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8880
8881             /* skip data reference handle bytes and the
8882              * following pascal string and some extra 4
8883              * bytes I have no idea what are */
8884             if (!gst_byte_reader_skip (&dref, 4) ||
8885                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8886                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8887               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8888               break;
8889             }
8890
8891             /* iterate over the atoms to find the data atom */
8892             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8893               guint32 atom_size;
8894               guint32 atom_type;
8895
8896               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8897                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8898                 if (atom_type == FOURCC_data) {
8899                   const guint8 *uri_aux = NULL;
8900
8901                   /* found the data atom that might contain the rtsp uri */
8902                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8903                       "hndl atom, interpreting it as an URI");
8904                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8905                           &uri_aux)) {
8906                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8907                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8908                     else
8909                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8910                           "didn't contain a rtsp address");
8911                   } else {
8912                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8913                         "atom contents");
8914                   }
8915                   break;
8916                 }
8917                 /* skipping to the next entry */
8918                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8919                   break;
8920               } else {
8921                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8922                     "atom header");
8923                 break;
8924               }
8925             }
8926             break;
8927           }
8928           /* skip to the next entry */
8929           if (!gst_byte_reader_skip (&dref, size - 8))
8930             break;
8931         } else {
8932           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8933         }
8934       }
8935       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8936     }
8937   }
8938   return uri;
8939 }
8940
8941 #define AMR_NB_ALL_MODES        0x81ff
8942 #define AMR_WB_ALL_MODES        0x83ff
8943 static guint
8944 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8945 {
8946   /* The 'damr' atom is of the form:
8947    *
8948    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8949    *    32 b       8 b          16 b           8 b                 8 b
8950    *
8951    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8952    * represents the highest mode used in the stream (and thus the maximum
8953    * bitrate), with a couple of special cases as seen below.
8954    */
8955
8956   /* Map of frame type ID -> bitrate */
8957   static const guint nb_bitrates[] = {
8958     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8959   };
8960   static const guint wb_bitrates[] = {
8961     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8962   };
8963   GstMapInfo map;
8964   gsize max_mode;
8965   guint16 mode_set;
8966
8967   gst_buffer_map (buf, &map, GST_MAP_READ);
8968
8969   if (map.size != 0x11) {
8970     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8971     goto bad_data;
8972   }
8973
8974   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8975     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8976         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8977     goto bad_data;
8978   }
8979
8980   mode_set = QT_UINT16 (map.data + 13);
8981
8982   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8983     max_mode = 7 + (wb ? 1 : 0);
8984   else
8985     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8986     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8987
8988   if (max_mode == -1) {
8989     GST_DEBUG ("No mode indication was found (mode set) = %x",
8990         (guint) mode_set);
8991     goto bad_data;
8992   }
8993
8994   gst_buffer_unmap (buf, &map);
8995   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8996
8997 bad_data:
8998   gst_buffer_unmap (buf, &map);
8999   return 0;
9000 }
9001
9002 static gboolean
9003 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9004     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9005 {
9006   /*
9007    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9008    * [0 1 2]
9009    * [3 4 5]
9010    * [6 7 8]
9011    */
9012
9013   if (gst_byte_reader_get_remaining (reader) < 36)
9014     return FALSE;
9015
9016   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9017   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9018   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9019   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9020   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9021   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9022   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9023   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9024   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9025
9026   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9027   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9028       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9029       matrix[2] & 0xFF);
9030   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9031       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9032       matrix[5] & 0xFF);
9033   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9034       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9035       matrix[8] & 0xFF);
9036
9037   return TRUE;
9038 }
9039
9040 static void
9041 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9042     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9043 {
9044
9045 /* [a b c]
9046  * [d e f]
9047  * [g h i]
9048  *
9049  * This macro will only compare value abdegh, it expects cfi to have already
9050  * been checked
9051  */
9052 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9053                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9054
9055   /* only handle the cases where the last column has standard values */
9056   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9057     const gchar *rotation_tag = NULL;
9058
9059     /* no rotation needed */
9060     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9061       /* NOP */
9062     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9063       rotation_tag = "rotate-90";
9064     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9065       rotation_tag = "rotate-180";
9066     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9067       rotation_tag = "rotate-270";
9068     } else {
9069       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9070     }
9071
9072     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9073         rotation_tag);
9074     if (rotation_tag != NULL) {
9075       if (*taglist == NULL)
9076         *taglist = gst_tag_list_new_empty ();
9077       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9078           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9079     }
9080   } else {
9081     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9082   }
9083 }
9084
9085 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9086  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9087  * Common Encryption (cenc), the function will also parse the tenc box (defined
9088  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9089  * (typically an enc[v|a|t|s] sample entry); the function will set
9090  * @original_fmt to the fourcc of the original unencrypted stream format.
9091  * Returns TRUE if successful; FALSE otherwise. */
9092 static gboolean
9093 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9094     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9095 {
9096   GNode *sinf;
9097   GNode *frma;
9098   GNode *schm;
9099   GNode *schi;
9100
9101   g_return_val_if_fail (qtdemux != NULL, FALSE);
9102   g_return_val_if_fail (stream != NULL, FALSE);
9103   g_return_val_if_fail (container != NULL, FALSE);
9104   g_return_val_if_fail (original_fmt != NULL, FALSE);
9105
9106   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9107   if (G_UNLIKELY (!sinf)) {
9108     if (stream->protection_scheme_type == FOURCC_cenc) {
9109       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9110           "mandatory for Common Encryption");
9111       return FALSE;
9112     }
9113     return TRUE;
9114   }
9115
9116   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9117   if (G_UNLIKELY (!frma)) {
9118     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9119     return FALSE;
9120   }
9121
9122   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9123   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9124       GST_FOURCC_ARGS (*original_fmt));
9125
9126   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9127   if (!schm) {
9128     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9129     return FALSE;
9130   }
9131   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9132   stream->protection_scheme_version =
9133       QT_UINT32 ((const guint8 *) schm->data + 16);
9134
9135   GST_DEBUG_OBJECT (qtdemux,
9136       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9137       "protection_scheme_version: %#010x",
9138       GST_FOURCC_ARGS (stream->protection_scheme_type),
9139       stream->protection_scheme_version);
9140
9141   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9142   if (!schi) {
9143     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9144     return FALSE;
9145   }
9146   if (stream->protection_scheme_type == FOURCC_cenc) {
9147     QtDemuxCencSampleSetInfo *info;
9148     GNode *tenc;
9149     const guint8 *tenc_data;
9150     guint32 isEncrypted;
9151     guint8 iv_size;
9152     const guint8 *default_kid;
9153     GstBuffer *kid_buf;
9154
9155     if (G_UNLIKELY (!stream->protection_scheme_info))
9156       stream->protection_scheme_info =
9157           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9158
9159     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9160
9161     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9162     if (!tenc) {
9163       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9164           "which is mandatory for Common Encryption");
9165       return FALSE;
9166     }
9167     tenc_data = (const guint8 *) tenc->data + 12;
9168     isEncrypted = QT_UINT24 (tenc_data);
9169     iv_size = QT_UINT8 (tenc_data + 3);
9170     default_kid = (tenc_data + 4);
9171     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9172     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9173     if (info->default_properties)
9174       gst_structure_free (info->default_properties);
9175     info->default_properties =
9176         gst_structure_new ("application/x-cenc",
9177         "iv_size", G_TYPE_UINT, iv_size,
9178         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9179         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9180     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9181         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9182     gst_buffer_unref (kid_buf);
9183   }
9184   return TRUE;
9185 }
9186
9187 /* parse the traks.
9188  * With each track we associate a new QtDemuxStream that contains all the info
9189  * about the trak.
9190  * traks that do not decode to something (like strm traks) will not have a pad.
9191  */
9192 static gboolean
9193 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9194 {
9195   GstByteReader tkhd;
9196   int offset;
9197   GNode *mdia;
9198   GNode *mdhd;
9199   GNode *hdlr;
9200   GNode *minf;
9201   GNode *stbl;
9202   GNode *stsd;
9203   GNode *mp4a;
9204   GNode *mp4v;
9205   GNode *wave;
9206   GNode *esds;
9207   GNode *pasp;
9208   GNode *colr;
9209   GNode *tref;
9210   GNode *udta;
9211   GNode *svmi;
9212
9213   QtDemuxStream *stream = NULL;
9214   gboolean new_stream = FALSE;
9215   gchar *codec = NULL;
9216   const guint8 *stsd_data;
9217   guint16 lang_code;            /* quicktime lang code or packed iso code */
9218   guint32 version;
9219   guint32 tkhd_flags = 0;
9220   guint8 tkhd_version = 0;
9221   guint32 fourcc;
9222   guint value_size, stsd_len, len;
9223   guint32 track_id;
9224   guint32 dummy;
9225
9226   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9227
9228   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9229       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9230       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9231     goto corrupt_file;
9232
9233   /* pick between 64 or 32 bits */
9234   value_size = tkhd_version == 1 ? 8 : 4;
9235   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9236       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9237     goto corrupt_file;
9238
9239   if (!qtdemux->got_moov) {
9240     if (qtdemux_find_stream (qtdemux, track_id))
9241       goto existing_stream;
9242     stream = _create_stream ();
9243     stream->track_id = track_id;
9244     new_stream = TRUE;
9245   } else {
9246     stream = qtdemux_find_stream (qtdemux, track_id);
9247     if (!stream) {
9248       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9249       goto skip_track;
9250     }
9251
9252     /* flush samples data from this track from previous moov */
9253     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9254     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9255   }
9256   /* need defaults for fragments */
9257   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9258
9259   if (stream->pending_tags == NULL)
9260     stream->pending_tags = gst_tag_list_new_empty ();
9261
9262   if ((tkhd_flags & 1) == 0)
9263     stream->disabled = TRUE;
9264
9265   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9266       tkhd_version, tkhd_flags, stream->track_id);
9267
9268   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9269     goto corrupt_file;
9270
9271   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9272     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9273     if (qtdemux->major_brand != FOURCC_mjp2 ||
9274         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9275       goto corrupt_file;
9276   }
9277
9278   len = QT_UINT32 ((guint8 *) mdhd->data);
9279   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9280   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9281   if (version == 0x01000000) {
9282     if (len < 38)
9283       goto corrupt_file;
9284     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9285     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9286     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9287   } else {
9288     if (len < 30)
9289       goto corrupt_file;
9290     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9291     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9292     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9293   }
9294
9295   if (lang_code < 0x400) {
9296     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9297   } else if (lang_code == 0x7fff) {
9298     stream->lang_id[0] = 0;     /* unspecified */
9299   } else {
9300     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9301     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9302     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9303     stream->lang_id[3] = 0;
9304   }
9305
9306   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9307       stream->timescale);
9308   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9309       stream->duration);
9310   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9311       lang_code, stream->lang_id);
9312
9313   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9314     goto corrupt_file;
9315
9316   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9317     /* chapters track reference */
9318     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9319     if (chap) {
9320       gsize length = GST_READ_UINT32_BE (chap->data);
9321       if (qtdemux->chapters_track_id)
9322         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9323
9324       if (length >= 12) {
9325         qtdemux->chapters_track_id =
9326             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9327       }
9328     }
9329   }
9330
9331   /* fragmented files may have bogus duration in moov */
9332   if (!qtdemux->fragmented &&
9333       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9334     guint64 tdur1, tdur2;
9335
9336     /* don't overflow */
9337     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9338     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9339
9340     /* HACK:
9341      * some of those trailers, nowadays, have prologue images that are
9342      * themselves video tracks as well. I haven't really found a way to
9343      * identify those yet, except for just looking at their duration. */
9344     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9345       GST_WARNING_OBJECT (qtdemux,
9346           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9347           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9348           "found, assuming preview image or something; skipping track",
9349           stream->duration, stream->timescale, qtdemux->duration,
9350           qtdemux->timescale);
9351       if (new_stream)
9352         gst_qtdemux_stream_free (qtdemux, stream);
9353       return TRUE;
9354     }
9355   }
9356
9357   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9358     goto corrupt_file;
9359
9360   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9361       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9362
9363   len = QT_UINT32 ((guint8 *) hdlr->data);
9364   if (len >= 20)
9365     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9366   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9367       GST_FOURCC_ARGS (stream->subtype));
9368
9369   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9370     goto corrupt_file;
9371
9372   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9373     goto corrupt_file;
9374
9375   /*parse svmi header if existing */
9376   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9377   if (svmi) {
9378     len = QT_UINT32 ((guint8 *) svmi->data);
9379     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9380     if (!version) {
9381       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9382       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9383       guint8 frame_type, frame_layout;
9384
9385       /* MPEG-A stereo video */
9386       if (qtdemux->major_brand == FOURCC_ss02)
9387         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9388
9389       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9390       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9391       switch (frame_type) {
9392         case 0:
9393           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9394           break;
9395         case 1:
9396           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9397           break;
9398         case 2:
9399           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9400           break;
9401         case 3:
9402           /* mode 3 is primary/secondary view sequence, ie
9403            * left/right views in separate tracks. See section 7.2
9404            * of ISO/IEC 23000-11:2009 */
9405           GST_FIXME_OBJECT (qtdemux,
9406               "Implement stereo video in separate streams");
9407       }
9408
9409       if ((frame_layout & 0x1) == 0)
9410         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9411
9412       GST_LOG_OBJECT (qtdemux,
9413           "StereoVideo: composition type: %u, is_left_first: %u",
9414           frame_type, frame_layout);
9415       stream->multiview_mode = mode;
9416       stream->multiview_flags = flags;
9417     }
9418   }
9419
9420   /* parse stsd */
9421   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9422     goto corrupt_file;
9423   stsd_data = (const guint8 *) stsd->data;
9424
9425   /* stsd should at least have one entry */
9426   stsd_len = QT_UINT32 (stsd_data);
9427   if (stsd_len < 24) {
9428     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9429     if (stream->subtype == FOURCC_vivo) {
9430       if (new_stream)
9431         gst_qtdemux_stream_free (qtdemux, stream);
9432       return TRUE;
9433     } else {
9434       goto corrupt_file;
9435     }
9436   }
9437
9438   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9439
9440   /* and that entry should fit within stsd */
9441   len = QT_UINT32 (stsd_data + 16);
9442   if (len > stsd_len + 16)
9443     goto corrupt_file;
9444
9445   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9446   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9447       GST_FOURCC_ARGS (stream->fourcc));
9448   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9449
9450   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9451     goto error_encrypted;
9452
9453   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9454     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9455     stream->protected = TRUE;
9456     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9457       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9458   }
9459
9460   if (stream->subtype == FOURCC_vide) {
9461     guint32 w = 0, h = 0;
9462     gboolean gray;
9463     gint depth, palette_size, palette_count;
9464     guint32 matrix[9];
9465     guint32 *palette_data = NULL;
9466
9467     stream->sampled = TRUE;
9468
9469     /* version 1 uses some 64-bit ints */
9470     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9471       goto corrupt_file;
9472
9473     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9474       goto corrupt_file;
9475
9476     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9477         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9478       goto corrupt_file;
9479
9480     stream->display_width = w >> 16;
9481     stream->display_height = h >> 16;
9482
9483     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9484         &stream->pending_tags);
9485
9486     offset = 16;
9487     if (len < 86)
9488       goto corrupt_file;
9489
9490     stream->width = QT_UINT16 (stsd_data + offset + 32);
9491     stream->height = QT_UINT16 (stsd_data + offset + 34);
9492     stream->fps_n = 0;          /* this is filled in later */
9493     stream->fps_d = 0;          /* this is filled in later */
9494     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9495     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9496
9497     /* if color_table_id is 0, ctab atom must follow; however some files
9498      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9499      * if color table is not present we'll correct the value */
9500     if (stream->color_table_id == 0 &&
9501         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9502       stream->color_table_id = -1;
9503     }
9504
9505     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9506         stream->width, stream->height, stream->bits_per_sample,
9507         stream->color_table_id);
9508
9509     depth = stream->bits_per_sample;
9510
9511     /* more than 32 bits means grayscale */
9512     gray = (depth > 32);
9513     /* low 32 bits specify the depth  */
9514     depth &= 0x1F;
9515
9516     /* different number of palette entries is determined by depth. */
9517     palette_count = 0;
9518     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9519       palette_count = (1 << depth);
9520     palette_size = palette_count * 4;
9521
9522     if (stream->color_table_id) {
9523       switch (palette_count) {
9524         case 0:
9525           break;
9526         case 2:
9527           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9528           break;
9529         case 4:
9530           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9531           break;
9532         case 16:
9533           if (gray)
9534             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9535           else
9536             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9537           break;
9538         case 256:
9539           if (gray)
9540             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9541           else
9542             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9543           break;
9544         default:
9545           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9546               (_("The video in this file might not play correctly.")),
9547               ("unsupported palette depth %d", depth));
9548           break;
9549       }
9550     } else {
9551       gint i, j, start, end;
9552
9553       if (len < 94)
9554         goto corrupt_file;
9555
9556       /* read table */
9557       start = QT_UINT32 (stsd_data + offset + 86);
9558       palette_count = QT_UINT16 (stsd_data + offset + 90);
9559       end = QT_UINT16 (stsd_data + offset + 92);
9560
9561       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9562           start, end, palette_count);
9563
9564       if (end > 255)
9565         end = 255;
9566       if (start > end)
9567         start = end;
9568
9569       if (len < 94 + (end - start) * 8)
9570         goto corrupt_file;
9571
9572       /* palette is always the same size */
9573       palette_data = g_malloc0 (256 * 4);
9574       palette_size = 256 * 4;
9575
9576       for (j = 0, i = start; i <= end; j++, i++) {
9577         guint32 a, r, g, b;
9578
9579         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9580         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9581         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9582         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9583
9584         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9585             (g & 0xff00) | (b >> 8);
9586       }
9587     }
9588
9589     if (stream->caps)
9590       gst_caps_unref (stream->caps);
9591
9592     stream->caps =
9593         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9594     if (G_UNLIKELY (!stream->caps)) {
9595       g_free (palette_data);
9596       goto unknown_stream;
9597     }
9598
9599     if (codec) {
9600       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9601           GST_TAG_VIDEO_CODEC, codec, NULL);
9602       g_free (codec);
9603       codec = NULL;
9604     }
9605
9606
9607     if (palette_data) {
9608       GstStructure *s;
9609
9610       if (stream->rgb8_palette)
9611         gst_memory_unref (stream->rgb8_palette);
9612       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9613           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9614
9615       s = gst_caps_get_structure (stream->caps, 0);
9616
9617       /* non-raw video has a palette_data property. raw video has the palette as
9618        * an extra plane that we append to the output buffers before we push
9619        * them*/
9620       if (!gst_structure_has_name (s, "video/x-raw")) {
9621         GstBuffer *palette;
9622
9623         palette = gst_buffer_new ();
9624         gst_buffer_append_memory (palette, stream->rgb8_palette);
9625         stream->rgb8_palette = NULL;
9626
9627         gst_caps_set_simple (stream->caps, "palette_data",
9628             GST_TYPE_BUFFER, palette, NULL);
9629         gst_buffer_unref (palette);
9630       }
9631     } else if (palette_count != 0) {
9632       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9633           (NULL), ("Unsupported palette depth %d", depth));
9634     }
9635
9636     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9637         QT_UINT16 (stsd_data + offset + 48));
9638
9639     esds = NULL;
9640     pasp = NULL;
9641     colr = NULL;
9642     /* pick 'the' stsd child */
9643     if (!stream->protected)
9644       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9645     else
9646       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9647
9648     if (mp4v) {
9649       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9650       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9651       colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
9652     }
9653
9654     if (pasp) {
9655       const guint8 *pasp_data = (const guint8 *) pasp->data;
9656
9657       stream->par_w = QT_UINT32 (pasp_data + 8);
9658       stream->par_h = QT_UINT32 (pasp_data + 12);
9659     } else {
9660       stream->par_w = 0;
9661       stream->par_h = 0;
9662     }
9663
9664     if (colr) {
9665       const guint8 *colr_data = (const guint8 *) colr->data;
9666       gint len = QT_UINT32 (colr_data);
9667
9668       if (len == 19 || len == 18) {
9669         guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
9670
9671         if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
9672           guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
9673           guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
9674           guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
9675           gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
9676
9677           switch (primaries) {
9678             case 1:
9679               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
9680               break;
9681             case 5:
9682               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
9683               break;
9684             case 6:
9685               stream->colorimetry.primaries =
9686                   GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
9687               break;
9688             case 9:
9689               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT2020;
9690               break;
9691             default:
9692               break;
9693           }
9694
9695           switch (transfer_function) {
9696             case 1:
9697               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
9698               break;
9699             case 7:
9700               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE240M;
9701               break;
9702             default:
9703               break;
9704           }
9705
9706           switch (matrix) {
9707             case 1:
9708               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
9709               break;
9710             case 6:
9711               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
9712               break;
9713             case 7:
9714               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_SMPTE240M;
9715               break;
9716             case 9:
9717               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT2020;
9718               break;
9719             default:
9720               break;
9721           }
9722
9723           stream->colorimetry.range =
9724               full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
9725               GST_VIDEO_COLOR_RANGE_16_235;
9726         } else {
9727           GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
9728         }
9729       } else {
9730         GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
9731       }
9732     }
9733
9734     if (esds) {
9735       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9736     } else {
9737       switch (fourcc) {
9738         case FOURCC_H264:
9739         case FOURCC_avc1:
9740         case FOURCC_avc3:
9741         {
9742           gint len = QT_UINT32 (stsd_data) - 0x66;
9743           const guint8 *avc_data = stsd_data + 0x66;
9744
9745           /* find avcC */
9746           while (len >= 0x8) {
9747             gint size;
9748
9749             if (QT_UINT32 (avc_data) <= len)
9750               size = QT_UINT32 (avc_data) - 0x8;
9751             else
9752               size = len - 0x8;
9753
9754             if (size < 1)
9755               /* No real data, so break out */
9756               break;
9757
9758             switch (QT_FOURCC (avc_data + 0x4)) {
9759               case FOURCC_avcC:
9760               {
9761                 /* parse, if found */
9762                 GstBuffer *buf;
9763
9764                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9765
9766                 /* First 4 bytes are the length of the atom, the next 4 bytes
9767                  * are the fourcc, the next 1 byte is the version, and the
9768                  * subsequent bytes are profile_tier_level structure like data. */
9769                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9770                     avc_data + 8 + 1, size - 1);
9771                 buf = gst_buffer_new_and_alloc (size);
9772                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9773                 gst_caps_set_simple (stream->caps,
9774                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9775                 gst_buffer_unref (buf);
9776
9777                 break;
9778               }
9779               case FOURCC_strf:
9780               {
9781                 GstBuffer *buf;
9782
9783                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9784
9785                 /* First 4 bytes are the length of the atom, the next 4 bytes
9786                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9787                  * next 1 byte is the version, and the
9788                  * subsequent bytes are sequence parameter set like data. */
9789
9790                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9791                 if (size > 1) {
9792                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9793                       avc_data + 8 + 40 + 1, size - 1);
9794
9795                   buf = gst_buffer_new_and_alloc (size);
9796                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9797                   gst_caps_set_simple (stream->caps,
9798                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9799                   gst_buffer_unref (buf);
9800                 }
9801                 break;
9802               }
9803               case FOURCC_btrt:
9804               {
9805                 guint avg_bitrate, max_bitrate;
9806
9807                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9808                 if (size < 12)
9809                   break;
9810
9811                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9812                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9813
9814                 if (!max_bitrate && !avg_bitrate)
9815                   break;
9816
9817                 /* Some muxers seem to swap the average and maximum bitrates
9818                  * (I'm looking at you, YouTube), so we swap for sanity. */
9819                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9820                   guint temp = avg_bitrate;
9821
9822                   avg_bitrate = max_bitrate;
9823                   max_bitrate = temp;
9824                 }
9825
9826                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9827                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9828                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9829                 }
9830                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9831                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9832                       GST_TAG_BITRATE, avg_bitrate, NULL);
9833                 }
9834
9835                 break;
9836               }
9837
9838               default:
9839                 break;
9840             }
9841
9842             len -= size + 8;
9843             avc_data += size + 8;
9844           }
9845
9846           break;
9847         }
9848         case FOURCC_H265:
9849         case FOURCC_hvc1:
9850         case FOURCC_hev1:
9851         {
9852           gint len = QT_UINT32 (stsd_data) - 0x66;
9853           const guint8 *hevc_data = stsd_data + 0x66;
9854
9855           /* find hevc */
9856           while (len >= 0x8) {
9857             gint size;
9858
9859             if (QT_UINT32 (hevc_data) <= len)
9860               size = QT_UINT32 (hevc_data) - 0x8;
9861             else
9862               size = len - 0x8;
9863
9864             if (size < 1)
9865               /* No real data, so break out */
9866               break;
9867
9868             switch (QT_FOURCC (hevc_data + 0x4)) {
9869               case FOURCC_hvcC:
9870               {
9871                 /* parse, if found */
9872                 GstBuffer *buf;
9873
9874                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9875
9876                 /* First 4 bytes are the length of the atom, the next 4 bytes
9877                  * are the fourcc, the next 1 byte is the version, and the
9878                  * subsequent bytes are sequence parameter set like data. */
9879                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9880                     (stream->caps, hevc_data + 8 + 1, size - 1);
9881
9882                 buf = gst_buffer_new_and_alloc (size);
9883                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9884                 gst_caps_set_simple (stream->caps,
9885                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9886                 gst_buffer_unref (buf);
9887                 break;
9888               }
9889               default:
9890                 break;
9891             }
9892             len -= size + 8;
9893             hevc_data += size + 8;
9894           }
9895           break;
9896         }
9897         case FOURCC_mp4v:
9898         case FOURCC_MP4V:
9899         case FOURCC_fmp4:
9900         case FOURCC_FMP4:
9901         {
9902           GNode *glbl;
9903
9904           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9905               GST_FOURCC_ARGS (fourcc));
9906
9907           /* codec data might be in glbl extension atom */
9908           glbl = mp4v ?
9909               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9910           if (glbl) {
9911             guint8 *data;
9912             GstBuffer *buf;
9913             gint len;
9914
9915             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9916             data = glbl->data;
9917             len = QT_UINT32 (data);
9918             if (len > 0x8) {
9919               len -= 0x8;
9920               buf = gst_buffer_new_and_alloc (len);
9921               gst_buffer_fill (buf, 0, data + 8, len);
9922               gst_caps_set_simple (stream->caps,
9923                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9924               gst_buffer_unref (buf);
9925             }
9926           }
9927           break;
9928         }
9929         case FOURCC_mjp2:
9930         {
9931           /* see annex I of the jpeg2000 spec */
9932           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9933           const guint8 *data;
9934           const gchar *colorspace = NULL;
9935           gint ncomp = 0;
9936           guint32 ncomp_map = 0;
9937           gint32 *comp_map = NULL;
9938           guint32 nchan_def = 0;
9939           gint32 *chan_def = NULL;
9940
9941           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9942           /* some required atoms */
9943           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9944           if (!mjp2)
9945             break;
9946           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9947           if (!jp2h)
9948             break;
9949
9950           /* number of components; redundant with info in codestream, but useful
9951              to a muxer */
9952           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9953           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9954             break;
9955           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9956
9957           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9958           if (!colr)
9959             break;
9960           GST_DEBUG_OBJECT (qtdemux, "found colr");
9961           /* extract colour space info */
9962           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9963             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9964               case 16:
9965                 colorspace = "sRGB";
9966                 break;
9967               case 17:
9968                 colorspace = "GRAY";
9969                 break;
9970               case 18:
9971                 colorspace = "sYUV";
9972                 break;
9973               default:
9974                 colorspace = NULL;
9975                 break;
9976             }
9977           }
9978           if (!colorspace)
9979             /* colr is required, and only values 16, 17, and 18 are specified,
9980                so error if we have no colorspace */
9981             break;
9982
9983           /* extract component mapping */
9984           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9985           if (cmap) {
9986             guint32 cmap_len = 0;
9987             int i;
9988             cmap_len = QT_UINT32 (cmap->data);
9989             if (cmap_len >= 8) {
9990               /* normal box, subtract off header */
9991               cmap_len -= 8;
9992               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9993               if (cmap_len % 4 == 0) {
9994                 ncomp_map = (cmap_len / 4);
9995                 comp_map = g_new0 (gint32, ncomp_map);
9996                 for (i = 0; i < ncomp_map; i++) {
9997                   guint16 cmp;
9998                   guint8 mtyp, pcol;
9999                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10000                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10001                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10002                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10003                 }
10004               }
10005             }
10006           }
10007           /* extract channel definitions */
10008           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10009           if (cdef) {
10010             guint32 cdef_len = 0;
10011             int i;
10012             cdef_len = QT_UINT32 (cdef->data);
10013             if (cdef_len >= 10) {
10014               /* normal box, subtract off header and len */
10015               cdef_len -= 10;
10016               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10017               if (cdef_len % 6 == 0) {
10018                 nchan_def = (cdef_len / 6);
10019                 chan_def = g_new0 (gint32, nchan_def);
10020                 for (i = 0; i < nchan_def; i++)
10021                   chan_def[i] = -1;
10022                 for (i = 0; i < nchan_def; i++) {
10023                   guint16 cn, typ, asoc;
10024                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10025                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10026                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10027                   if (cn < nchan_def) {
10028                     switch (typ) {
10029                       case 0:
10030                         chan_def[cn] = asoc;
10031                         break;
10032                       case 1:
10033                         chan_def[cn] = 0;       /* alpha */
10034                         break;
10035                       default:
10036                         chan_def[cn] = -typ;
10037                     }
10038                   }
10039                 }
10040               }
10041             }
10042           }
10043
10044           gst_caps_set_simple (stream->caps,
10045               "num-components", G_TYPE_INT, ncomp, NULL);
10046           gst_caps_set_simple (stream->caps,
10047               "colorspace", G_TYPE_STRING, colorspace, NULL);
10048
10049           if (comp_map) {
10050             GValue arr = { 0, };
10051             GValue elt = { 0, };
10052             int i;
10053             g_value_init (&arr, GST_TYPE_ARRAY);
10054             g_value_init (&elt, G_TYPE_INT);
10055             for (i = 0; i < ncomp_map; i++) {
10056               g_value_set_int (&elt, comp_map[i]);
10057               gst_value_array_append_value (&arr, &elt);
10058             }
10059             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10060                 "component-map", &arr);
10061             g_value_unset (&elt);
10062             g_value_unset (&arr);
10063             g_free (comp_map);
10064           }
10065
10066           if (chan_def) {
10067             GValue arr = { 0, };
10068             GValue elt = { 0, };
10069             int i;
10070             g_value_init (&arr, GST_TYPE_ARRAY);
10071             g_value_init (&elt, G_TYPE_INT);
10072             for (i = 0; i < nchan_def; i++) {
10073               g_value_set_int (&elt, chan_def[i]);
10074               gst_value_array_append_value (&arr, &elt);
10075             }
10076             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10077                 "channel-definitions", &arr);
10078             g_value_unset (&elt);
10079             g_value_unset (&arr);
10080             g_free (chan_def);
10081           }
10082
10083           /* some optional atoms */
10084           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10085           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10086
10087           /* indicate possible fields in caps */
10088           if (field) {
10089             data = (guint8 *) field->data + 8;
10090             if (*data != 1)
10091               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
10092                   (gint) * data, NULL);
10093           }
10094           /* add codec_data if provided */
10095           if (prefix) {
10096             GstBuffer *buf;
10097             gint len;
10098
10099             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10100             data = prefix->data;
10101             len = QT_UINT32 (data);
10102             if (len > 0x8) {
10103               len -= 0x8;
10104               buf = gst_buffer_new_and_alloc (len);
10105               gst_buffer_fill (buf, 0, data + 8, len);
10106               gst_caps_set_simple (stream->caps,
10107                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10108               gst_buffer_unref (buf);
10109             }
10110           }
10111           break;
10112         }
10113         case FOURCC_jpeg:
10114         {
10115           /* https://developer.apple.com/standards/qtff-2001.pdf,
10116            * page 92, "Video Sample Description", under table 3.1 */
10117           GstByteReader br;
10118
10119           const off_t compressor_offset =
10120               16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10121           const off_t min_size = compressor_offset + 32 + 2 + 2;
10122           GNode *jpeg;
10123           guint32 len;
10124           guint16 color_table_id = 0;
10125           gboolean ok;
10126
10127           GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10128
10129           /* recover information on interlaced/progressive */
10130           jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10131           if (!jpeg)
10132             break;
10133
10134           len = QT_UINT32 (jpeg->data);
10135           GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %lu", len,
10136               min_size);
10137           if (len >= min_size) {
10138             gst_byte_reader_init (&br, jpeg->data, len);
10139
10140             gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10141             gst_byte_reader_get_uint16_le (&br, &color_table_id);
10142             if (color_table_id != 0) {
10143               /* the spec says there can be concatenated chunks in the data, and we want
10144                * to find one called field. Walk through them. */
10145               off_t offset = min_size;
10146               while (offset + 8 < len) {
10147                 guint32 size, tag;
10148                 ok = gst_byte_reader_get_uint32_le (&br, &size);
10149                 ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10150                 if (!ok || size < 8) {
10151                   GST_WARNING_OBJECT (qtdemux,
10152                       "Failed to walk optional chunk list");
10153                   break;
10154                 }
10155                 GST_DEBUG_OBJECT (qtdemux,
10156                     "Found optional %4.4s chunk, size %u", (const char *) &tag,
10157                     size);
10158                 if (tag == FOURCC_fiel) {
10159                   guint8 n_fields, ordering;
10160                   gst_byte_reader_get_uint8 (&br, &n_fields);
10161                   gst_byte_reader_get_uint8 (&br, &ordering);
10162                   if (n_fields == 1 || n_fields == 2) {
10163                     GST_DEBUG_OBJECT (qtdemux,
10164                         "Found fiel tag with %u fields, ordering %u", n_fields,
10165                         ordering);
10166                     if (n_fields == 2)
10167                       gst_caps_set_simple (stream->caps, "interlace-mode",
10168                           G_TYPE_STRING, "interleaved", NULL);
10169                   } else {
10170                     GST_WARNING_OBJECT (qtdemux,
10171                         "Found fiel tag with invalid fields (%u)", n_fields);
10172                   }
10173                 }
10174                 offset += size;
10175               }
10176             } else {
10177               GST_DEBUG_OBJECT (qtdemux,
10178                   "Color table ID is 0, not trying to get interlacedness");
10179             }
10180           } else {
10181             GST_WARNING_OBJECT (qtdemux,
10182                 "Length of jpeg chunk is too small, not trying to get interlacedness");
10183           }
10184
10185           break;
10186         }
10187         case FOURCC_SVQ3:
10188         case FOURCC_VP31:
10189         {
10190           GstBuffer *buf;
10191           GstBuffer *seqh = NULL;
10192           guint8 *gamma_data = NULL;
10193           gint len = QT_UINT32 (stsd_data);
10194
10195           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
10196           if (gamma_data) {
10197             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
10198                 QT_FP32 (gamma_data), NULL);
10199           }
10200           if (seqh) {
10201             /* sorry for the bad name, but we don't know what this is, other
10202              * than its own fourcc */
10203             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
10204                 NULL);
10205           }
10206
10207           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10208           buf = gst_buffer_new_and_alloc (len);
10209           gst_buffer_fill (buf, 0, stsd_data, len);
10210           gst_caps_set_simple (stream->caps,
10211               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10212           gst_buffer_unref (buf);
10213           break;
10214         }
10215         case FOURCC_rle_:
10216         case FOURCC_WRLE:
10217         {
10218           gst_caps_set_simple (stream->caps,
10219               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
10220           break;
10221         }
10222         case FOURCC_XiTh:
10223         {
10224           GNode *xith, *xdxt;
10225
10226           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10227           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
10228           if (!xith)
10229             break;
10230
10231           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10232           if (!xdxt)
10233             break;
10234
10235           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10236           /* collect the headers and store them in a stream list so that we can
10237            * send them out first */
10238           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10239           break;
10240         }
10241         case FOURCC_ovc1:
10242         {
10243           GNode *ovc1;
10244           guint8 *ovc1_data;
10245           guint ovc1_len;
10246           GstBuffer *buf;
10247
10248           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10249           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
10250           if (!ovc1)
10251             break;
10252           ovc1_data = ovc1->data;
10253           ovc1_len = QT_UINT32 (ovc1_data);
10254           if (ovc1_len <= 198) {
10255             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10256             break;
10257           }
10258           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10259           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10260           gst_caps_set_simple (stream->caps,
10261               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10262           gst_buffer_unref (buf);
10263           break;
10264         }
10265         case FOURCC_vc_1:
10266         {
10267           gint len = QT_UINT32 (stsd_data) - 0x66;
10268           const guint8 *vc1_data = stsd_data + 0x66;
10269
10270           /* find dvc1 */
10271           while (len >= 8) {
10272             gint size;
10273
10274             if (QT_UINT32 (vc1_data) <= len)
10275               size = QT_UINT32 (vc1_data) - 8;
10276             else
10277               size = len - 8;
10278
10279             if (size < 1)
10280               /* No real data, so break out */
10281               break;
10282
10283             switch (QT_FOURCC (vc1_data + 0x4)) {
10284               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10285               {
10286                 GstBuffer *buf;
10287
10288                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10289                 buf = gst_buffer_new_and_alloc (size);
10290                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
10291                 gst_caps_set_simple (stream->caps,
10292                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10293                 gst_buffer_unref (buf);
10294                 break;
10295               }
10296               default:
10297                 break;
10298             }
10299             len -= size + 8;
10300             vc1_data += size + 8;
10301           }
10302           break;
10303         }
10304         default:
10305           break;
10306       }
10307     }
10308
10309     GST_INFO_OBJECT (qtdemux,
10310         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10311         GST_FOURCC_ARGS (fourcc), stream->caps);
10312
10313   } else if (stream->subtype == FOURCC_soun) {
10314     int version, samplesize;
10315     guint16 compression_id;
10316     gboolean amrwb = FALSE;
10317
10318     offset = 32;
10319     /* sample description entry (16) + sound sample description v0 (20) */
10320     if (len < 36)
10321       goto corrupt_file;
10322
10323     version = QT_UINT32 (stsd_data + offset);
10324     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10325     samplesize = QT_UINT16 (stsd_data + offset + 10);
10326     compression_id = QT_UINT16 (stsd_data + offset + 12);
10327     stream->rate = QT_FP32 (stsd_data + offset + 16);
10328
10329     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10330     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10331         QT_UINT32 (stsd_data + offset + 4));
10332     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10333     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10334     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10335     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10336         QT_UINT16 (stsd_data + offset + 14));
10337     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10338
10339     if (compression_id == 0xfffe)
10340       stream->sampled = TRUE;
10341
10342     /* first assume uncompressed audio */
10343     stream->bytes_per_sample = samplesize / 8;
10344     stream->samples_per_frame = stream->n_channels;
10345     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10346     stream->samples_per_packet = stream->samples_per_frame;
10347     stream->bytes_per_packet = stream->bytes_per_sample;
10348
10349     offset = 52;
10350     switch (fourcc) {
10351         /* Yes, these have to be hard-coded */
10352       case FOURCC_MAC6:
10353       {
10354         stream->samples_per_packet = 6;
10355         stream->bytes_per_packet = 1;
10356         stream->bytes_per_frame = 1 * stream->n_channels;
10357         stream->bytes_per_sample = 1;
10358         stream->samples_per_frame = 6 * stream->n_channels;
10359         break;
10360       }
10361       case FOURCC_MAC3:
10362       {
10363         stream->samples_per_packet = 3;
10364         stream->bytes_per_packet = 1;
10365         stream->bytes_per_frame = 1 * stream->n_channels;
10366         stream->bytes_per_sample = 1;
10367         stream->samples_per_frame = 3 * stream->n_channels;
10368         break;
10369       }
10370       case FOURCC_ima4:
10371       {
10372         stream->samples_per_packet = 64;
10373         stream->bytes_per_packet = 34;
10374         stream->bytes_per_frame = 34 * stream->n_channels;
10375         stream->bytes_per_sample = 2;
10376         stream->samples_per_frame = 64 * stream->n_channels;
10377         break;
10378       }
10379       case FOURCC_ulaw:
10380       case FOURCC_alaw:
10381       {
10382         stream->samples_per_packet = 1;
10383         stream->bytes_per_packet = 1;
10384         stream->bytes_per_frame = 1 * stream->n_channels;
10385         stream->bytes_per_sample = 1;
10386         stream->samples_per_frame = 1 * stream->n_channels;
10387         break;
10388       }
10389       case FOURCC_agsm:
10390       {
10391         stream->samples_per_packet = 160;
10392         stream->bytes_per_packet = 33;
10393         stream->bytes_per_frame = 33 * stream->n_channels;
10394         stream->bytes_per_sample = 2;
10395         stream->samples_per_frame = 160 * stream->n_channels;
10396         break;
10397       }
10398       default:
10399         break;
10400     }
10401
10402     if (version == 0x00010000) {
10403       /* sample description entry (16) + sound sample description v1 (20+16) */
10404       if (len < 52)
10405         goto corrupt_file;
10406
10407       switch (fourcc) {
10408         case FOURCC_twos:
10409         case FOURCC_sowt:
10410         case FOURCC_raw_:
10411           break;
10412         default:
10413         {
10414           /* only parse extra decoding config for non-pcm audio */
10415           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10416           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10417           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10418           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10419
10420           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10421               stream->samples_per_packet);
10422           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10423               stream->bytes_per_packet);
10424           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10425               stream->bytes_per_frame);
10426           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10427               stream->bytes_per_sample);
10428
10429           if (!stream->sampled && stream->bytes_per_packet) {
10430             stream->samples_per_frame = (stream->bytes_per_frame /
10431                 stream->bytes_per_packet) * stream->samples_per_packet;
10432             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10433                 stream->samples_per_frame);
10434           }
10435           break;
10436         }
10437       }
10438     } else if (version == 0x00020000) {
10439       union
10440       {
10441         gdouble fp;
10442         guint64 val;
10443       } qtfp;
10444
10445       /* sample description entry (16) + sound sample description v2 (56) */
10446       if (len < 72)
10447         goto corrupt_file;
10448
10449       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10450       stream->rate = qtfp.fp;
10451       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10452
10453       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10454       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10455       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10456       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10457           QT_UINT32 (stsd_data + offset + 20));
10458       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10459           QT_UINT32 (stsd_data + offset + 24));
10460       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10461           QT_UINT32 (stsd_data + offset + 28));
10462       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10463           QT_UINT32 (stsd_data + offset + 32));
10464     } else if (version != 0x00000) {
10465       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10466     }
10467
10468     if (stream->caps)
10469       gst_caps_unref (stream->caps);
10470
10471     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10472         stsd_data + 32, len - 16, &codec);
10473
10474     switch (fourcc) {
10475       case FOURCC_in24:
10476       {
10477         GNode *enda;
10478         GNode *in24;
10479
10480         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10481
10482         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10483         if (!enda) {
10484           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10485           if (wave)
10486             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10487         }
10488         if (enda) {
10489           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10490           gst_caps_set_simple (stream->caps,
10491               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10492         }
10493         break;
10494       }
10495       case FOURCC_owma:
10496       {
10497         GNode *owma;
10498         const guint8 *owma_data;
10499         const gchar *codec_name = NULL;
10500         guint owma_len;
10501         GstBuffer *buf;
10502         gint version = 1;
10503         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10504         /* FIXME this should also be gst_riff_strf_auds,
10505          * but the latter one is actually missing bits-per-sample :( */
10506         typedef struct
10507         {
10508           gint16 wFormatTag;
10509           gint16 nChannels;
10510           gint32 nSamplesPerSec;
10511           gint32 nAvgBytesPerSec;
10512           gint16 nBlockAlign;
10513           gint16 wBitsPerSample;
10514           gint16 cbSize;
10515         } WAVEFORMATEX;
10516         WAVEFORMATEX *wfex;
10517
10518         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10519         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10520         if (!owma)
10521           break;
10522         owma_data = owma->data;
10523         owma_len = QT_UINT32 (owma_data);
10524         if (owma_len <= 54) {
10525           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10526           break;
10527         }
10528         wfex = (WAVEFORMATEX *) (owma_data + 36);
10529         buf = gst_buffer_new_and_alloc (owma_len - 54);
10530         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10531         if (wfex->wFormatTag == 0x0161) {
10532           codec_name = "Windows Media Audio";
10533           version = 2;
10534         } else if (wfex->wFormatTag == 0x0162) {
10535           codec_name = "Windows Media Audio 9 Pro";
10536           version = 3;
10537         } else if (wfex->wFormatTag == 0x0163) {
10538           codec_name = "Windows Media Audio 9 Lossless";
10539           /* is that correct? gstffmpegcodecmap.c is missing it, but
10540            * fluendo codec seems to support it */
10541           version = 4;
10542         }
10543
10544         gst_caps_set_simple (stream->caps,
10545             "codec_data", GST_TYPE_BUFFER, buf,
10546             "wmaversion", G_TYPE_INT, version,
10547             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10548             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10549             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10550             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10551             NULL);
10552         gst_buffer_unref (buf);
10553
10554         if (codec_name) {
10555           g_free (codec);
10556           codec = g_strdup (codec_name);
10557         }
10558         break;
10559       }
10560       case FOURCC_wma_:
10561       {
10562         gint len = QT_UINT32 (stsd_data) - offset;
10563         const guint8 *wfex_data = stsd_data + offset;
10564         const gchar *codec_name = NULL;
10565         gint version = 1;
10566         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10567         /* FIXME this should also be gst_riff_strf_auds,
10568          * but the latter one is actually missing bits-per-sample :( */
10569         typedef struct
10570         {
10571           gint16 wFormatTag;
10572           gint16 nChannels;
10573           gint32 nSamplesPerSec;
10574           gint32 nAvgBytesPerSec;
10575           gint16 nBlockAlign;
10576           gint16 wBitsPerSample;
10577           gint16 cbSize;
10578         } WAVEFORMATEX;
10579         WAVEFORMATEX wfex;
10580
10581         /* FIXME: unify with similar wavformatex parsing code above */
10582         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10583
10584         /* find wfex */
10585         while (len >= 8) {
10586           gint size;
10587
10588           if (QT_UINT32 (wfex_data) <= len)
10589             size = QT_UINT32 (wfex_data) - 8;
10590           else
10591             size = len - 8;
10592
10593           if (size < 1)
10594             /* No real data, so break out */
10595             break;
10596
10597           switch (QT_FOURCC (wfex_data + 4)) {
10598             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10599             {
10600               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10601
10602               if (size < 8 + 18)
10603                 break;
10604
10605               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10606               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10607               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10608               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10609               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10610               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10611               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10612
10613               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10614               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10615                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10616                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10617                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10618                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10619
10620               if (wfex.wFormatTag == 0x0161) {
10621                 codec_name = "Windows Media Audio";
10622                 version = 2;
10623               } else if (wfex.wFormatTag == 0x0162) {
10624                 codec_name = "Windows Media Audio 9 Pro";
10625                 version = 3;
10626               } else if (wfex.wFormatTag == 0x0163) {
10627                 codec_name = "Windows Media Audio 9 Lossless";
10628                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10629                  * fluendo codec seems to support it */
10630                 version = 4;
10631               }
10632
10633               gst_caps_set_simple (stream->caps,
10634                   "wmaversion", G_TYPE_INT, version,
10635                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10636                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10637                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10638                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10639
10640               if (size > wfex.cbSize) {
10641                 GstBuffer *buf;
10642
10643                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10644                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10645                     size - wfex.cbSize);
10646                 gst_caps_set_simple (stream->caps,
10647                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10648                 gst_buffer_unref (buf);
10649               } else {
10650                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10651               }
10652
10653               if (codec_name) {
10654                 g_free (codec);
10655                 codec = g_strdup (codec_name);
10656               }
10657               break;
10658             }
10659             default:
10660               break;
10661           }
10662           len -= size + 8;
10663           wfex_data += size + 8;
10664         }
10665         break;
10666       }
10667       case FOURCC_opus:
10668       {
10669         GNode *opus;
10670         const guint8 *opus_data;
10671         guint8 *channel_mapping = NULL;
10672         guint32 rate;
10673         guint8 channels;
10674         guint8 channel_mapping_family;
10675         guint8 stream_count;
10676         guint8 coupled_count;
10677         guint8 i;
10678
10679         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10680         opus_data = opus->data;
10681
10682         channels = GST_READ_UINT8 (opus_data + 45);
10683         rate = GST_READ_UINT32_LE (opus_data + 48);
10684         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10685         stream_count = GST_READ_UINT8 (opus_data + 55);
10686         coupled_count = GST_READ_UINT8 (opus_data + 56);
10687
10688         if (channels > 0) {
10689           channel_mapping = g_malloc (channels * sizeof (guint8));
10690           for (i = 0; i < channels; i++)
10691             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10692         }
10693
10694         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10695             channel_mapping_family, stream_count, coupled_count,
10696             channel_mapping);
10697         break;
10698       }
10699       default:
10700         break;
10701     }
10702
10703     if (codec) {
10704       GstStructure *s;
10705       gint bitrate = 0;
10706
10707       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10708           GST_TAG_AUDIO_CODEC, codec, NULL);
10709       g_free (codec);
10710       codec = NULL;
10711
10712       /* some bitrate info may have ended up in caps */
10713       s = gst_caps_get_structure (stream->caps, 0);
10714       gst_structure_get_int (s, "bitrate", &bitrate);
10715       if (bitrate > 0)
10716         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10717             GST_TAG_BITRATE, bitrate, NULL);
10718     }
10719
10720     if (stream->protected && fourcc == FOURCC_mp4a)
10721       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10722     else
10723       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10724
10725     wave = NULL;
10726     esds = NULL;
10727     if (mp4a) {
10728       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10729       if (wave)
10730         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10731       if (!esds)
10732         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10733     }
10734
10735
10736     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10737        16 bits is a byte-swapped wave-style codec identifier,
10738        and we can find a WAVE header internally to a 'wave' atom here.
10739        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10740        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10741        is big-endian).
10742      */
10743     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10744       if (len < offset + 20) {
10745         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10746       } else {
10747         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10748         const guint8 *data = stsd_data + offset + 16;
10749         GNode *wavenode;
10750         GNode *waveheadernode;
10751
10752         wavenode = g_node_new ((guint8 *) data);
10753         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10754           const guint8 *waveheader;
10755           guint32 headerlen;
10756
10757           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10758           if (waveheadernode) {
10759             waveheader = (const guint8 *) waveheadernode->data;
10760             headerlen = QT_UINT32 (waveheader);
10761
10762             if (headerlen > 8) {
10763               gst_riff_strf_auds *header = NULL;
10764               GstBuffer *headerbuf;
10765               GstBuffer *extra;
10766
10767               waveheader += 8;
10768               headerlen -= 8;
10769
10770               headerbuf = gst_buffer_new_and_alloc (headerlen);
10771               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10772
10773               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10774                       headerbuf, &header, &extra)) {
10775                 gst_caps_unref (stream->caps);
10776                 /* FIXME: Need to do something with the channel reorder map */
10777                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10778                     header, extra, NULL, NULL, NULL);
10779
10780                 if (extra)
10781                   gst_buffer_unref (extra);
10782                 g_free (header);
10783               }
10784             }
10785           } else
10786             GST_DEBUG ("Didn't find waveheadernode for this codec");
10787         }
10788         g_node_destroy (wavenode);
10789       }
10790     } else if (esds) {
10791       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10792     } else {
10793       switch (fourcc) {
10794 #if 0
10795           /* FIXME: what is in the chunk? */
10796         case FOURCC_QDMC:
10797         {
10798           gint len = QT_UINT32 (stsd_data);
10799
10800           /* seems to be always = 116 = 0x74 */
10801           break;
10802         }
10803 #endif
10804         case FOURCC_QDM2:
10805         {
10806           gint len = QT_UINT32 (stsd_data);
10807
10808           if (len > 0x4C) {
10809             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10810
10811             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10812             gst_caps_set_simple (stream->caps,
10813                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10814             gst_buffer_unref (buf);
10815           }
10816           gst_caps_set_simple (stream->caps,
10817               "samplesize", G_TYPE_INT, samplesize, NULL);
10818           break;
10819         }
10820         case FOURCC_alac:
10821         {
10822           GNode *alac, *wave = NULL;
10823
10824           /* apparently, m4a has this atom appended directly in the stsd entry,
10825            * while mov has it in a wave atom */
10826           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10827           if (alac) {
10828             /* alac now refers to stsd entry atom */
10829             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10830             if (wave)
10831               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10832             else
10833               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10834           }
10835           if (alac) {
10836             const guint8 *alac_data = alac->data;
10837             gint len = QT_UINT32 (alac->data);
10838             GstBuffer *buf;
10839
10840             if (len < 36) {
10841               GST_DEBUG_OBJECT (qtdemux,
10842                   "discarding alac atom with unexpected len %d", len);
10843             } else {
10844               /* codec-data contains alac atom size and prefix,
10845                * ffmpeg likes it that way, not quite gst-ish though ...*/
10846               buf = gst_buffer_new_and_alloc (len);
10847               gst_buffer_fill (buf, 0, alac->data, len);
10848               gst_caps_set_simple (stream->caps,
10849                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10850               gst_buffer_unref (buf);
10851
10852               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10853               stream->n_channels = QT_UINT8 (alac_data + 21);
10854               stream->rate = QT_UINT32 (alac_data + 32);
10855             }
10856           }
10857           gst_caps_set_simple (stream->caps,
10858               "samplesize", G_TYPE_INT, samplesize, NULL);
10859           break;
10860         }
10861         case FOURCC_sawb:
10862           /* Fallthrough! */
10863           amrwb = TRUE;
10864         case FOURCC_samr:
10865         {
10866           gint len = QT_UINT32 (stsd_data);
10867
10868           if (len > 0x34) {
10869             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10870             guint bitrate;
10871
10872             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10873
10874             /* If we have enough data, let's try to get the 'damr' atom. See
10875              * the 3GPP container spec (26.244) for more details. */
10876             if ((len - 0x34) > 8 &&
10877                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10878               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10879                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10880             }
10881
10882             gst_caps_set_simple (stream->caps,
10883                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10884             gst_buffer_unref (buf);
10885           }
10886           break;
10887         }
10888         case FOURCC_mp4a:
10889         {
10890           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10891           gint len = QT_UINT32 (stsd_data);
10892
10893           if (len >= 50) {
10894             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10895
10896             if (sound_version == 1) {
10897               guint16 channels = QT_UINT16 (stsd_data + 40);
10898               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10899               guint8 codec_data[2];
10900               GstBuffer *buf;
10901               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10902
10903               gint sample_rate_index =
10904                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10905
10906               /* build AAC codec data */
10907               codec_data[0] = profile << 3;
10908               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10909               codec_data[1] = (sample_rate_index & 0x01) << 7;
10910               codec_data[1] |= (channels & 0xF) << 3;
10911
10912               buf = gst_buffer_new_and_alloc (2);
10913               gst_buffer_fill (buf, 0, codec_data, 2);
10914               gst_caps_set_simple (stream->caps,
10915                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10916               gst_buffer_unref (buf);
10917             }
10918           }
10919           break;
10920         }
10921         default:
10922           GST_INFO_OBJECT (qtdemux,
10923               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10924           break;
10925       }
10926     }
10927     GST_INFO_OBJECT (qtdemux,
10928         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10929         GST_FOURCC_ARGS (fourcc), stream->caps);
10930
10931   } else if (stream->subtype == FOURCC_strm) {
10932     if (fourcc == FOURCC_rtsp) {
10933       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10934     } else {
10935       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10936           GST_FOURCC_ARGS (fourcc));
10937       goto unknown_stream;
10938     }
10939     stream->sampled = TRUE;
10940   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10941       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10942
10943     stream->sampled = TRUE;
10944     stream->sparse = TRUE;
10945
10946     stream->caps =
10947         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10948     if (codec) {
10949       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10950           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10951       g_free (codec);
10952       codec = NULL;
10953     }
10954
10955     /* hunt for sort-of codec data */
10956     switch (fourcc) {
10957       case FOURCC_mp4s:
10958       {
10959         GNode *mp4s = NULL;
10960         GNode *esds = NULL;
10961
10962         /* look for palette in a stsd->mp4s->esds sub-atom */
10963         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10964         if (mp4s)
10965           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10966         if (esds == NULL) {
10967           /* Invalid STSD */
10968           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10969           break;
10970         }
10971
10972         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10973         break;
10974       }
10975       default:
10976         GST_INFO_OBJECT (qtdemux,
10977             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10978         break;
10979     }
10980     GST_INFO_OBJECT (qtdemux,
10981         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10982         GST_FOURCC_ARGS (fourcc), stream->caps);
10983   } else {
10984     /* everything in 1 sample */
10985     stream->sampled = TRUE;
10986
10987     stream->caps =
10988         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10989
10990     if (stream->caps == NULL)
10991       goto unknown_stream;
10992
10993     if (codec) {
10994       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10995           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10996       g_free (codec);
10997       codec = NULL;
10998     }
10999   }
11000
11001   /* promote to sampled format */
11002   if (stream->fourcc == FOURCC_samr) {
11003     /* force mono 8000 Hz for AMR */
11004     stream->sampled = TRUE;
11005     stream->n_channels = 1;
11006     stream->rate = 8000;
11007   } else if (stream->fourcc == FOURCC_sawb) {
11008     /* force mono 16000 Hz for AMR-WB */
11009     stream->sampled = TRUE;
11010     stream->n_channels = 1;
11011     stream->rate = 16000;
11012   } else if (stream->fourcc == FOURCC_mp4a) {
11013     stream->sampled = TRUE;
11014   }
11015
11016   /* collect sample information */
11017   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11018     goto samples_failed;
11019
11020   if (qtdemux->fragmented) {
11021     guint64 offset;
11022
11023     /* need all moov samples as basis; probably not many if any at all */
11024     /* prevent moof parsing taking of at this time */
11025     offset = qtdemux->moof_offset;
11026     qtdemux->moof_offset = 0;
11027     if (stream->n_samples &&
11028         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11029       qtdemux->moof_offset = offset;
11030       goto samples_failed;
11031     }
11032     qtdemux->moof_offset = 0;
11033     /* movie duration more reliable in this case (e.g. mehd) */
11034     if (qtdemux->segment.duration &&
11035         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11036       stream->duration =
11037           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11038   }
11039
11040   /* configure segments */
11041   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11042     goto segments_failed;
11043
11044   /* add some language tag, if useful */
11045   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11046       strcmp (stream->lang_id, "und")) {
11047     const gchar *lang_code;
11048
11049     /* convert ISO 639-2 code to ISO 639-1 */
11050     lang_code = gst_tag_get_language_code (stream->lang_id);
11051     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11052         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11053   }
11054
11055   /* Check for UDTA tags */
11056   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11057     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
11058   }
11059
11060   /* now we are ready to add the stream */
11061   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11062     goto too_many_streams;
11063
11064   if (!qtdemux->got_moov) {
11065     qtdemux->streams[qtdemux->n_streams] = stream;
11066     qtdemux->n_streams++;
11067     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11068   }
11069
11070   return TRUE;
11071
11072 /* ERRORS */
11073 skip_track:
11074   {
11075     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11076     if (new_stream)
11077       gst_qtdemux_stream_free (qtdemux, stream);
11078     return TRUE;
11079   }
11080 corrupt_file:
11081   {
11082     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11083         (_("This file is corrupt and cannot be played.")), (NULL));
11084     if (new_stream)
11085       gst_qtdemux_stream_free (qtdemux, stream);
11086     return FALSE;
11087   }
11088 error_encrypted:
11089   {
11090     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11091     if (new_stream)
11092       gst_qtdemux_stream_free (qtdemux, stream);
11093     return FALSE;
11094   }
11095 samples_failed:
11096 segments_failed:
11097   {
11098     /* we posted an error already */
11099     /* free stbl sub-atoms */
11100     gst_qtdemux_stbl_free (stream);
11101     if (new_stream)
11102       gst_qtdemux_stream_free (qtdemux, stream);
11103     return FALSE;
11104   }
11105 existing_stream:
11106   {
11107     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11108         track_id);
11109     if (new_stream)
11110       gst_qtdemux_stream_free (qtdemux, stream);
11111     return TRUE;
11112   }
11113 unknown_stream:
11114   {
11115     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11116         GST_FOURCC_ARGS (stream->subtype));
11117     if (new_stream)
11118       gst_qtdemux_stream_free (qtdemux, stream);
11119     return TRUE;
11120   }
11121 too_many_streams:
11122   {
11123     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11124         (_("This file contains too many streams. Only playing first %d"),
11125             GST_QTDEMUX_MAX_STREAMS), (NULL));
11126     return TRUE;
11127   }
11128 }
11129
11130 /* If we can estimate the overall bitrate, and don't have information about the
11131  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11132  * the overall bitrate minus the sum of the bitrates of all other streams. This
11133  * should be useful for the common case where we have one audio and one video
11134  * stream and can estimate the bitrate of one, but not the other. */
11135 static void
11136 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11137 {
11138   QtDemuxStream *stream = NULL;
11139   gint64 size, sys_bitrate, sum_bitrate = 0;
11140   GstClockTime duration;
11141   gint i;
11142   guint bitrate;
11143
11144   if (qtdemux->fragmented)
11145     return;
11146
11147   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11148
11149   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11150       || size <= 0) {
11151     GST_DEBUG_OBJECT (qtdemux,
11152         "Size in bytes of the stream not known - bailing");
11153     return;
11154   }
11155
11156   /* Subtract the header size */
11157   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11158       size, qtdemux->header_size);
11159
11160   if (size < qtdemux->header_size)
11161     return;
11162
11163   size = size - qtdemux->header_size;
11164
11165   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11166     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11167     return;
11168   }
11169
11170   for (i = 0; i < qtdemux->n_streams; i++) {
11171     switch (qtdemux->streams[i]->subtype) {
11172       case FOURCC_soun:
11173       case FOURCC_vide:
11174         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11175             qtdemux->streams[i]->caps);
11176         /* retrieve bitrate, prefer avg then max */
11177         bitrate = 0;
11178         if (qtdemux->streams[i]->pending_tags) {
11179           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11180               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11181           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11182           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11183               GST_TAG_NOMINAL_BITRATE, &bitrate);
11184           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11185           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11186               GST_TAG_BITRATE, &bitrate);
11187           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11188         }
11189         if (bitrate)
11190           sum_bitrate += bitrate;
11191         else {
11192           if (stream) {
11193             GST_DEBUG_OBJECT (qtdemux,
11194                 ">1 stream with unknown bitrate - bailing");
11195             return;
11196           } else
11197             stream = qtdemux->streams[i];
11198         }
11199
11200       default:
11201         /* For other subtypes, we assume no significant impact on bitrate */
11202         break;
11203     }
11204   }
11205
11206   if (!stream) {
11207     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11208     return;
11209   }
11210
11211   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11212
11213   if (sys_bitrate < sum_bitrate) {
11214     /* This can happen, since sum_bitrate might be derived from maximum
11215      * bitrates and not average bitrates */
11216     GST_DEBUG_OBJECT (qtdemux,
11217         "System bitrate less than sum bitrate - bailing");
11218     return;
11219   }
11220
11221   bitrate = sys_bitrate - sum_bitrate;
11222   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11223       ", Stream bitrate = %u", sys_bitrate, bitrate);
11224
11225   if (!stream->pending_tags)
11226     stream->pending_tags = gst_tag_list_new_empty ();
11227
11228   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11229       GST_TAG_BITRATE, bitrate, NULL);
11230 }
11231
11232 static GstFlowReturn
11233 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11234 {
11235   gint i;
11236   GstFlowReturn ret = GST_FLOW_OK;
11237
11238   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11239
11240   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11241     QtDemuxStream *stream = qtdemux->streams[i];
11242     guint32 sample_num = 0;
11243
11244     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11245         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11246
11247     if (qtdemux->fragmented) {
11248       /* need all moov samples first */
11249       GST_OBJECT_LOCK (qtdemux);
11250       while (stream->n_samples == 0)
11251         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11252           break;
11253       GST_OBJECT_UNLOCK (qtdemux);
11254     } else {
11255       /* discard any stray moof */
11256       qtdemux->moof_offset = 0;
11257     }
11258
11259     /* prepare braking */
11260     if (ret != GST_FLOW_ERROR)
11261       ret = GST_FLOW_OK;
11262
11263     /* in pull mode, we should have parsed some sample info by now;
11264      * and quite some code will not handle no samples.
11265      * in push mode, we'll just have to deal with it */
11266     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11267       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11268       gst_qtdemux_remove_stream (qtdemux, i);
11269       i--;
11270       continue;
11271     }
11272
11273     /* parse the initial sample for use in setting the frame rate cap */
11274     while (sample_num == 0 && sample_num < stream->n_samples) {
11275       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11276         break;
11277       ++sample_num;
11278     }
11279     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11280       stream->first_duration = stream->samples[0].duration;
11281       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11282           stream->track_id, stream->first_duration);
11283     }
11284   }
11285
11286   return ret;
11287 }
11288
11289 static GstFlowReturn
11290 qtdemux_expose_streams (GstQTDemux * qtdemux)
11291 {
11292   gint i;
11293   GstFlowReturn ret = GST_FLOW_OK;
11294   GSList *oldpads = NULL;
11295   GSList *iter;
11296
11297   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11298
11299   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11300     QtDemuxStream *stream = qtdemux->streams[i];
11301     GstPad *oldpad = stream->pad;
11302     GstTagList *list;
11303
11304     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11305         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11306
11307     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11308         stream->track_id == qtdemux->chapters_track_id) {
11309       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11310          so that it doesn't look like a subtitle track */
11311       gst_qtdemux_remove_stream (qtdemux, i);
11312       i--;
11313       continue;
11314     }
11315
11316     /* now we have all info and can expose */
11317     list = stream->pending_tags;
11318     stream->pending_tags = NULL;
11319     if (oldpad)
11320       oldpads = g_slist_prepend (oldpads, oldpad);
11321     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11322       return GST_FLOW_ERROR;
11323   }
11324
11325   gst_qtdemux_guess_bitrate (qtdemux);
11326
11327   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11328
11329   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11330     GstPad *oldpad = iter->data;
11331     GstEvent *event;
11332
11333     event = gst_event_new_eos ();
11334     if (qtdemux->segment_seqnum)
11335       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11336
11337     gst_pad_push_event (oldpad, event);
11338     gst_pad_set_active (oldpad, FALSE);
11339     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11340     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11341     gst_object_unref (oldpad);
11342   }
11343
11344   /* check if we should post a redirect in case there is a single trak
11345    * and it is a redirecting trak */
11346   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11347     GstMessage *m;
11348
11349     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11350         "an external content");
11351     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11352         gst_structure_new ("redirect",
11353             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11354             NULL));
11355     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11356     qtdemux->posted_redirect = TRUE;
11357   }
11358
11359   for (i = 0; i < qtdemux->n_streams; i++) {
11360     QtDemuxStream *stream = qtdemux->streams[i];
11361
11362     qtdemux_do_allocation (qtdemux, stream);
11363   }
11364
11365   qtdemux->exposed = TRUE;
11366   return ret;
11367 }
11368
11369 /* check if major or compatible brand is 3GP */
11370 static inline gboolean
11371 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11372 {
11373   if (major) {
11374     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11375         FOURCC_3g__);
11376   } else if (qtdemux->comp_brands != NULL) {
11377     GstMapInfo map;
11378     guint8 *data;
11379     gsize size;
11380     gboolean res = FALSE;
11381
11382     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11383     data = map.data;
11384     size = map.size;
11385     while (size >= 4) {
11386       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11387           FOURCC_3g__);
11388       data += 4;
11389       size -= 4;
11390     }
11391     gst_buffer_unmap (qtdemux->comp_brands, &map);
11392     return res;
11393   } else {
11394     return FALSE;
11395   }
11396 }
11397
11398 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11399 static inline gboolean
11400 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11401 {
11402   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11403       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11404       || fourcc == FOURCC_albm;
11405 }
11406
11407 static void
11408 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11409     const char *tag, const char *dummy, GNode * node)
11410 {
11411   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11412   int offset;
11413   char *name;
11414   gchar *data;
11415   gdouble longitude, latitude, altitude;
11416   gint len;
11417
11418   len = QT_UINT32 (node->data);
11419   if (len <= 14)
11420     goto short_read;
11421
11422   data = node->data;
11423   offset = 14;
11424
11425   /* TODO: language code skipped */
11426
11427   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11428
11429   if (!name) {
11430     /* do not alarm in trivial case, but bail out otherwise */
11431     if (*(data + offset) != 0) {
11432       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11433           "giving up", tag);
11434     }
11435   } else {
11436     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11437         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11438     offset += strlen (name);
11439     g_free (name);
11440   }
11441
11442   if (len < offset + 2 + 4 + 4 + 4)
11443     goto short_read;
11444
11445   /* +1 +1 = skip null-terminator and location role byte */
11446   offset += 1 + 1;
11447   /* table in spec says unsigned, semantics say negative has meaning ... */
11448   longitude = QT_SFP32 (data + offset);
11449
11450   offset += 4;
11451   latitude = QT_SFP32 (data + offset);
11452
11453   offset += 4;
11454   altitude = QT_SFP32 (data + offset);
11455
11456   /* one invalid means all are invalid */
11457   if (longitude >= -180.0 && longitude <= 180.0 &&
11458       latitude >= -90.0 && latitude <= 90.0) {
11459     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11460         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11461         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11462         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11463   }
11464
11465   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11466
11467   return;
11468
11469   /* ERRORS */
11470 short_read:
11471   {
11472     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11473     return;
11474   }
11475 }
11476
11477
11478 static void
11479 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11480     const char *tag, const char *dummy, GNode * node)
11481 {
11482   guint16 y;
11483   GDate *date;
11484   gint len;
11485
11486   len = QT_UINT32 (node->data);
11487   if (len < 14)
11488     return;
11489
11490   y = QT_UINT16 ((guint8 *) node->data + 12);
11491   if (y == 0) {
11492     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11493     return;
11494   }
11495   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11496
11497   date = g_date_new_dmy (1, 1, y);
11498   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11499   g_date_free (date);
11500 }
11501
11502 static void
11503 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11504     const char *tag, const char *dummy, GNode * node)
11505 {
11506   int offset;
11507   char *tag_str = NULL;
11508   guint8 *entity;
11509   guint16 table;
11510   gint len;
11511
11512   len = QT_UINT32 (node->data);
11513   if (len <= 20)
11514     goto short_read;
11515
11516   offset = 12;
11517   entity = (guint8 *) node->data + offset;
11518   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11519     GST_DEBUG_OBJECT (qtdemux,
11520         "classification info: %c%c%c%c invalid classification entity",
11521         entity[0], entity[1], entity[2], entity[3]);
11522     return;
11523   }
11524
11525   offset += 4;
11526   table = QT_UINT16 ((guint8 *) node->data + offset);
11527
11528   /* Language code skipped */
11529
11530   offset += 4;
11531
11532   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11533    * XXXX: classification entity, fixed length 4 chars.
11534    * Y[YYYY]: classification table, max 5 chars.
11535    */
11536   tag_str = g_strdup_printf ("----://%u/%s",
11537       table, (char *) node->data + offset);
11538
11539   /* memcpy To be sure we're preserving byte order */
11540   memcpy (tag_str, entity, 4);
11541   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11542
11543   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11544
11545   g_free (tag_str);
11546
11547   return;
11548
11549   /* ERRORS */
11550 short_read:
11551   {
11552     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11553     return;
11554   }
11555 }
11556
11557 static gboolean
11558 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11559     const char *tag, const char *dummy, GNode * node)
11560 {
11561   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11562   GNode *data;
11563   char *s;
11564   int len;
11565   guint32 type;
11566   int offset;
11567   gboolean ret = TRUE;
11568   const gchar *charset = NULL;
11569
11570   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11571   if (data) {
11572     len = QT_UINT32 (data->data);
11573     type = QT_UINT32 ((guint8 *) data->data + 8);
11574     if (type == 0x00000001 && len > 16) {
11575       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11576           env_vars);
11577       if (s) {
11578         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11579         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11580         g_free (s);
11581       } else {
11582         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11583       }
11584     }
11585   } else {
11586     len = QT_UINT32 (node->data);
11587     type = QT_UINT32 ((guint8 *) node->data + 4);
11588     if ((type >> 24) == 0xa9) {
11589       gint str_len;
11590       gint lang_code;
11591
11592       /* Type starts with the (C) symbol, so the next data is a list
11593        * of (string size(16), language code(16), string) */
11594
11595       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11596       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11597
11598       /* the string + fourcc + size + 2 16bit fields,
11599        * means that there are more tags in this atom */
11600       if (len > str_len + 8 + 4) {
11601         /* TODO how to represent the same tag in different languages? */
11602         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11603             "text alternatives, reading only first one");
11604       }
11605
11606       offset = 12;
11607       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
11608       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11609
11610       if (lang_code < 0x800) {  /* MAC encoded string */
11611         charset = "mac";
11612       }
11613     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11614             QT_FOURCC ((guint8 *) node->data + 4))) {
11615       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11616
11617       /* we go for 3GP style encoding if major brands claims so,
11618        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11619       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11620           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11621               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11622         offset = 14;
11623         /* 16-bit Language code is ignored here as well */
11624         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11625       } else {
11626         goto normal;
11627       }
11628     } else {
11629     normal:
11630       offset = 8;
11631       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11632       ret = FALSE;              /* may have to fallback */
11633     }
11634     if (charset) {
11635       GError *err = NULL;
11636
11637       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11638           charset, NULL, NULL, &err);
11639       if (err) {
11640         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11641             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11642             err->message);
11643         g_error_free (err);
11644       }
11645     } else {
11646       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11647           len - offset, env_vars);
11648     }
11649     if (s) {
11650       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11651       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11652       g_free (s);
11653       ret = TRUE;
11654     } else {
11655       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11656     }
11657   }
11658   return ret;
11659 }
11660
11661 static void
11662 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11663     const char *tag, const char *dummy, GNode * node)
11664 {
11665   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11666 }
11667
11668 static void
11669 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11670     const char *tag, const char *dummy, GNode * node)
11671 {
11672   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11673   guint8 *data;
11674   char *s, *t, *k = NULL;
11675   int len;
11676   int offset;
11677   int count;
11678
11679   /* first try normal string tag if major brand not 3GP */
11680   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11681     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11682       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11683        * let's try it 3gpp way after minor safety check */
11684       data = node->data;
11685       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11686         return;
11687     } else
11688       return;
11689   }
11690
11691   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11692
11693   data = node->data;
11694
11695   len = QT_UINT32 (data);
11696   if (len < 15)
11697     goto short_read;
11698
11699   count = QT_UINT8 (data + 14);
11700   offset = 15;
11701   for (; count; count--) {
11702     gint slen;
11703
11704     if (offset + 1 > len)
11705       goto short_read;
11706     slen = QT_UINT8 (data + offset);
11707     offset += 1;
11708     if (offset + slen > len)
11709       goto short_read;
11710     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11711         slen, env_vars);
11712     if (s) {
11713       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11714       if (k) {
11715         t = g_strjoin (",", k, s, NULL);
11716         g_free (s);
11717         g_free (k);
11718         k = t;
11719       } else {
11720         k = s;
11721       }
11722     } else {
11723       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11724     }
11725     offset += slen;
11726   }
11727
11728 done:
11729   if (k) {
11730     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11731     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11732   }
11733   g_free (k);
11734
11735   return;
11736
11737   /* ERRORS */
11738 short_read:
11739   {
11740     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11741     goto done;
11742   }
11743 }
11744
11745 static void
11746 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11747     const char *tag1, const char *tag2, GNode * node)
11748 {
11749   GNode *data;
11750   int len;
11751   int type;
11752   int n1, n2;
11753
11754   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11755   if (data) {
11756     len = QT_UINT32 (data->data);
11757     type = QT_UINT32 ((guint8 *) data->data + 8);
11758     if (type == 0x00000000 && len >= 22) {
11759       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11760       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11761       if (n1 > 0) {
11762         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11763         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11764       }
11765       if (n2 > 0) {
11766         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11767         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11768       }
11769     }
11770   }
11771 }
11772
11773 static void
11774 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11775     const char *tag1, const char *dummy, GNode * node)
11776 {
11777   GNode *data;
11778   int len;
11779   int type;
11780   int n1;
11781
11782   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11783   if (data) {
11784     len = QT_UINT32 (data->data);
11785     type = QT_UINT32 ((guint8 *) data->data + 8);
11786     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11787     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11788     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11789       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11790       if (n1) {
11791         /* do not add bpm=0 */
11792         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11793         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11794             NULL);
11795       }
11796     }
11797   }
11798 }
11799
11800 static void
11801 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11802     const char *tag1, const char *dummy, GNode * node)
11803 {
11804   GNode *data;
11805   int len;
11806   int type;
11807   guint32 num;
11808
11809   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11810   if (data) {
11811     len = QT_UINT32 (data->data);
11812     type = QT_UINT32 ((guint8 *) data->data + 8);
11813     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11814     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11815     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11816       num = QT_UINT32 ((guint8 *) data->data + 16);
11817       if (num) {
11818         /* do not add num=0 */
11819         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11820         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11821       }
11822     }
11823   }
11824 }
11825
11826 static void
11827 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11828     const char *tag1, const char *dummy, GNode * node)
11829 {
11830   GNode *data;
11831   int len;
11832   int type;
11833   GstSample *sample;
11834
11835   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11836   if (data) {
11837     len = QT_UINT32 (data->data);
11838     type = QT_UINT32 ((guint8 *) data->data + 8);
11839     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11840     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11841       if ((sample =
11842               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11843                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11844         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11845         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11846         gst_sample_unref (sample);
11847       }
11848     }
11849   }
11850 }
11851
11852 static void
11853 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11854     const char *tag, const char *dummy, GNode * node)
11855 {
11856   GNode *data;
11857   char *s;
11858   int len;
11859   int type;
11860
11861   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11862   if (data) {
11863     len = QT_UINT32 (data->data);
11864     type = QT_UINT32 ((guint8 *) data->data + 8);
11865     if (type == 0x00000001 && len > 16) {
11866       guint y, m = 1, d = 1;
11867       gint ret;
11868
11869       s = g_strndup ((char *) data->data + 16, len - 16);
11870       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11871       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11872       if (ret >= 1 && y > 1500 && y < 3000) {
11873         GDate *date;
11874
11875         date = g_date_new_dmy (d, m, y);
11876         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11877         g_date_free (date);
11878       } else {
11879         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11880       }
11881       g_free (s);
11882     }
11883   }
11884 }
11885
11886 static void
11887 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11888     const char *tag, const char *dummy, GNode * node)
11889 {
11890   GNode *data;
11891
11892   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11893
11894   /* re-route to normal string tag if major brand says so
11895    * or no data atom and compatible brand suggests so */
11896   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11897       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11898     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11899     return;
11900   }
11901
11902   if (data) {
11903     guint len, type, n;
11904
11905     len = QT_UINT32 (data->data);
11906     type = QT_UINT32 ((guint8 *) data->data + 8);
11907     if (type == 0x00000000 && len >= 18) {
11908       n = QT_UINT16 ((guint8 *) data->data + 16);
11909       if (n > 0) {
11910         const gchar *genre;
11911
11912         genre = gst_tag_id3_genre_get (n - 1);
11913         if (genre != NULL) {
11914           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11915           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11916         }
11917       }
11918     }
11919   }
11920 }
11921
11922 static void
11923 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11924     const gchar * tag, guint8 * data, guint32 datasize)
11925 {
11926   gdouble value;
11927   gchar *datacopy;
11928
11929   /* make a copy to have \0 at the end */
11930   datacopy = g_strndup ((gchar *) data, datasize);
11931
11932   /* convert the str to double */
11933   if (sscanf (datacopy, "%lf", &value) == 1) {
11934     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11935     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11936   } else {
11937     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11938         datacopy);
11939   }
11940   g_free (datacopy);
11941 }
11942
11943
11944 static void
11945 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11946     const char *tag, const char *tag_bis, GNode * node)
11947 {
11948   GNode *mean;
11949   GNode *name;
11950   GNode *data;
11951   guint32 meansize;
11952   guint32 namesize;
11953   guint32 datatype;
11954   guint32 datasize;
11955   const gchar *meanstr;
11956   const gchar *namestr;
11957
11958   /* checking the whole ---- atom size for consistency */
11959   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11960     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11961     return;
11962   }
11963
11964   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11965   if (!mean) {
11966     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11967     return;
11968   }
11969
11970   meansize = QT_UINT32 (mean->data);
11971   if (meansize <= 12) {
11972     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11973     return;
11974   }
11975   meanstr = ((gchar *) mean->data) + 12;
11976   meansize -= 12;
11977
11978   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11979   if (!name) {
11980     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11981     return;
11982   }
11983
11984   namesize = QT_UINT32 (name->data);
11985   if (namesize <= 12) {
11986     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11987     return;
11988   }
11989   namestr = ((gchar *) name->data) + 12;
11990   namesize -= 12;
11991
11992   /*
11993    * Data atom is:
11994    * uint32 - size
11995    * uint32 - name
11996    * uint8  - version
11997    * uint24 - data type
11998    * uint32 - all 0
11999    * rest   - the data
12000    */
12001   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12002   if (!data) {
12003     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12004     return;
12005   }
12006   datasize = QT_UINT32 (data->data);
12007   if (datasize <= 16) {
12008     GST_WARNING_OBJECT (demux, "Data atom too small");
12009     return;
12010   }
12011   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12012
12013   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12014       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12015     static const struct
12016     {
12017       const gchar name[28];
12018       const gchar tag[28];
12019     } tags[] = {
12020       {
12021       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12022       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12023       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12024       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12025       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12026       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12027       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12028       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12029     };
12030     int i;
12031
12032     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12033       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12034         switch (gst_tag_get_type (tags[i].tag)) {
12035           case G_TYPE_DOUBLE:
12036             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12037                 ((guint8 *) data->data) + 16, datasize - 16);
12038             break;
12039           case G_TYPE_STRING:
12040             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12041             break;
12042           default:
12043             /* not reached */
12044             break;
12045         }
12046         break;
12047       }
12048     }
12049     if (i == G_N_ELEMENTS (tags))
12050       goto unknown_tag;
12051   } else {
12052     goto unknown_tag;
12053   }
12054
12055   return;
12056
12057 /* errors */
12058 unknown_tag:
12059 #ifndef GST_DISABLE_GST_DEBUG
12060   {
12061     gchar *namestr_dbg;
12062     gchar *meanstr_dbg;
12063
12064     meanstr_dbg = g_strndup (meanstr, meansize);
12065     namestr_dbg = g_strndup (namestr, namesize);
12066
12067     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12068         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12069
12070     g_free (namestr_dbg);
12071     g_free (meanstr_dbg);
12072   }
12073 #endif
12074   return;
12075 }
12076
12077 static void
12078 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12079     const char *tag_bis, GNode * node)
12080 {
12081   guint8 *data;
12082   GstBuffer *buf;
12083   guint len;
12084   GstTagList *id32_taglist = NULL;
12085
12086   GST_LOG_OBJECT (demux, "parsing ID32");
12087
12088   data = node->data;
12089   len = GST_READ_UINT32_BE (data);
12090
12091   /* need at least full box and language tag */
12092   if (len < 12 + 2)
12093     return;
12094
12095   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12096   gst_buffer_fill (buf, 0, data + 14, len - 14);
12097
12098   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12099   if (id32_taglist) {
12100     GST_LOG_OBJECT (demux, "parsing ok");
12101     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12102     gst_tag_list_unref (id32_taglist);
12103   } else {
12104     GST_LOG_OBJECT (demux, "parsing failed");
12105   }
12106
12107   gst_buffer_unref (buf);
12108 }
12109
12110 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12111     const char *tag, const char *tag_bis, GNode * node);
12112
12113 /* unmapped tags
12114 FOURCC_pcst -> if media is a podcast -> bool
12115 FOURCC_cpil -> if media is part of a compilation -> bool
12116 FOURCC_pgap -> if media is part of a gapless context -> bool
12117 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12118 */
12119
12120 static const struct
12121 {
12122   guint32 fourcc;
12123   const gchar *gst_tag;
12124   const gchar *gst_tag_bis;
12125   const GstQTDemuxAddTagFunc func;
12126 } add_funcs[] = {
12127   {
12128   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12129   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12130   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12131   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12132   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12133   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12134   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12135   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12136   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12137   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12138   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12139   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12140   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12141   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12142   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12143   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12144   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12145   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12146   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12147   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12148   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12149   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12150   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12151         qtdemux_tag_add_num}, {
12152   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12153         qtdemux_tag_add_num}, {
12154   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12155   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12156   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12157   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
12158   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12159   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12160   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12161   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12162   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12163   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12164   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12165   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12166   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12167   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12168   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12169   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12170   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12171   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12172         qtdemux_tag_add_classification}, {
12173   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12174   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12175   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12176
12177     /* This is a special case, some tags are stored in this
12178      * 'reverse dns naming', according to:
12179      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12180      * bug #614471
12181      */
12182   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12183     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12184   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12185 };
12186
12187 struct _GstQtDemuxTagList
12188 {
12189   GstQTDemux *demux;
12190   GstTagList *taglist;
12191 };
12192 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12193
12194 static void
12195 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12196 {
12197   gint len;
12198   guint8 *data;
12199   GstBuffer *buf;
12200   gchar *media_type;
12201   const gchar *style;
12202   GstSample *sample;
12203   GstStructure *s;
12204   guint i;
12205   guint8 ndata[4];
12206   GstQTDemux *demux = qtdemuxtaglist->demux;
12207   GstTagList *taglist = qtdemuxtaglist->taglist;
12208
12209   data = node->data;
12210   len = QT_UINT32 (data);
12211   buf = gst_buffer_new_and_alloc (len);
12212   gst_buffer_fill (buf, 0, data, len);
12213
12214   /* heuristic to determine style of tag */
12215   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12216       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12217     style = "itunes";
12218   else if (demux->major_brand == FOURCC_qt__)
12219     style = "quicktime";
12220   /* fall back to assuming iso/3gp tag style */
12221   else
12222     style = "iso";
12223
12224   /* santize the name for the caps. */
12225   for (i = 0; i < 4; i++) {
12226     guint8 d = data[4 + i];
12227     if (g_ascii_isalnum (d))
12228       ndata[i] = g_ascii_tolower (d);
12229     else
12230       ndata[i] = '_';
12231   }
12232
12233   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12234       ndata[0], ndata[1], ndata[2], ndata[3]);
12235   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12236
12237   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12238   sample = gst_sample_new (buf, NULL, NULL, s);
12239   gst_buffer_unref (buf);
12240   g_free (media_type);
12241
12242   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12243       len, s);
12244
12245   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12246       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12247
12248   gst_sample_unref (sample);
12249 }
12250
12251 static void
12252 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12253 {
12254   GNode *meta;
12255   GNode *ilst;
12256   GNode *xmp_;
12257   GNode *node;
12258   gint i;
12259   GstQtDemuxTagList demuxtaglist;
12260
12261   demuxtaglist.demux = qtdemux;
12262   demuxtaglist.taglist = taglist;
12263
12264   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12265   if (meta != NULL) {
12266     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12267     if (ilst == NULL) {
12268       GST_LOG_OBJECT (qtdemux, "no ilst");
12269       return;
12270     }
12271   } else {
12272     ilst = udta;
12273     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12274   }
12275
12276   i = 0;
12277   while (i < G_N_ELEMENTS (add_funcs)) {
12278     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12279     if (node) {
12280       gint len;
12281
12282       len = QT_UINT32 (node->data);
12283       if (len < 12) {
12284         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12285             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12286       } else {
12287         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12288             add_funcs[i].gst_tag_bis, node);
12289       }
12290       g_node_destroy (node);
12291     } else {
12292       i++;
12293     }
12294   }
12295
12296   /* parsed nodes have been removed, pass along remainder as blob */
12297   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12298       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12299
12300   /* parse up XMP_ node if existing */
12301   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12302   if (xmp_ != NULL) {
12303     GstBuffer *buf;
12304     GstTagList *xmptaglist;
12305
12306     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12307         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12308     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12309     gst_buffer_unref (buf);
12310
12311     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12312   } else {
12313     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12314   }
12315 }
12316
12317 typedef struct
12318 {
12319   GstStructure *structure;      /* helper for sort function */
12320   gchar *location;
12321   guint min_req_bitrate;
12322   guint min_req_qt_version;
12323 } GstQtReference;
12324
12325 static gint
12326 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12327 {
12328   GstQtReference *ref_a = (GstQtReference *) a;
12329   GstQtReference *ref_b = (GstQtReference *) b;
12330
12331   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12332     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12333
12334   /* known bitrates go before unknown; higher bitrates go first */
12335   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12336 }
12337
12338 /* sort the redirects and post a message for the application.
12339  */
12340 static void
12341 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12342 {
12343   GstQtReference *best;
12344   GstStructure *s;
12345   GstMessage *msg;
12346   GValue list_val = { 0, };
12347   GList *l;
12348
12349   g_assert (references != NULL);
12350
12351   references = g_list_sort (references, qtdemux_redirects_sort_func);
12352
12353   best = (GstQtReference *) references->data;
12354
12355   g_value_init (&list_val, GST_TYPE_LIST);
12356
12357   for (l = references; l != NULL; l = l->next) {
12358     GstQtReference *ref = (GstQtReference *) l->data;
12359     GValue struct_val = { 0, };
12360
12361     ref->structure = gst_structure_new ("redirect",
12362         "new-location", G_TYPE_STRING, ref->location, NULL);
12363
12364     if (ref->min_req_bitrate > 0) {
12365       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12366           ref->min_req_bitrate, NULL);
12367     }
12368
12369     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12370     g_value_set_boxed (&struct_val, ref->structure);
12371     gst_value_list_append_value (&list_val, &struct_val);
12372     g_value_unset (&struct_val);
12373     /* don't free anything here yet, since we need best->structure below */
12374   }
12375
12376   g_assert (best != NULL);
12377   s = gst_structure_copy (best->structure);
12378
12379   if (g_list_length (references) > 1) {
12380     gst_structure_set_value (s, "locations", &list_val);
12381   }
12382
12383   g_value_unset (&list_val);
12384
12385   for (l = references; l != NULL; l = l->next) {
12386     GstQtReference *ref = (GstQtReference *) l->data;
12387
12388     gst_structure_free (ref->structure);
12389     g_free (ref->location);
12390     g_free (ref);
12391   }
12392   g_list_free (references);
12393
12394   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12395   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12396   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12397   qtdemux->posted_redirect = TRUE;
12398 }
12399
12400 /* look for redirect nodes, collect all redirect information and
12401  * process it.
12402  */
12403 static gboolean
12404 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12405 {
12406   GNode *rmra, *rmda, *rdrf;
12407
12408   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12409   if (rmra) {
12410     GList *redirects = NULL;
12411
12412     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12413     while (rmda) {
12414       GstQtReference ref = { NULL, NULL, 0, 0 };
12415       GNode *rmdr, *rmvc;
12416
12417       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12418         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12419         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12420             ref.min_req_bitrate);
12421       }
12422
12423       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12424         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12425         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12426
12427 #ifndef GST_DISABLE_GST_DEBUG
12428         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12429 #endif
12430         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12431
12432         GST_LOG_OBJECT (qtdemux,
12433             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12434             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12435             bitmask, check_type);
12436         if (package == FOURCC_qtim && check_type == 0) {
12437           ref.min_req_qt_version = version;
12438         }
12439       }
12440
12441       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12442       if (rdrf) {
12443         guint32 ref_type;
12444         guint8 *ref_data;
12445         guint ref_len;
12446
12447         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12448         if (ref_len > 20) {
12449           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12450           ref_data = (guint8 *) rdrf->data + 20;
12451           if (ref_type == FOURCC_alis) {
12452             guint record_len, record_version, fn_len;
12453
12454             if (ref_len > 70) {
12455               /* MacOSX alias record, google for alias-layout.txt */
12456               record_len = QT_UINT16 (ref_data + 4);
12457               record_version = QT_UINT16 (ref_data + 4 + 2);
12458               fn_len = QT_UINT8 (ref_data + 50);
12459               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12460                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12461               }
12462             } else {
12463               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12464                   ref_len);
12465             }
12466           } else if (ref_type == FOURCC_url_) {
12467             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12468           } else {
12469             GST_DEBUG_OBJECT (qtdemux,
12470                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12471                 GST_FOURCC_ARGS (ref_type));
12472           }
12473           if (ref.location != NULL) {
12474             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12475             redirects =
12476                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12477           } else {
12478             GST_WARNING_OBJECT (qtdemux,
12479                 "Failed to extract redirect location from rdrf atom");
12480           }
12481         } else {
12482           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12483         }
12484       }
12485
12486       /* look for others */
12487       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12488     }
12489
12490     if (redirects != NULL) {
12491       qtdemux_process_redirects (qtdemux, redirects);
12492     }
12493   }
12494   return TRUE;
12495 }
12496
12497 static GstTagList *
12498 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12499 {
12500   const gchar *fmt;
12501
12502   if (tags == NULL) {
12503     tags = gst_tag_list_new_empty ();
12504     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12505   }
12506
12507   if (qtdemux->major_brand == FOURCC_mjp2)
12508     fmt = "Motion JPEG 2000";
12509   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12510     fmt = "3GP";
12511   else if (qtdemux->major_brand == FOURCC_qt__)
12512     fmt = "Quicktime";
12513   else if (qtdemux->fragmented)
12514     fmt = "ISO fMP4";
12515   else
12516     fmt = "ISO MP4/M4A";
12517
12518   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12519       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12520
12521   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12522       fmt, NULL);
12523
12524   return tags;
12525 }
12526
12527 /* we have read the complete moov node now.
12528  * This function parses all of the relevant info, creates the traks and
12529  * prepares all data structures for playback
12530  */
12531 static gboolean
12532 qtdemux_parse_tree (GstQTDemux * qtdemux)
12533 {
12534   GNode *mvhd;
12535   GNode *trak;
12536   GNode *udta;
12537   GNode *mvex;
12538   GstClockTime duration;
12539   GNode *pssh;
12540   guint64 creation_time;
12541   GstDateTime *datetime = NULL;
12542   gint version;
12543
12544   /* make sure we have a usable taglist */
12545   if (!qtdemux->tag_list) {
12546     qtdemux->tag_list = gst_tag_list_new_empty ();
12547     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12548   } else {
12549     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12550   }
12551
12552   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12553   if (mvhd == NULL) {
12554     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12555     return qtdemux_parse_redirects (qtdemux);
12556   }
12557
12558   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12559   if (version == 1) {
12560     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12561     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12562     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12563   } else if (version == 0) {
12564     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12565     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12566     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12567   } else {
12568     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12569     return FALSE;
12570   }
12571
12572   /* Moving qt creation time (secs since 1904) to unix time */
12573   if (creation_time != 0) {
12574     /* Try to use epoch first as it should be faster and more commonly found */
12575     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12576       GTimeVal now;
12577
12578       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12579       /* some data cleansing sanity */
12580       g_get_current_time (&now);
12581       if (now.tv_sec + 24 * 3600 < creation_time) {
12582         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12583       } else {
12584         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12585       }
12586     } else {
12587       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12588       GDateTime *dt, *dt_local;
12589
12590       dt = g_date_time_add_seconds (base_dt, creation_time);
12591       dt_local = g_date_time_to_local (dt);
12592       datetime = gst_date_time_new_from_g_date_time (dt_local);
12593
12594       g_date_time_unref (base_dt);
12595       g_date_time_unref (dt);
12596     }
12597   }
12598   if (datetime) {
12599     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12600     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12601         datetime, NULL);
12602     gst_date_time_unref (datetime);
12603   }
12604
12605   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12606   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12607
12608   /* check for fragmented file and get some (default) data */
12609   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12610   if (mvex) {
12611     GNode *mehd;
12612     GstByteReader mehd_data;
12613
12614     /* let track parsing or anyone know weird stuff might happen ... */
12615     qtdemux->fragmented = TRUE;
12616
12617     /* compensate for total duration */
12618     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12619     if (mehd)
12620       qtdemux_parse_mehd (qtdemux, &mehd_data);
12621   }
12622
12623   /* set duration in the segment info */
12624   gst_qtdemux_get_duration (qtdemux, &duration);
12625   if (duration) {
12626     qtdemux->segment.duration = duration;
12627     /* also do not exceed duration; stop is set that way post seek anyway,
12628      * and segment activation falls back to duration,
12629      * whereas loop only checks stop, so let's align this here as well */
12630     qtdemux->segment.stop = duration;
12631   }
12632
12633   /* parse all traks */
12634   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12635   while (trak) {
12636     qtdemux_parse_trak (qtdemux, trak);
12637     /* iterate all siblings */
12638     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12639   }
12640
12641   if (!qtdemux->tag_list) {
12642     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12643     qtdemux->tag_list = gst_tag_list_new_empty ();
12644     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12645   } else {
12646     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12647   }
12648
12649   /* find tags */
12650   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12651   if (udta) {
12652     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12653   } else {
12654     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12655   }
12656
12657   /* maybe also some tags in meta box */
12658   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12659   if (udta) {
12660     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12661     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12662   } else {
12663     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12664   }
12665
12666   /* parse any protection system info */
12667   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12668   while (pssh) {
12669     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12670     qtdemux_parse_pssh (qtdemux, pssh);
12671     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12672   }
12673
12674   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12675
12676   return TRUE;
12677 }
12678
12679 /* taken from ffmpeg */
12680 static int
12681 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12682 {
12683   int count = 4;
12684   int len = 0;
12685
12686   while (count--) {
12687     int c;
12688
12689     if (ptr >= end)
12690       return -1;
12691
12692     c = *ptr++;
12693     len = (len << 7) | (c & 0x7f);
12694     if (!(c & 0x80))
12695       break;
12696   }
12697   *end_out = ptr;
12698   return len;
12699 }
12700
12701 /* this can change the codec originally present in @list */
12702 static void
12703 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12704     GNode * esds, GstTagList * list)
12705 {
12706   int len = QT_UINT32 (esds->data);
12707   guint8 *ptr = esds->data;
12708   guint8 *end = ptr + len;
12709   int tag;
12710   guint8 *data_ptr = NULL;
12711   int data_len = 0;
12712   guint8 object_type_id = 0;
12713   const char *codec_name = NULL;
12714   GstCaps *caps = NULL;
12715
12716   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12717   ptr += 8;
12718   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12719   ptr += 4;
12720   while (ptr + 1 < end) {
12721     tag = QT_UINT8 (ptr);
12722     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12723     ptr++;
12724     len = read_descr_size (ptr, end, &ptr);
12725     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12726
12727     /* Check the stated amount of data is available for reading */
12728     if (len < 0 || ptr + len > end)
12729       break;
12730
12731     switch (tag) {
12732       case ES_DESCRIPTOR_TAG:
12733         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12734         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12735         ptr += 3;
12736         break;
12737       case DECODER_CONFIG_DESC_TAG:{
12738         guint max_bitrate, avg_bitrate;
12739
12740         object_type_id = QT_UINT8 (ptr);
12741         max_bitrate = QT_UINT32 (ptr + 5);
12742         avg_bitrate = QT_UINT32 (ptr + 9);
12743         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12744         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12745         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12746         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12747         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12748         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12749           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12750               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12751         }
12752         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12753           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12754               avg_bitrate, NULL);
12755         }
12756         ptr += 13;
12757         break;
12758       }
12759       case DECODER_SPECIFIC_INFO_TAG:
12760         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12761         if (object_type_id == 0xe0 && len == 0x40) {
12762           guint8 *data;
12763           GstStructure *s;
12764           guint32 clut[16];
12765           gint i;
12766
12767           GST_DEBUG_OBJECT (qtdemux,
12768               "Have VOBSUB palette. Creating palette event");
12769           /* move to decConfigDescr data and read palette */
12770           data = ptr;
12771           for (i = 0; i < 16; i++) {
12772             clut[i] = QT_UINT32 (data);
12773             data += 4;
12774           }
12775
12776           s = gst_structure_new ("application/x-gst-dvd", "event",
12777               G_TYPE_STRING, "dvd-spu-clut-change",
12778               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12779               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12780               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12781               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12782               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12783               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12784               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12785               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12786               NULL);
12787
12788           /* store event and trigger custom processing */
12789           stream->pending_event =
12790               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12791         } else {
12792           /* Generic codec_data handler puts it on the caps */
12793           data_ptr = ptr;
12794           data_len = len;
12795         }
12796
12797         ptr += len;
12798         break;
12799       case SL_CONFIG_DESC_TAG:
12800         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12801         ptr += 1;
12802         break;
12803       default:
12804         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12805             tag);
12806         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12807         ptr += len;
12808         break;
12809     }
12810   }
12811
12812   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12813    * in use, and should also be used to override some other parameters for some
12814    * codecs. */
12815   switch (object_type_id) {
12816     case 0x20:                 /* MPEG-4 */
12817       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12818        * profile_and_level_indication */
12819       if (data_ptr != NULL && data_len >= 5 &&
12820           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12821         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12822             data_ptr + 4, data_len - 4);
12823       }
12824       break;                    /* Nothing special needed here */
12825     case 0x21:                 /* H.264 */
12826       codec_name = "H.264 / AVC";
12827       caps = gst_caps_new_simple ("video/x-h264",
12828           "stream-format", G_TYPE_STRING, "avc",
12829           "alignment", G_TYPE_STRING, "au", NULL);
12830       break;
12831     case 0x40:                 /* AAC (any) */
12832     case 0x66:                 /* AAC Main */
12833     case 0x67:                 /* AAC LC */
12834     case 0x68:                 /* AAC SSR */
12835       /* Override channels and rate based on the codec_data, as it's often
12836        * wrong. */
12837       /* Only do so for basic setup without HE-AAC extension */
12838       if (data_ptr && data_len == 2) {
12839         guint channels, rate;
12840
12841         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
12842         if (channels > 0)
12843           stream->n_channels = channels;
12844
12845         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
12846         if (rate > 0)
12847           stream->rate = rate;
12848       }
12849
12850       /* Set level and profile if possible */
12851       if (data_ptr != NULL && data_len >= 2) {
12852         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12853             data_ptr, data_len);
12854       } else {
12855         const gchar *profile_str = NULL;
12856         GstBuffer *buffer;
12857         GstMapInfo map;
12858         guint8 *codec_data;
12859         gint rate_idx, profile;
12860
12861         /* No codec_data, let's invent something.
12862          * FIXME: This is wrong for SBR! */
12863
12864         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
12865
12866         buffer = gst_buffer_new_and_alloc (2);
12867         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
12868         codec_data = map.data;
12869
12870         rate_idx =
12871             gst_codec_utils_aac_get_index_from_sample_rate (stream->rate);
12872
12873         switch (object_type_id) {
12874           case 0x66:
12875             profile_str = "main";
12876             profile = 0;
12877             break;
12878           case 0x67:
12879             profile_str = "lc";
12880             profile = 1;
12881             break;
12882           case 0x68:
12883             profile_str = "ssr";
12884             profile = 2;
12885             break;
12886           default:
12887             profile = 3;
12888             break;
12889         }
12890
12891         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
12892         codec_data[1] = ((rate_idx & 0x1) << 7) | (stream->n_channels << 3);
12893
12894         gst_buffer_unmap (buffer, &map);
12895         gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12896             buffer, NULL);
12897         gst_buffer_unref (buffer);
12898
12899         if (profile_str) {
12900           gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
12901               profile_str, NULL);
12902         }
12903       }
12904       break;
12905     case 0x60:                 /* MPEG-2, various profiles */
12906     case 0x61:
12907     case 0x62:
12908     case 0x63:
12909     case 0x64:
12910     case 0x65:
12911       codec_name = "MPEG-2 video";
12912       caps = gst_caps_new_simple ("video/mpeg",
12913           "mpegversion", G_TYPE_INT, 2,
12914           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12915       break;
12916     case 0x69:                 /* MPEG-2 BC audio */
12917     case 0x6B:                 /* MPEG-1 audio */
12918       caps = gst_caps_new_simple ("audio/mpeg",
12919           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12920       codec_name = "MPEG-1 audio";
12921       break;
12922     case 0x6A:                 /* MPEG-1 */
12923       codec_name = "MPEG-1 video";
12924       caps = gst_caps_new_simple ("video/mpeg",
12925           "mpegversion", G_TYPE_INT, 1,
12926           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12927       break;
12928     case 0x6C:                 /* MJPEG */
12929       caps =
12930           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12931           NULL);
12932       codec_name = "Motion-JPEG";
12933       break;
12934     case 0x6D:                 /* PNG */
12935       caps =
12936           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12937           NULL);
12938       codec_name = "PNG still images";
12939       break;
12940     case 0x6E:                 /* JPEG2000 */
12941       codec_name = "JPEG-2000";
12942       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12943       break;
12944     case 0xA4:                 /* Dirac */
12945       codec_name = "Dirac";
12946       caps = gst_caps_new_empty_simple ("video/x-dirac");
12947       break;
12948     case 0xA5:                 /* AC3 */
12949       codec_name = "AC-3 audio";
12950       caps = gst_caps_new_simple ("audio/x-ac3",
12951           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12952       break;
12953     case 0xA9:                 /* AC3 */
12954       codec_name = "DTS audio";
12955       caps = gst_caps_new_simple ("audio/x-dts",
12956           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12957       break;
12958     case 0xE1:                 /* QCELP */
12959       /* QCELP, the codec_data is a riff tag (little endian) with
12960        * 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). */
12961       caps = gst_caps_new_empty_simple ("audio/qcelp");
12962       codec_name = "QCELP";
12963       break;
12964     default:
12965       break;
12966   }
12967
12968   /* If we have a replacement caps, then change our caps for this stream */
12969   if (caps) {
12970     gst_caps_unref (stream->caps);
12971     stream->caps = caps;
12972   }
12973
12974   if (codec_name && list)
12975     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12976         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12977
12978   /* Add the codec_data attribute to caps, if we have it */
12979   if (data_ptr) {
12980     GstBuffer *buffer;
12981
12982     buffer = gst_buffer_new_and_alloc (data_len);
12983     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12984
12985     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12986     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12987
12988     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12989         buffer, NULL);
12990     gst_buffer_unref (buffer);
12991   }
12992
12993 }
12994
12995 #define _codec(name) \
12996   do { \
12997     if (codec_name) { \
12998       *codec_name = g_strdup (name); \
12999     } \
13000   } while (0)
13001
13002 static GstCaps *
13003 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13004     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13005 {
13006   GstCaps *caps = NULL;
13007   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13008
13009   switch (fourcc) {
13010     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
13011       _codec ("PNG still images");
13012       caps = gst_caps_new_empty_simple ("image/png");
13013       break;
13014     case FOURCC_jpeg:
13015       _codec ("JPEG still images");
13016       caps =
13017           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13018           NULL);
13019       break;
13020     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13021     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13022     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13023     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13024       _codec ("Motion-JPEG");
13025       caps =
13026           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13027           NULL);
13028       break;
13029     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13030       _codec ("Motion-JPEG format B");
13031       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13032       break;
13033     case FOURCC_mjp2:
13034       _codec ("JPEG-2000");
13035       /* override to what it should be according to spec, avoid palette_data */
13036       stream->bits_per_sample = 24;
13037       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13038       break;
13039     case FOURCC_SVQ3:
13040       _codec ("Sorensen video v.3");
13041       caps = gst_caps_new_simple ("video/x-svq",
13042           "svqversion", G_TYPE_INT, 3, NULL);
13043       break;
13044     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13045     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13046       _codec ("Sorensen video v.1");
13047       caps = gst_caps_new_simple ("video/x-svq",
13048           "svqversion", G_TYPE_INT, 1, NULL);
13049       break;
13050     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13051       caps = gst_caps_new_empty_simple ("video/x-raw");
13052       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13053       _codec ("Windows Raw RGB");
13054       break;
13055     case FOURCC_raw_:
13056     {
13057       guint16 bps;
13058
13059       bps = QT_UINT16 (stsd_data + 98);
13060       switch (bps) {
13061         case 15:
13062           format = GST_VIDEO_FORMAT_RGB15;
13063           break;
13064         case 16:
13065           format = GST_VIDEO_FORMAT_RGB16;
13066           break;
13067         case 24:
13068           format = GST_VIDEO_FORMAT_RGB;
13069           break;
13070         case 32:
13071           format = GST_VIDEO_FORMAT_ARGB;
13072           break;
13073         default:
13074           /* unknown */
13075           break;
13076       }
13077       break;
13078     }
13079     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13080       format = GST_VIDEO_FORMAT_I420;
13081       break;
13082     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13083     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13084       format = GST_VIDEO_FORMAT_I420;
13085       break;
13086     case FOURCC_2vuy:
13087     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13088       format = GST_VIDEO_FORMAT_UYVY;
13089       break;
13090     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13091       format = GST_VIDEO_FORMAT_v308;
13092       break;
13093     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13094       format = GST_VIDEO_FORMAT_v216;
13095       break;
13096     case FOURCC_v210:
13097       format = GST_VIDEO_FORMAT_v210;
13098       break;
13099     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13100       format = GST_VIDEO_FORMAT_r210;
13101       break;
13102       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13103          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13104          format = GST_VIDEO_FORMAT_v410;
13105          break;
13106        */
13107       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13108        * but different order than AYUV
13109        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13110        format = GST_VIDEO_FORMAT_v408;
13111        break;
13112        */
13113     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13114     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13115       _codec ("MPEG-1 video");
13116       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13117           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13118       break;
13119     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13120     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13121     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13122     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13123     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13124     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13125     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13126     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13127     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13128     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13129     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13130     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13131     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13132     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13133     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13134     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13135     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13136     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13137     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13138     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13139     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13140     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13141     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13142     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13143     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13144     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13145     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13146     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13147     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13148     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13149     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13150     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13151     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13152     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13153     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13154     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13155     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13156     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13157     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13158     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13159     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13160     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13161     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13162     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13163     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13164     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13165       _codec ("MPEG-2 video");
13166       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13167           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13168       break;
13169     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13170       _codec ("GIF still images");
13171       caps = gst_caps_new_empty_simple ("image/gif");
13172       break;
13173     case FOURCC_h263:
13174     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13175     case FOURCC_s263:
13176     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13177       _codec ("H.263");
13178       /* ffmpeg uses the height/width props, don't know why */
13179       caps = gst_caps_new_simple ("video/x-h263",
13180           "variant", G_TYPE_STRING, "itu", NULL);
13181       break;
13182     case FOURCC_mp4v:
13183     case FOURCC_MP4V:
13184       _codec ("MPEG-4 video");
13185       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13186           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13187       break;
13188     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13189     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13190       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13191       caps = gst_caps_new_simple ("video/x-msmpeg",
13192           "msmpegversion", G_TYPE_INT, 43, NULL);
13193       break;
13194     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13195       _codec ("DivX 3");
13196       caps = gst_caps_new_simple ("video/x-divx",
13197           "divxversion", G_TYPE_INT, 3, NULL);
13198       break;
13199     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13200     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13201       _codec ("DivX 4");
13202       caps = gst_caps_new_simple ("video/x-divx",
13203           "divxversion", G_TYPE_INT, 4, NULL);
13204       break;
13205     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13206       _codec ("DivX 5");
13207       caps = gst_caps_new_simple ("video/x-divx",
13208           "divxversion", G_TYPE_INT, 5, NULL);
13209       break;
13210
13211     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13212       _codec ("FFV1");
13213       caps = gst_caps_new_simple ("video/x-ffv",
13214           "ffvversion", G_TYPE_INT, 1, NULL);
13215       break;
13216
13217     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13218     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13219     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
13220     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
13221     case FOURCC_FMP4:
13222     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13223       caps = gst_caps_new_simple ("video/mpeg",
13224           "mpegversion", G_TYPE_INT, 4, NULL);
13225       _codec ("MPEG-4");
13226       break;
13227
13228     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13229       _codec ("Cinepak");
13230       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13231       break;
13232     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13233       _codec ("Apple QuickDraw");
13234       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13235       break;
13236     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13237       _codec ("Apple video");
13238       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13239       break;
13240     case FOURCC_H264:
13241     case FOURCC_avc1:
13242       _codec ("H.264 / AVC");
13243       caps = gst_caps_new_simple ("video/x-h264",
13244           "stream-format", G_TYPE_STRING, "avc",
13245           "alignment", G_TYPE_STRING, "au", NULL);
13246       break;
13247     case FOURCC_avc3:
13248       _codec ("H.264 / AVC");
13249       caps = gst_caps_new_simple ("video/x-h264",
13250           "stream-format", G_TYPE_STRING, "avc3",
13251           "alignment", G_TYPE_STRING, "au", NULL);
13252       break;
13253     case FOURCC_H265:
13254     case FOURCC_hvc1:
13255       _codec ("H.265 / HEVC");
13256       caps = gst_caps_new_simple ("video/x-h265",
13257           "stream-format", G_TYPE_STRING, "hvc1",
13258           "alignment", G_TYPE_STRING, "au", NULL);
13259       break;
13260     case FOURCC_hev1:
13261       _codec ("H.265 / HEVC");
13262       caps = gst_caps_new_simple ("video/x-h265",
13263           "stream-format", G_TYPE_STRING, "hev1",
13264           "alignment", G_TYPE_STRING, "au", NULL);
13265       break;
13266     case FOURCC_rle_:
13267       _codec ("Run-length encoding");
13268       caps = gst_caps_new_simple ("video/x-rle",
13269           "layout", G_TYPE_STRING, "quicktime", NULL);
13270       break;
13271     case FOURCC_WRLE:
13272       _codec ("Run-length encoding");
13273       caps = gst_caps_new_simple ("video/x-rle",
13274           "layout", G_TYPE_STRING, "microsoft", NULL);
13275       break;
13276     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13277     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13278       _codec ("Indeo Video 3");
13279       caps = gst_caps_new_simple ("video/x-indeo",
13280           "indeoversion", G_TYPE_INT, 3, NULL);
13281       break;
13282     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13283     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13284       _codec ("Intel Video 4");
13285       caps = gst_caps_new_simple ("video/x-indeo",
13286           "indeoversion", G_TYPE_INT, 4, NULL);
13287       break;
13288     case FOURCC_dvcp:
13289     case FOURCC_dvc_:
13290     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13291     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13292     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13293     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13294     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13295     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13296       _codec ("DV Video");
13297       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13298           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13299       break;
13300     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13301     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13302       _codec ("DVCPro50 Video");
13303       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13304           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13305       break;
13306     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13307     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13308       _codec ("DVCProHD Video");
13309       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13310           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13311       break;
13312     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13313       _codec ("Apple Graphics (SMC)");
13314       caps = gst_caps_new_empty_simple ("video/x-smc");
13315       break;
13316     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13317       _codec ("VP3");
13318       caps = gst_caps_new_empty_simple ("video/x-vp3");
13319       break;
13320     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13321       _codec ("VP6 Flash");
13322       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13323       break;
13324     case FOURCC_XiTh:
13325       _codec ("Theora");
13326       caps = gst_caps_new_empty_simple ("video/x-theora");
13327       /* theora uses one byte of padding in the data stream because it does not
13328        * allow 0 sized packets while theora does */
13329       stream->padding = 1;
13330       break;
13331     case FOURCC_drac:
13332       _codec ("Dirac");
13333       caps = gst_caps_new_empty_simple ("video/x-dirac");
13334       break;
13335     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13336       _codec ("TIFF still images");
13337       caps = gst_caps_new_empty_simple ("image/tiff");
13338       break;
13339     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13340       _codec ("Apple Intermediate Codec");
13341       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13342       break;
13343     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13344       _codec ("AVID DNxHD");
13345       caps = gst_caps_from_string ("video/x-dnxhd");
13346       break;
13347     case FOURCC_VP80:
13348       _codec ("On2 VP8");
13349       caps = gst_caps_from_string ("video/x-vp8");
13350       break;
13351     case FOURCC_apcs:
13352       _codec ("Apple ProRes LT");
13353       caps =
13354           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13355           NULL);
13356       break;
13357     case FOURCC_apch:
13358       _codec ("Apple ProRes HQ");
13359       caps =
13360           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13361           NULL);
13362       break;
13363     case FOURCC_apcn:
13364       _codec ("Apple ProRes");
13365       caps =
13366           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13367           "standard", NULL);
13368       break;
13369     case FOURCC_apco:
13370       _codec ("Apple ProRes Proxy");
13371       caps =
13372           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13373           "proxy", NULL);
13374       break;
13375     case FOURCC_ap4h:
13376       _codec ("Apple ProRes 4444");
13377       caps =
13378           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13379           "4444", NULL);
13380       break;
13381     case FOURCC_ap4x:
13382       _codec ("Apple ProRes 4444 XQ");
13383       caps =
13384           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13385           "4444xq", NULL);
13386       break;
13387     case FOURCC_vc_1:
13388     case FOURCC_ovc1:
13389       _codec ("VC-1");
13390       caps = gst_caps_new_simple ("video/x-wmv",
13391           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13392       break;
13393     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13394     default:
13395     {
13396       char *s, fourstr[5];
13397
13398       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13399       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
13400       caps = gst_caps_new_empty_simple (s);
13401       g_free (s);
13402       break;
13403     }
13404   }
13405
13406   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13407     GstVideoInfo info;
13408
13409     gst_video_info_init (&info);
13410     gst_video_info_set_format (&info, format, stream->width, stream->height);
13411
13412     caps = gst_video_info_to_caps (&info);
13413     *codec_name = gst_pb_utils_get_codec_description (caps);
13414
13415     /* enable clipping for raw video streams */
13416     stream->need_clip = TRUE;
13417   }
13418
13419   return caps;
13420 }
13421
13422 static GstCaps *
13423 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13424     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13425 {
13426   GstCaps *caps;
13427   const GstStructure *s;
13428   const gchar *name;
13429   gint endian = 0;
13430   GstAudioFormat format = 0;
13431   gint depth;
13432
13433   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13434
13435   depth = stream->bytes_per_packet * 8;
13436
13437   switch (fourcc) {
13438     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13439     case FOURCC_raw_:
13440       /* 8-bit audio is unsigned */
13441       if (depth == 8)
13442         format = GST_AUDIO_FORMAT_U8;
13443       /* otherwise it's signed and big-endian just like 'twos' */
13444     case FOURCC_twos:
13445       endian = G_BIG_ENDIAN;
13446       /* fall-through */
13447     case FOURCC_sowt:
13448     {
13449       gchar *str;
13450
13451       if (!endian)
13452         endian = G_LITTLE_ENDIAN;
13453
13454       if (!format)
13455         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13456
13457       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13458       _codec (str);
13459       g_free (str);
13460
13461       caps = gst_caps_new_simple ("audio/x-raw",
13462           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13463           "layout", G_TYPE_STRING, "interleaved", NULL);
13464       break;
13465     }
13466     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13467       _codec ("Raw 64-bit floating-point audio");
13468       caps = gst_caps_new_simple ("audio/x-raw",
13469           "format", G_TYPE_STRING, "F64BE",
13470           "layout", G_TYPE_STRING, "interleaved", NULL);
13471       break;
13472     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13473       _codec ("Raw 32-bit floating-point audio");
13474       caps = gst_caps_new_simple ("audio/x-raw",
13475           "format", G_TYPE_STRING, "F32BE",
13476           "layout", G_TYPE_STRING, "interleaved", NULL);
13477       break;
13478     case FOURCC_in24:
13479       _codec ("Raw 24-bit PCM audio");
13480       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13481        * endian later */
13482       caps = gst_caps_new_simple ("audio/x-raw",
13483           "format", G_TYPE_STRING, "S24BE",
13484           "layout", G_TYPE_STRING, "interleaved", NULL);
13485       break;
13486     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13487       _codec ("Raw 32-bit PCM audio");
13488       caps = gst_caps_new_simple ("audio/x-raw",
13489           "format", G_TYPE_STRING, "S32BE",
13490           "layout", G_TYPE_STRING, "interleaved", NULL);
13491       break;
13492     case FOURCC_ulaw:
13493       _codec ("Mu-law audio");
13494       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13495       break;
13496     case FOURCC_alaw:
13497       _codec ("A-law audio");
13498       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13499       break;
13500     case 0x0200736d:
13501     case 0x6d730002:
13502       _codec ("Microsoft ADPCM");
13503       /* Microsoft ADPCM-ACM code 2 */
13504       caps = gst_caps_new_simple ("audio/x-adpcm",
13505           "layout", G_TYPE_STRING, "microsoft", NULL);
13506       break;
13507     case 0x1100736d:
13508     case 0x6d730011:
13509       _codec ("DVI/IMA ADPCM");
13510       caps = gst_caps_new_simple ("audio/x-adpcm",
13511           "layout", G_TYPE_STRING, "dvi", NULL);
13512       break;
13513     case 0x1700736d:
13514     case 0x6d730017:
13515       _codec ("DVI/Intel IMA ADPCM");
13516       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13517       caps = gst_caps_new_simple ("audio/x-adpcm",
13518           "layout", G_TYPE_STRING, "quicktime", NULL);
13519       break;
13520     case 0x5500736d:
13521     case 0x6d730055:
13522       /* MPEG layer 3, CBR only (pre QT4.1) */
13523     case FOURCC__mp3:
13524       _codec ("MPEG-1 layer 3");
13525       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13526       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13527           "mpegversion", G_TYPE_INT, 1, NULL);
13528       break;
13529     case 0x20736d:
13530     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13531       _codec ("EAC-3 audio");
13532       caps = gst_caps_new_simple ("audio/x-eac3",
13533           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13534       stream->sampled = TRUE;
13535       break;
13536     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13537     case FOURCC_ac_3:
13538       _codec ("AC-3 audio");
13539       caps = gst_caps_new_simple ("audio/x-ac3",
13540           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13541       stream->sampled = TRUE;
13542       break;
13543     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13544     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13545       _codec ("DTS audio");
13546       caps = gst_caps_new_simple ("audio/x-dts",
13547           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13548       stream->sampled = TRUE;
13549       break;
13550     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13551     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13552       _codec ("DTS-HD audio");
13553       caps = gst_caps_new_simple ("audio/x-dts",
13554           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13555       stream->sampled = TRUE;
13556       break;
13557     case FOURCC_MAC3:
13558       _codec ("MACE-3");
13559       caps = gst_caps_new_simple ("audio/x-mace",
13560           "maceversion", G_TYPE_INT, 3, NULL);
13561       break;
13562     case FOURCC_MAC6:
13563       _codec ("MACE-6");
13564       caps = gst_caps_new_simple ("audio/x-mace",
13565           "maceversion", G_TYPE_INT, 6, NULL);
13566       break;
13567     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13568       /* ogg/vorbis */
13569       caps = gst_caps_new_empty_simple ("application/ogg");
13570       break;
13571     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13572       _codec ("DV audio");
13573       caps = gst_caps_new_empty_simple ("audio/x-dv");
13574       break;
13575     case FOURCC_mp4a:
13576       _codec ("MPEG-4 AAC audio");
13577       caps = gst_caps_new_simple ("audio/mpeg",
13578           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13579           "stream-format", G_TYPE_STRING, "raw", NULL);
13580       break;
13581     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13582       _codec ("QDesign Music");
13583       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13584       break;
13585     case FOURCC_QDM2:
13586       _codec ("QDesign Music v.2");
13587       /* FIXME: QDesign music version 2 (no constant) */
13588       if (FALSE && data) {
13589         caps = gst_caps_new_simple ("audio/x-qdm2",
13590             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13591             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13592             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13593       } else {
13594         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13595       }
13596       break;
13597     case FOURCC_agsm:
13598       _codec ("GSM audio");
13599       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13600       break;
13601     case FOURCC_samr:
13602       _codec ("AMR audio");
13603       caps = gst_caps_new_empty_simple ("audio/AMR");
13604       break;
13605     case FOURCC_sawb:
13606       _codec ("AMR-WB audio");
13607       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13608       break;
13609     case FOURCC_ima4:
13610       _codec ("Quicktime IMA ADPCM");
13611       caps = gst_caps_new_simple ("audio/x-adpcm",
13612           "layout", G_TYPE_STRING, "quicktime", NULL);
13613       break;
13614     case FOURCC_alac:
13615       _codec ("Apple lossless audio");
13616       caps = gst_caps_new_empty_simple ("audio/x-alac");
13617       break;
13618     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13619       _codec ("QualComm PureVoice");
13620       caps = gst_caps_from_string ("audio/qcelp");
13621       break;
13622     case FOURCC_wma_:
13623     case FOURCC_owma:
13624       _codec ("WMA");
13625       caps = gst_caps_new_empty_simple ("audio/x-wma");
13626       break;
13627     case FOURCC_opus:
13628       _codec ("Opus");
13629       caps = gst_caps_new_empty_simple ("audio/x-opus");
13630       break;
13631     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13632     {
13633       guint32 flags = 0;
13634       guint32 depth = 0;
13635       guint32 width = 0;
13636       GstAudioFormat format;
13637       enum
13638       {
13639         FLAG_IS_FLOAT = 0x1,
13640         FLAG_IS_BIG_ENDIAN = 0x2,
13641         FLAG_IS_SIGNED = 0x4,
13642         FLAG_IS_PACKED = 0x8,
13643         FLAG_IS_ALIGNED_HIGH = 0x10,
13644         FLAG_IS_NON_INTERLEAVED = 0x20
13645       };
13646       _codec ("Raw LPCM audio");
13647
13648       if (data && len >= 56) {
13649         depth = QT_UINT32 (data + 40);
13650         flags = QT_UINT32 (data + 44);
13651         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13652       }
13653       if ((flags & FLAG_IS_FLOAT) == 0) {
13654         if (depth == 0)
13655           depth = 16;
13656         if (width == 0)
13657           width = 16;
13658         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13659             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13660             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13661         caps = gst_caps_new_simple ("audio/x-raw",
13662             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13663             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13664             "non-interleaved" : "interleaved", NULL);
13665       } else {
13666         if (width == 0)
13667           width = 32;
13668         if (width == 64) {
13669           if (flags & FLAG_IS_BIG_ENDIAN)
13670             format = GST_AUDIO_FORMAT_F64BE;
13671           else
13672             format = GST_AUDIO_FORMAT_F64LE;
13673         } else {
13674           if (flags & FLAG_IS_BIG_ENDIAN)
13675             format = GST_AUDIO_FORMAT_F32BE;
13676           else
13677             format = GST_AUDIO_FORMAT_F32LE;
13678         }
13679         caps = gst_caps_new_simple ("audio/x-raw",
13680             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13681             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13682             "non-interleaved" : "interleaved", NULL);
13683       }
13684       break;
13685     }
13686     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
13687       /* ? */
13688     default:
13689     {
13690       char *s, fourstr[5];
13691
13692       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13693       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
13694       caps = gst_caps_new_empty_simple (s);
13695       g_free (s);
13696       break;
13697     }
13698   }
13699
13700   if (caps) {
13701     GstCaps *templ_caps =
13702         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
13703     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
13704     gst_caps_unref (caps);
13705     gst_caps_unref (templ_caps);
13706     caps = intersection;
13707   }
13708
13709   /* enable clipping for raw audio streams */
13710   s = gst_caps_get_structure (caps, 0);
13711   name = gst_structure_get_name (s);
13712   if (g_str_has_prefix (name, "audio/x-raw")) {
13713     stream->need_clip = TRUE;
13714     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
13715     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
13716   }
13717   return caps;
13718 }
13719
13720 static GstCaps *
13721 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13722     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13723 {
13724   GstCaps *caps;
13725
13726   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13727
13728   switch (fourcc) {
13729     case FOURCC_mp4s:
13730       _codec ("DVD subtitle");
13731       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
13732       stream->need_process = TRUE;
13733       break;
13734     case FOURCC_text:
13735       _codec ("Quicktime timed text");
13736       goto text;
13737     case FOURCC_tx3g:
13738       _codec ("3GPP timed text");
13739     text:
13740       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
13741           "utf8", NULL);
13742       /* actual text piece needs to be extracted */
13743       stream->need_process = TRUE;
13744       break;
13745     case FOURCC_stpp:
13746       _codec ("XML subtitles");
13747       caps = gst_caps_new_empty_simple ("application/ttml+xml");
13748       break;
13749     default:
13750     {
13751       char *s, fourstr[5];
13752
13753       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13754       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
13755       caps = gst_caps_new_empty_simple (s);
13756       g_free (s);
13757       break;
13758     }
13759   }
13760   return caps;
13761 }
13762
13763 static GstCaps *
13764 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13765     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13766 {
13767   GstCaps *caps;
13768
13769   switch (fourcc) {
13770     case FOURCC_m1v:
13771       _codec ("MPEG 1 video");
13772       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13773           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13774       break;
13775     default:
13776       caps = NULL;
13777       break;
13778   }
13779   return caps;
13780 }
13781
13782 static void
13783 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
13784     const gchar * system_id)
13785 {
13786   gint i;
13787
13788   if (!qtdemux->protection_system_ids)
13789     qtdemux->protection_system_ids =
13790         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13791   /* Check whether we already have an entry for this system ID. */
13792   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13793     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13794     if (g_ascii_strcasecmp (system_id, id) == 0) {
13795       return;
13796     }
13797   }
13798   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13799   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13800           -1));
13801 }