qtdemux: expose streams with first moof for fragmented format
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public
24  * License along with this library; if not, write to the
25  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 /**
30  * SECTION:element-qtdemux
31  *
32  * Demuxes a .mov file into raw or compressed audio and/or video streams.
33  *
34  * This element supports both push and pull-based scheduling, depending on the
35  * capabilities of the upstream elements.
36  *
37  * <refsect2>
38  * <title>Example launch line</title>
39  * |[
40  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
41  * ]| Play (parse and decode) a .mov file and try to output it to
42  * an automatically detected soundcard and videosink. If the MOV file contains
43  * compressed audio or video data, this will only work if you have the
44  * right decoder elements/plugins installed.
45  * </refsect2>
46  */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #include "gst/gst-i18n-plugin.h"
53
54 #include <glib/gprintf.h>
55 #include <gst/tag/tag.h>
56 #include <gst/audio/audio.h>
57 #include <gst/video/video.h>
58
59 #include "qtatomparser.h"
60 #include "qtdemux_types.h"
61 #include "qtdemux_dump.h"
62 #include "fourcc.h"
63 #include "descriptors.h"
64 #include "qtdemux_lang.h"
65 #include "qtdemux.h"
66 #include "qtpalette.h"
67
68 #include "gst/riff/riff-media.h"
69 #include "gst/riff/riff-read.h"
70
71 #include <gst/pbutils/pbutils.h>
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include <math.h>
78 #include <gst/math-compat.h>
79
80 #ifdef HAVE_ZLIB
81 # include <zlib.h>
82 #endif
83
84 /* max. size considered 'sane' for non-mdat atoms */
85 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
86
87 /* if the sample index is larger than this, something is likely wrong */
88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
89
90 /* For converting qt creation times to unix epoch times */
91 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
92 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
93 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
94     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
95
96 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
97
98 GST_DEBUG_CATEGORY (qtdemux_debug);
99
100 /*typedef struct _QtNode QtNode; */
101 typedef struct _QtDemuxSegment QtDemuxSegment;
102 typedef struct _QtDemuxSample QtDemuxSample;
103
104 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
105
106 /*struct _QtNode
107 {
108   guint32 type;
109   guint8 *data;
110   gint len;
111 };*/
112
113 struct _QtDemuxSample
114 {
115   guint32 size;
116   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
117   guint64 offset;
118   guint64 timestamp;            /* DTS In mov time */
119   guint32 duration;             /* In mov time */
120   gboolean keyframe;            /* TRUE when this packet is a keyframe */
121 };
122
123 /* Macros for converting to/from timescale */
124 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
125 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
126
127 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
128 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
129
130 /* timestamp is the DTS */
131 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
132 /* timestamp + offset is the PTS */
133 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
134 /* timestamp + duration - dts is the duration */
135 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
136
137 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
138
139 /*
140  * Quicktime has tracks and segments. A track is a continuous piece of
141  * multimedia content. The track is not always played from start to finish but
142  * instead, pieces of the track are 'cut out' and played in sequence. This is
143  * what the segments do.
144  *
145  * Inside the track we have keyframes (K) and delta frames. The track has its
146  * own timing, which starts from 0 and extends to end. The position in the track
147  * is called the media_time.
148  *
149  * The segments now describe the pieces that should be played from this track
150  * and are basically tuples of media_time/duration/rate entries. We can have
151  * multiple segments and they are all played after one another. An example:
152  *
153  * segment 1: media_time: 1 second, duration: 1 second, rate 1
154  * segment 2: media_time: 3 second, duration: 2 second, rate 2
155  *
156  * To correctly play back this track, one must play: 1 second of media starting
157  * from media_time 1 followed by 2 seconds of media starting from media_time 3
158  * at a rate of 2.
159  *
160  * Each of the segments will be played at a specific time, the first segment at
161  * time 0, the second one after the duration of the first one, etc.. Note that
162  * the time in resulting playback is not identical to the media_time of the
163  * track anymore.
164  *
165  * Visually, assuming the track has 4 second of media_time:
166  *
167  *                (a)                   (b)          (c)              (d)
168  *         .-----------------------------------------------------------.
169  * track:  | K.....K.........K........K.......K.......K...........K... |
170  *         '-----------------------------------------------------------'
171  *         0              1              2              3              4
172  *           .------------^              ^   .----------^              ^
173  *          /              .-------------'  /       .------------------'
174  *         /              /          .-----'       /
175  *         .--------------.         .--------------.
176  *         | segment 1    |         | segment 2    |
177  *         '--------------'         '--------------'
178  *
179  * The challenge here is to cut out the right pieces of the track for each of
180  * the playback segments. This fortunately can easily be done with the SEGMENT
181  * events of GStreamer.
182  *
183  * For playback of segment 1, we need to provide the decoder with the keyframe
184  * (a), in the above figure, but we must instruct it only to output the decoded
185  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
186  * position set to the time of the segment: 0.
187  *
188  * We then proceed to push data from keyframe (a) to frame (b). The decoder
189  * decodes but clips all before media_time 1.
190  *
191  * After finishing a segment, we push out a new SEGMENT event with the clipping
192  * boundaries of the new data.
193  *
194  * This is a good usecase for the GStreamer accumulated SEGMENT events.
195  */
196
197 struct _QtDemuxSegment
198 {
199   /* global time and duration, all gst time */
200   GstClockTime time;
201   GstClockTime stop_time;
202   GstClockTime duration;
203   /* media time of trak, all gst time */
204   GstClockTime media_start;
205   GstClockTime media_stop;
206   gdouble rate;
207   /* Media start time in trak timescale units */
208   guint32 trak_media_start;
209 };
210
211 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
212
213 /* Used with fragmented MP4 files (mfra atom) */
214 typedef struct
215 {
216   GstClockTime ts;
217   guint64 moof_offset;
218 } QtDemuxRandomAccessEntry;
219
220 struct _QtDemuxStream
221 {
222   GstPad *pad;
223
224   /* stream type */
225   guint32 subtype;
226   GstCaps *caps;
227   guint32 fourcc;
228   gboolean sparse;
229
230   gboolean new_caps;
231   gboolean new_stream;          /* signals that a stream_start is required */
232   gboolean on_keyframe;         /* if this stream last pushed buffer was a
233                                  * keyframe. This is important to identify
234                                  * where to stop pushing buffers after a
235                                  * segment stop time */
236
237   /* if the stream has a redirect URI in its headers, we store it here */
238   gchar *redirect_uri;
239
240   /* track id */
241   guint track_id;
242
243   /* duration/scale */
244   guint64 duration;             /* in timescale */
245   guint32 timescale;
246
247   /* language */
248   gchar lang_id[4];             /* ISO 639-2T language code */
249
250   /* our samples */
251   guint32 n_samples;
252   QtDemuxSample *samples;
253   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
254   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
255                                    the framerate, in timescale units */
256   guint32 offset_in_sample;
257   guint32 max_buffer_size;
258
259   /* if we use chunks or samples */
260   gboolean sampled;
261   guint padding;
262
263   /* video info */
264   gint width;
265   gint height;
266   /* aspect ratio */
267   gint display_width;
268   gint display_height;
269   gint par_w;
270   gint par_h;
271   /* Numerator/denominator framerate */
272   gint fps_n;
273   gint fps_d;
274   guint16 bits_per_sample;
275   guint16 color_table_id;
276   GstMemory *rgb8_palette;
277
278   /* audio info */
279   gdouble rate;
280   gint n_channels;
281   guint samples_per_packet;
282   guint samples_per_frame;
283   guint bytes_per_packet;
284   guint bytes_per_sample;
285   guint bytes_per_frame;
286   guint compression;
287
288   /* allocation */
289   gboolean use_allocator;
290   GstAllocator *allocator;
291   GstAllocationParams params;
292
293   /* when a discontinuity is pending */
294   gboolean discont;
295
296   /* list of buffers to push first */
297   GSList *buffers;
298
299   /* if we need to clip this buffer. This is only needed for uncompressed
300    * data */
301   gboolean need_clip;
302
303   /* buffer needs some custom processing, e.g. subtitles */
304   gboolean need_process;
305
306   /* current position */
307   guint32 segment_index;
308   guint32 sample_index;
309   GstClockTime time_position;   /* in gst time */
310   guint64 accumulated_base;
311
312   /* the Gst segment we are processing out, used for clipping */
313   GstSegment segment;
314   guint32 segment_seqnum;       /* segment event seqnum obtained from seek */
315
316   /* quicktime segments */
317   guint32 n_segments;
318   QtDemuxSegment *segments;
319   gboolean dummy_segment;
320   guint32 from_sample;
321   guint32 to_sample;
322
323   gboolean sent_eos;
324   GstTagList *pending_tags;
325   gboolean send_global_tags;
326
327   GstEvent *pending_event;
328
329   GstByteReader stco;
330   GstByteReader stsz;
331   GstByteReader stsc;
332   GstByteReader stts;
333   GstByteReader stss;
334   GstByteReader stps;
335   GstByteReader ctts;
336
337   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
338   gint64 stbl_index;
339   /* stco */
340   guint co_size;
341   GstByteReader co_chunk;
342   guint32 first_chunk;
343   guint32 current_chunk;
344   guint32 last_chunk;
345   guint32 samples_per_chunk;
346   guint32 stco_sample_index;
347   /* stsz */
348   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
349   /* stsc */
350   guint32 stsc_index;
351   guint32 n_samples_per_chunk;
352   guint32 stsc_chunk_index;
353   guint32 stsc_sample_index;
354   guint64 chunk_offset;
355   /* stts */
356   guint32 stts_index;
357   guint32 stts_samples;
358   guint32 n_sample_times;
359   guint32 stts_sample_index;
360   guint64 stts_time;
361   guint32 stts_duration;
362   /* stss */
363   gboolean stss_present;
364   guint32 n_sample_syncs;
365   guint32 stss_index;
366   /* stps */
367   gboolean stps_present;
368   guint32 n_sample_partial_syncs;
369   guint32 stps_index;
370   QtDemuxRandomAccessEntry *ra_entries;
371   guint n_ra_entries;
372
373   const QtDemuxRandomAccessEntry *pending_seek;
374
375   /* ctts */
376   gboolean ctts_present;
377   guint32 n_composition_times;
378   guint32 ctts_index;
379   guint32 ctts_sample_index;
380   guint32 ctts_count;
381   gint32 ctts_soffset;
382
383   /* cslg */
384   guint32 cslg_shift;
385
386   /* fragmented */
387   gboolean parsed_trex;
388   guint32 def_sample_duration;
389   guint32 def_sample_size;
390   guint32 def_sample_flags;
391
392   gboolean disabled;
393
394   /* stereoscopic video streams */
395   GstVideoMultiviewMode multiview_mode;
396   GstVideoMultiviewFlags multiview_flags;
397
398   /* protected streams */
399   gboolean protected;
400   guint32 protection_scheme_type;
401   guint32 protection_scheme_version;
402   gpointer protection_scheme_info;      /* specific to the protection scheme */
403   GQueue protection_scheme_event_queue;
404 };
405
406 /* Contains properties and cryptographic info for a set of samples from a
407  * track protected using Common Encryption (cenc) */
408 struct _QtDemuxCencSampleSetInfo
409 {
410   GstStructure *default_properties;
411
412   /* @crypto_info holds one GstStructure per sample */
413   GPtrArray *crypto_info;
414 };
415
416 enum QtDemuxState
417 {
418   QTDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
419   QTDEMUX_STATE_HEADER,         /* Parsing the header */
420   QTDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
421   QTDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
422 };
423
424 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
425 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
426     guint32 fourcc, GstByteReader * parser);
427 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
428 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
429     guint32 fourcc, GstByteReader * parser);
430
431 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
432
433 static GstStaticPadTemplate gst_qtdemux_sink_template =
434     GST_STATIC_PAD_TEMPLATE ("sink",
435     GST_PAD_SINK,
436     GST_PAD_ALWAYS,
437     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
438         "application/x-3gp")
439     );
440
441 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
442 GST_STATIC_PAD_TEMPLATE ("video_%u",
443     GST_PAD_SRC,
444     GST_PAD_SOMETIMES,
445     GST_STATIC_CAPS_ANY);
446
447 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
448 GST_STATIC_PAD_TEMPLATE ("audio_%u",
449     GST_PAD_SRC,
450     GST_PAD_SOMETIMES,
451     GST_STATIC_CAPS_ANY);
452
453 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
454 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
455     GST_PAD_SRC,
456     GST_PAD_SOMETIMES,
457     GST_STATIC_CAPS_ANY);
458
459 #define gst_qtdemux_parent_class parent_class
460 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
461
462 static void gst_qtdemux_dispose (GObject * object);
463
464 static guint32
465 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
466     GstClockTime media_time);
467 static guint32
468 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
469     QtDemuxStream * str, gint64 media_offset);
470
471 #if 0
472 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
473 static GstIndex *gst_qtdemux_get_index (GstElement * element);
474 #endif
475 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
476     GstStateChange transition);
477 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
478 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
479     GstObject * parent, GstPadMode mode, gboolean active);
480
481 static void gst_qtdemux_loop (GstPad * pad);
482 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
483     GstBuffer * inbuf);
484 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
485     GstEvent * event);
486 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
487 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
488     QtDemuxStream * stream);
489 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
490     gboolean force);
491
492 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
493     const guint8 * buffer, guint length);
494 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
495     const guint8 * buffer, guint length);
496 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
497 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
498     GNode * udta);
499
500 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
501     QtDemuxStream * stream, GNode * esds, GstTagList * list);
502 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
503     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
504     gchar ** codec_name);
505 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
506     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
507     gchar ** codec_name);
508 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
509     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
510     gchar ** codec_name);
511 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
512     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
513     gchar ** codec_name);
514
515 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
516     QtDemuxStream * stream, guint32 n);
517 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
518 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
519     QtDemuxStream * stream);
520 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
521     QtDemuxStream * stream);
522 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
523 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
524 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
525     QtDemuxStream * stream);
526
527 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
528 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
529
530 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
531     const gchar * id);
532
533 static void
534 gst_qtdemux_class_init (GstQTDemuxClass * klass)
535 {
536   GObjectClass *gobject_class;
537   GstElementClass *gstelement_class;
538
539   gobject_class = (GObjectClass *) klass;
540   gstelement_class = (GstElementClass *) klass;
541
542   parent_class = g_type_class_peek_parent (klass);
543
544   gobject_class->dispose = gst_qtdemux_dispose;
545
546   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
547 #if 0
548   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
549   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
550 #endif
551
552   gst_tag_register_musicbrainz_tags ();
553
554   gst_element_class_add_pad_template (gstelement_class,
555       gst_static_pad_template_get (&gst_qtdemux_sink_template));
556   gst_element_class_add_pad_template (gstelement_class,
557       gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
558   gst_element_class_add_pad_template (gstelement_class,
559       gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
560   gst_element_class_add_pad_template (gstelement_class,
561       gst_static_pad_template_get (&gst_qtdemux_subsrc_template));
562   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
563       "Codec/Demuxer",
564       "Demultiplex a QuickTime file into audio and video streams",
565       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
566
567   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
568
569 }
570
571 static void
572 gst_qtdemux_init (GstQTDemux * qtdemux)
573 {
574   qtdemux->sinkpad =
575       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
576   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
577   gst_pad_set_activatemode_function (qtdemux->sinkpad,
578       qtdemux_sink_activate_mode);
579   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
580   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
581   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
582
583   qtdemux->state = QTDEMUX_STATE_INITIAL;
584   qtdemux->pullbased = FALSE;
585   qtdemux->posted_redirect = FALSE;
586   qtdemux->pending_configure = FALSE;
587   qtdemux->neededbytes = 16;
588   qtdemux->todrop = 0;
589   qtdemux->adapter = gst_adapter_new ();
590   qtdemux->offset = 0;
591   qtdemux->first_mdat = -1;
592   qtdemux->got_moov = FALSE;
593   qtdemux->mdatoffset = -1;
594   qtdemux->mdatbuffer = NULL;
595   qtdemux->restoredata_buffer = NULL;
596   qtdemux->restoredata_offset = -1;
597   qtdemux->fragment_start = -1;
598   qtdemux->fragment_start_offset = -1;
599   qtdemux->media_caps = NULL;
600   qtdemux->exposed = FALSE;
601   qtdemux->mss_mode = FALSE;
602   qtdemux->pending_newsegment = NULL;
603   qtdemux->upstream_format_is_time = FALSE;
604   qtdemux->have_group_id = FALSE;
605   qtdemux->group_id = G_MAXUINT;
606   qtdemux->cenc_aux_info_offset = 0;
607   qtdemux->cenc_aux_info_sizes = NULL;
608   qtdemux->cenc_aux_sample_count = 0;
609   qtdemux->protection_system_ids = NULL;
610   g_queue_init (&qtdemux->protection_event_queue);
611   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
612   qtdemux->flowcombiner = gst_flow_combiner_new ();
613
614   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
615 }
616
617 static void
618 gst_qtdemux_dispose (GObject * object)
619 {
620   GstQTDemux *qtdemux = GST_QTDEMUX (object);
621
622   if (qtdemux->adapter) {
623     g_object_unref (G_OBJECT (qtdemux->adapter));
624     qtdemux->adapter = NULL;
625   }
626   gst_flow_combiner_free (qtdemux->flowcombiner);
627   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
628       NULL);
629   g_queue_clear (&qtdemux->protection_event_queue);
630
631   g_free (qtdemux->cenc_aux_info_sizes);
632   qtdemux->cenc_aux_info_sizes = NULL;
633
634   G_OBJECT_CLASS (parent_class)->dispose (object);
635 }
636
637 static void
638 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
639 {
640   if (qtdemux->posted_redirect) {
641     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
642         (_("This file contains no playable streams.")),
643         ("no known streams found, a redirect message has been posted"));
644   } else {
645     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
646         (_("This file contains no playable streams.")),
647         ("no known streams found"));
648   }
649 }
650
651 static GstBuffer *
652 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
653 {
654   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
655       mem, size, 0, size, mem, free_func);
656 }
657
658 static GstFlowReturn
659 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
660     GstBuffer ** buf)
661 {
662   GstFlowReturn flow;
663   GstMapInfo map;
664   gsize bsize;
665
666   if (G_UNLIKELY (size == 0)) {
667     GstFlowReturn ret;
668     GstBuffer *tmp = NULL;
669
670     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
671     if (ret != GST_FLOW_OK)
672       return ret;
673
674     gst_buffer_map (tmp, &map, GST_MAP_READ);
675     size = QT_UINT32 (map.data);
676     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
677
678     gst_buffer_unmap (tmp, &map);
679     gst_buffer_unref (tmp);
680   }
681
682   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
683   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
684     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
685       /* we're pulling header but already got most interesting bits,
686        * so never mind the rest (e.g. tags) (that much) */
687       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
688           size);
689       return GST_FLOW_EOS;
690     } else {
691       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
692           (_("This file is invalid and cannot be played.")),
693           ("atom has bogus size %" G_GUINT64_FORMAT, size));
694       return GST_FLOW_ERROR;
695     }
696   }
697
698   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
699
700   if (G_UNLIKELY (flow != GST_FLOW_OK))
701     return flow;
702
703   bsize = gst_buffer_get_size (*buf);
704   /* Catch short reads - we don't want any partial atoms */
705   if (G_UNLIKELY (bsize < size)) {
706     GST_WARNING_OBJECT (qtdemux,
707         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
708     gst_buffer_unref (*buf);
709     *buf = NULL;
710     return GST_FLOW_EOS;
711   }
712
713   return flow;
714 }
715
716 #if 1
717 static gboolean
718 gst_qtdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
719     GstFormat dest_format, gint64 * dest_value)
720 {
721   gboolean res = TRUE;
722   QtDemuxStream *stream = gst_pad_get_element_private (pad);
723   GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
724   gint32 index;
725
726   if (stream->subtype != FOURCC_vide) {
727     res = FALSE;
728     goto done;
729   }
730
731   switch (src_format) {
732     case GST_FORMAT_TIME:
733       switch (dest_format) {
734         case GST_FORMAT_BYTES:{
735           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
736           if (-1 == index)
737             return FALSE;
738
739           *dest_value = stream->samples[index].offset;
740
741           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
742               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
743               GST_TIME_ARGS (src_value), *dest_value);
744           break;
745         }
746         default:
747           res = FALSE;
748           break;
749       }
750       break;
751     case GST_FORMAT_BYTES:
752       switch (dest_format) {
753         case GST_FORMAT_TIME:{
754           index =
755               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
756               stream, src_value);
757
758           if (-1 == index)
759             return FALSE;
760
761           *dest_value =
762               QTSTREAMTIME_TO_GSTTIME (stream,
763               stream->samples[index].timestamp);
764           GST_DEBUG_OBJECT (qtdemux,
765               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
766               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
767           break;
768         }
769         default:
770           res = FALSE;
771           break;
772       }
773       break;
774     default:
775       res = FALSE;
776   }
777
778 done:
779   gst_object_unref (qtdemux);
780
781   return res;
782 }
783 #endif
784
785 static gboolean
786 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
787 {
788   gboolean res = TRUE;
789
790   *duration = GST_CLOCK_TIME_NONE;
791
792   if (qtdemux->duration != 0) {
793     if (qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
794       *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
795     }
796   }
797   return res;
798 }
799
800 static gboolean
801 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
802     GstQuery * query)
803 {
804   gboolean res = FALSE;
805   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
806
807   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
808
809   switch (GST_QUERY_TYPE (query)) {
810     case GST_QUERY_POSITION:{
811       GstFormat fmt;
812
813       gst_query_parse_position (query, &fmt, NULL);
814       if (fmt == GST_FORMAT_TIME
815           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
816         gst_query_set_position (query, GST_FORMAT_TIME,
817             qtdemux->segment.position);
818         res = TRUE;
819       }
820     }
821       break;
822     case GST_QUERY_DURATION:{
823       GstFormat fmt;
824
825       gst_query_parse_duration (query, &fmt, NULL);
826       if (fmt == GST_FORMAT_TIME) {
827         /* First try to query upstream */
828         res = gst_pad_query_default (pad, parent, query);
829         if (!res) {
830           guint64 duration;
831           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
832             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
833             res = TRUE;
834           }
835         }
836       }
837       break;
838     }
839     case GST_QUERY_CONVERT:{
840       GstFormat src_fmt, dest_fmt;
841       gint64 src_value, dest_value = 0;
842
843       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
844
845       res = gst_qtdemux_src_convert (pad,
846           src_fmt, src_value, dest_fmt, &dest_value);
847       if (res) {
848         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
849         res = TRUE;
850       }
851       break;
852     }
853     case GST_QUERY_FORMATS:
854       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
855       res = TRUE;
856       break;
857     case GST_QUERY_SEEKING:{
858       GstFormat fmt;
859       gboolean seekable;
860
861       /* try upstream first */
862       res = gst_pad_query_default (pad, parent, query);
863
864       if (!res) {
865         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
866         if (fmt == GST_FORMAT_TIME) {
867           GstClockTime duration = GST_CLOCK_TIME_NONE;
868
869           gst_qtdemux_get_duration (qtdemux, &duration);
870           seekable = TRUE;
871           if (!qtdemux->pullbased) {
872             GstQuery *q;
873
874             /* we might be able with help from upstream */
875             seekable = FALSE;
876             q = gst_query_new_seeking (GST_FORMAT_BYTES);
877             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
878               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
879               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
880             }
881             gst_query_unref (q);
882           }
883           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
884           res = TRUE;
885         }
886       }
887       break;
888     }
889     case GST_QUERY_SEGMENT:
890     {
891       GstFormat format;
892       gint64 start, stop;
893
894       format = qtdemux->segment.format;
895
896       start =
897           gst_segment_to_stream_time (&qtdemux->segment, format,
898           qtdemux->segment.start);
899       if ((stop = qtdemux->segment.stop) == -1)
900         stop = qtdemux->segment.duration;
901       else
902         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
903
904       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
905       res = TRUE;
906       break;
907     }
908     default:
909       res = gst_pad_query_default (pad, parent, query);
910       break;
911   }
912
913   return res;
914 }
915
916 static void
917 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
918 {
919   if (G_LIKELY (stream->pad)) {
920     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
921         GST_DEBUG_PAD_NAME (stream->pad));
922
923     if (G_UNLIKELY (stream->pending_tags)) {
924       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
925           stream->pending_tags);
926       gst_pad_push_event (stream->pad,
927           gst_event_new_tag (stream->pending_tags));
928       stream->pending_tags = NULL;
929     }
930
931     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
932       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
933           qtdemux->tag_list);
934       gst_pad_push_event (stream->pad,
935           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
936       stream->send_global_tags = FALSE;
937     }
938   }
939 }
940
941 /* push event on all source pads; takes ownership of the event */
942 static void
943 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
944 {
945   guint n;
946   gboolean has_valid_stream = FALSE;
947   GstEventType etype = GST_EVENT_TYPE (event);
948
949   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
950       GST_EVENT_TYPE_NAME (event));
951
952   for (n = 0; n < qtdemux->n_streams; n++) {
953     GstPad *pad;
954     QtDemuxStream *stream = qtdemux->streams[n];
955     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
956
957     if ((pad = stream->pad)) {
958       has_valid_stream = TRUE;
959
960       if (etype == GST_EVENT_EOS) {
961         /* let's not send twice */
962         if (stream->sent_eos)
963           continue;
964         stream->sent_eos = TRUE;
965       }
966
967       gst_pad_push_event (pad, gst_event_ref (event));
968     }
969   }
970
971   gst_event_unref (event);
972
973   /* if it is EOS and there are no pads, post an error */
974   if (!has_valid_stream && etype == GST_EVENT_EOS) {
975     gst_qtdemux_post_no_playable_stream_error (qtdemux);
976   }
977 }
978
979 /* push a pending newsegment event, if any from the streaming thread */
980 static void
981 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
982 {
983   if (qtdemux->pending_newsegment) {
984     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
985     qtdemux->pending_newsegment = NULL;
986   }
987 }
988
989 typedef struct
990 {
991   guint64 media_time;
992 } FindData;
993
994 static gint
995 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
996 {
997   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
998     return 1;
999   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1000     return 0;
1001
1002   return -1;
1003 }
1004
1005 /* find the index of the sample that includes the data for @media_time using a
1006  * binary search.  Only to be called in optimized cases of linear search below.
1007  *
1008  * Returns the index of the sample.
1009  */
1010 static guint32
1011 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1012     guint64 media_time)
1013 {
1014   QtDemuxSample *result;
1015   guint32 index;
1016
1017   /* convert media_time to mov format */
1018   media_time =
1019       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1020
1021   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1022       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1023       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1024
1025   if (G_LIKELY (result))
1026     index = result - str->samples;
1027   else
1028     index = 0;
1029
1030   return index;
1031 }
1032
1033
1034
1035 /* find the index of the sample that includes the data for @media_offset using a
1036  * linear search
1037  *
1038  * Returns the index of the sample.
1039  */
1040 static guint32
1041 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1042     QtDemuxStream * str, gint64 media_offset)
1043 {
1044   QtDemuxSample *result = str->samples;
1045   guint32 index = 0;
1046
1047   if (result == NULL || str->n_samples == 0)
1048     return -1;
1049
1050   if (media_offset == result->offset)
1051     return index;
1052
1053   result++;
1054   while (index < str->n_samples - 1) {
1055     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1056       goto parse_failed;
1057
1058     if (media_offset < result->offset)
1059       break;
1060
1061     index++;
1062     result++;
1063   }
1064   return index;
1065
1066   /* ERRORS */
1067 parse_failed:
1068   {
1069     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1070     return -1;
1071   }
1072 }
1073
1074 /* find the index of the sample that includes the data for @media_time using a
1075  * linear search, and keeping in mind that not all samples may have been parsed
1076  * yet.  If possible, it will delegate to binary search.
1077  *
1078  * Returns the index of the sample.
1079  */
1080 static guint32
1081 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1082     GstClockTime media_time)
1083 {
1084   guint32 index = 0;
1085   guint64 mov_time;
1086   QtDemuxSample *sample;
1087
1088   /* convert media_time to mov format */
1089   mov_time =
1090       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1091
1092   sample = str->samples;
1093   if (mov_time == sample->timestamp + sample->pts_offset)
1094     return index;
1095
1096   /* use faster search if requested time in already parsed range */
1097   sample = str->samples + str->stbl_index;
1098   if (str->stbl_index >= 0 &&
1099       mov_time <= (sample->timestamp + sample->pts_offset))
1100     return gst_qtdemux_find_index (qtdemux, str, media_time);
1101
1102   while (index < str->n_samples - 1) {
1103     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1104       goto parse_failed;
1105
1106     sample = str->samples + index + 1;
1107     if (mov_time < (sample->timestamp + sample->pts_offset))
1108       break;
1109
1110     index++;
1111   }
1112   return index;
1113
1114   /* ERRORS */
1115 parse_failed:
1116   {
1117     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1118     return -1;
1119   }
1120 }
1121
1122 /* find the index of the keyframe needed to decode the sample at @index
1123  * of stream @str.
1124  *
1125  * Returns the index of the keyframe.
1126  */
1127 static guint32
1128 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1129     guint32 index)
1130 {
1131   guint32 new_index = index;
1132
1133   if (index >= str->n_samples) {
1134     new_index = str->n_samples;
1135     goto beach;
1136   }
1137
1138   /* all keyframes, return index */
1139   if (str->all_keyframe) {
1140     new_index = index;
1141     goto beach;
1142   }
1143
1144   /* else go back until we have a keyframe */
1145   while (TRUE) {
1146     if (str->samples[new_index].keyframe)
1147       break;
1148
1149     if (new_index == 0)
1150       break;
1151
1152     new_index--;
1153   }
1154
1155 beach:
1156   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1157       "gave %u", index, new_index);
1158
1159   return new_index;
1160 }
1161
1162 /* find the segment for @time_position for @stream
1163  *
1164  * Returns the index of the segment containing @time_position.
1165  * Returns the last segment and sets the @eos variable to TRUE
1166  * if the time is beyond the end. @eos may be NULL
1167  */
1168 static guint32
1169 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1170     GstClockTime time_position)
1171 {
1172   gint i;
1173   guint32 seg_idx;
1174
1175   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1176       GST_TIME_ARGS (time_position));
1177
1178   seg_idx = -1;
1179   for (i = 0; i < stream->n_segments; i++) {
1180     QtDemuxSegment *segment = &stream->segments[i];
1181
1182     GST_LOG_OBJECT (stream->pad,
1183         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1184         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1185
1186     /* For the last segment we include stop_time in the last segment */
1187     if (i < stream->n_segments - 1) {
1188       if (segment->time <= time_position && time_position < segment->stop_time) {
1189         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1190         seg_idx = i;
1191         break;
1192       }
1193     } else {
1194       /* Last segment always matches */
1195       seg_idx = i;
1196       break;
1197     }
1198   }
1199   return seg_idx;
1200 }
1201
1202 /* move the stream @str to the sample position @index.
1203  *
1204  * Updates @str->sample_index and marks discontinuity if needed.
1205  */
1206 static void
1207 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1208     guint32 index)
1209 {
1210   /* no change needed */
1211   if (index == str->sample_index)
1212     return;
1213
1214   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1215       str->n_samples);
1216
1217   /* position changed, we have a discont */
1218   str->sample_index = index;
1219   str->offset_in_sample = 0;
1220   /* Each time we move in the stream we store the position where we are
1221    * starting from */
1222   str->from_sample = index;
1223   str->discont = TRUE;
1224 }
1225
1226 static void
1227 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1228     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1229 {
1230   guint64 min_offset;
1231   gint64 min_byte_offset = -1;
1232   gint n;
1233
1234   min_offset = desired_time;
1235
1236   /* for each stream, find the index of the sample in the segment
1237    * and move back to the previous keyframe. */
1238   for (n = 0; n < qtdemux->n_streams; n++) {
1239     QtDemuxStream *str;
1240     guint32 index, kindex;
1241     guint32 seg_idx;
1242     GstClockTime media_start;
1243     GstClockTime media_time;
1244     GstClockTime seg_time;
1245     QtDemuxSegment *seg;
1246     gboolean empty_segment = FALSE;
1247
1248     str = qtdemux->streams[n];
1249
1250     if (str->sparse && !use_sparse)
1251       continue;
1252
1253     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1254     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1255
1256     /* get segment and time in the segment */
1257     seg = &str->segments[seg_idx];
1258     seg_time = desired_time - seg->time;
1259
1260     while (QTSEGMENT_IS_EMPTY (seg)) {
1261       seg_time = 0;
1262       empty_segment = TRUE;
1263       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1264           seg_idx);
1265       seg_idx++;
1266       if (seg_idx == str->n_segments)
1267         break;
1268       seg = &str->segments[seg_idx];
1269     }
1270
1271     if (seg_idx == str->n_segments) {
1272       /* FIXME track shouldn't have the last segment as empty, but if it
1273        * happens we better handle it */
1274       continue;
1275     }
1276
1277     /* get the media time in the segment */
1278     media_start = seg->media_start + seg_time;
1279
1280     /* get the index of the sample with media time */
1281     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1282     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1283         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1284         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1285         empty_segment);
1286
1287     if (!empty_segment) {
1288       /* find previous keyframe */
1289       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1290
1291       /* if the keyframe is at a different position, we need to update the
1292        * requested seek time */
1293       if (index != kindex) {
1294         index = kindex;
1295
1296         /* get timestamp of keyframe */
1297         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1298         GST_DEBUG_OBJECT (qtdemux,
1299             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1300             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1301             str->samples[kindex].offset);
1302
1303         /* keyframes in the segment get a chance to change the
1304          * desired_offset. keyframes out of the segment are
1305          * ignored. */
1306         if (media_time >= seg->media_start) {
1307           GstClockTime seg_time;
1308
1309           /* this keyframe is inside the segment, convert back to
1310            * segment time */
1311           seg_time = (media_time - seg->media_start) + seg->time;
1312           if (seg_time < min_offset)
1313             min_offset = seg_time;
1314         }
1315       }
1316     }
1317
1318     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1319       min_byte_offset = str->samples[index].offset;
1320   }
1321
1322   if (key_time)
1323     *key_time = min_offset;
1324   if (key_offset)
1325     *key_offset = min_byte_offset;
1326 }
1327
1328 static gboolean
1329 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1330     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1331 {
1332   gboolean res;
1333
1334   g_return_val_if_fail (format != NULL, FALSE);
1335   g_return_val_if_fail (cur != NULL, FALSE);
1336   g_return_val_if_fail (stop != NULL, FALSE);
1337
1338   if (*format == GST_FORMAT_TIME)
1339     return TRUE;
1340
1341   res = TRUE;
1342   if (cur_type != GST_SEEK_TYPE_NONE)
1343     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1344   if (res && stop_type != GST_SEEK_TYPE_NONE)
1345     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1346
1347   if (res)
1348     *format = GST_FORMAT_TIME;
1349
1350   return res;
1351 }
1352
1353 /* perform seek in push based mode:
1354    find BYTE position to move to based on time and delegate to upstream
1355 */
1356 static gboolean
1357 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1358 {
1359   gdouble rate;
1360   GstFormat format;
1361   GstSeekFlags flags;
1362   GstSeekType cur_type, stop_type;
1363   gint64 cur, stop, key_cur;
1364   gboolean res;
1365   gint64 byte_cur;
1366   gint64 original_stop;
1367   guint32 seqnum;
1368
1369   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1370
1371   gst_event_parse_seek (event, &rate, &format, &flags,
1372       &cur_type, &cur, &stop_type, &stop);
1373   seqnum = gst_event_get_seqnum (event);
1374
1375   /* only forward streaming and seeking is possible */
1376   if (rate <= 0)
1377     goto unsupported_seek;
1378
1379   /* convert to TIME if needed and possible */
1380   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1381           stop_type, &stop))
1382     goto no_format;
1383
1384   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1385    * the original stop position to use when upstream pushes the new segment
1386    * for this seek */
1387   original_stop = stop;
1388   stop = -1;
1389
1390   /* find reasonable corresponding BYTE position,
1391    * also try to mind about keyframes, since we can not go back a bit for them
1392    * later on */
1393   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1394
1395   if (byte_cur == -1)
1396     goto abort_seek;
1397
1398   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1399       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1400       stop);
1401
1402   GST_OBJECT_LOCK (qtdemux);
1403   qtdemux->seek_offset = byte_cur;
1404   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1405     qtdemux->push_seek_start = cur;
1406   } else {
1407     qtdemux->push_seek_start = key_cur;
1408   }
1409
1410   if (stop_type == GST_SEEK_TYPE_NONE) {
1411     qtdemux->push_seek_stop = qtdemux->segment.stop;
1412   } else {
1413     qtdemux->push_seek_stop = original_stop;
1414   }
1415   GST_OBJECT_UNLOCK (qtdemux);
1416
1417   /* BYTE seek event */
1418   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1419       stop_type, stop);
1420   gst_event_set_seqnum (event, seqnum);
1421   res = gst_pad_push_event (qtdemux->sinkpad, event);
1422
1423   return res;
1424
1425   /* ERRORS */
1426 abort_seek:
1427   {
1428     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1429         "seek aborted.");
1430     return FALSE;
1431   }
1432 unsupported_seek:
1433   {
1434     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1435     return FALSE;
1436   }
1437 no_format:
1438   {
1439     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1440     return FALSE;
1441   }
1442 }
1443
1444 /* perform the seek.
1445  *
1446  * We set all segment_indexes in the streams to unknown and
1447  * adjust the time_position to the desired position. this is enough
1448  * to trigger a segment switch in the streaming thread to start
1449  * streaming from the desired position.
1450  *
1451  * Keyframe seeking is a little more complicated when dealing with
1452  * segments. Ideally we want to move to the previous keyframe in
1453  * the segment but there might not be a keyframe in the segment. In
1454  * fact, none of the segments could contain a keyframe. We take a
1455  * practical approach: seek to the previous keyframe in the segment,
1456  * if there is none, seek to the beginning of the segment.
1457  *
1458  * Called with STREAM_LOCK
1459  */
1460 static gboolean
1461 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1462     guint32 seqnum, GstSeekFlags flags)
1463 {
1464   gint64 desired_offset;
1465   gint n;
1466
1467   desired_offset = segment->position;
1468
1469   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1470       GST_TIME_ARGS (desired_offset));
1471
1472   /* may not have enough fragmented info to do this adjustment,
1473    * and we can't scan (and probably should not) at this time with
1474    * possibly flushing upstream */
1475   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1476     gint64 min_offset;
1477
1478     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1479     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1480         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1481     desired_offset = min_offset;
1482   }
1483
1484   /* and set all streams to the final position */
1485   gst_flow_combiner_reset (qtdemux->flowcombiner);
1486   for (n = 0; n < qtdemux->n_streams; n++) {
1487     QtDemuxStream *stream = qtdemux->streams[n];
1488
1489     stream->time_position = desired_offset;
1490     stream->accumulated_base = 0;
1491     stream->sample_index = -1;
1492     stream->offset_in_sample = 0;
1493     stream->segment_index = -1;
1494     stream->sent_eos = FALSE;
1495     stream->segment_seqnum = seqnum;
1496
1497     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1498       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1499   }
1500   segment->position = desired_offset;
1501   segment->time = desired_offset;
1502   if (segment->rate >= 0) {
1503     segment->start = desired_offset;
1504
1505     /* we stop at the end */
1506     if (segment->stop == -1)
1507       segment->stop = segment->duration;
1508   } else {
1509     segment->stop = desired_offset;
1510   }
1511
1512   if (qtdemux->fragmented)
1513     qtdemux->fragmented_seek_pending = TRUE;
1514
1515   return TRUE;
1516 }
1517
1518 /* do a seek in pull based mode */
1519 static gboolean
1520 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1521 {
1522   gdouble rate;
1523   GstFormat format;
1524   GstSeekFlags flags;
1525   GstSeekType cur_type, stop_type;
1526   gint64 cur, stop;
1527   gboolean flush;
1528   gboolean update;
1529   GstSegment seeksegment;
1530   guint32 seqnum = 0;
1531   GstEvent *flush_event;
1532
1533   if (event) {
1534     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1535
1536     gst_event_parse_seek (event, &rate, &format, &flags,
1537         &cur_type, &cur, &stop_type, &stop);
1538     seqnum = gst_event_get_seqnum (event);
1539
1540     /* we have to have a format as the segment format. Try to convert
1541      * if not. */
1542     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1543             stop_type, &stop))
1544       goto no_format;
1545
1546     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1547   } else {
1548     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1549     flags = 0;
1550   }
1551
1552   flush = flags & GST_SEEK_FLAG_FLUSH;
1553
1554   /* stop streaming, either by flushing or by pausing the task */
1555   if (flush) {
1556     flush_event = gst_event_new_flush_start ();
1557     if (seqnum)
1558       gst_event_set_seqnum (flush_event, seqnum);
1559     /* unlock upstream pull_range */
1560     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1561     /* make sure out loop function exits */
1562     gst_qtdemux_push_event (qtdemux, flush_event);
1563   } else {
1564     /* non flushing seek, pause the task */
1565     gst_pad_pause_task (qtdemux->sinkpad);
1566   }
1567
1568   /* wait for streaming to finish */
1569   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1570
1571   /* copy segment, we need this because we still need the old
1572    * segment when we close the current segment. */
1573   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1574
1575   if (event) {
1576     /* configure the segment with the seek variables */
1577     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1578     gst_segment_do_seek (&seeksegment, rate, format, flags,
1579         cur_type, cur, stop_type, stop, &update);
1580   }
1581
1582   /* now do the seek, this actually never returns FALSE */
1583   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1584
1585   /* prepare for streaming again */
1586   if (flush) {
1587     flush_event = gst_event_new_flush_stop (TRUE);
1588     if (seqnum)
1589       gst_event_set_seqnum (flush_event, seqnum);
1590
1591     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1592     gst_qtdemux_push_event (qtdemux, flush_event);
1593   }
1594
1595   /* commit the new segment */
1596   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1597
1598   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1599     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1600         qtdemux->segment.format, qtdemux->segment.position);
1601     if (seqnum)
1602       gst_message_set_seqnum (msg, seqnum);
1603     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1604   }
1605
1606   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1607   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1608       qtdemux->sinkpad, NULL);
1609
1610   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1611
1612   return TRUE;
1613
1614   /* ERRORS */
1615 no_format:
1616   {
1617     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1618     return FALSE;
1619   }
1620 }
1621
1622 static gboolean
1623 qtdemux_ensure_index (GstQTDemux * qtdemux)
1624 {
1625   guint i;
1626
1627   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1628
1629   /* Build complete index */
1630   for (i = 0; i < qtdemux->n_streams; i++) {
1631     QtDemuxStream *stream = qtdemux->streams[i];
1632
1633     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1634       goto parse_error;
1635   }
1636   return TRUE;
1637
1638   /* ERRORS */
1639 parse_error:
1640   {
1641     GST_LOG_OBJECT (qtdemux,
1642         "Building complete index of stream %u for seeking failed!", i);
1643     return FALSE;
1644   }
1645 }
1646
1647 static gboolean
1648 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1649     GstEvent * event)
1650 {
1651   gboolean res = TRUE;
1652   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1653
1654   switch (GST_EVENT_TYPE (event)) {
1655     case GST_EVENT_SEEK:
1656     {
1657 #ifndef GST_DISABLE_GST_DEBUG
1658       GstClockTime ts = gst_util_get_timestamp ();
1659 #endif
1660
1661       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1662         /* seek should be handled by upstream, we might need to re-download fragments */
1663         GST_DEBUG_OBJECT (qtdemux,
1664             "let upstream handle seek for fragmented playback");
1665         goto upstream;
1666       }
1667
1668       /* Build complete index for seeking;
1669        * if not a fragmented file at least */
1670       if (!qtdemux->fragmented)
1671         if (!qtdemux_ensure_index (qtdemux))
1672           goto index_failed;
1673 #ifndef GST_DISABLE_GST_DEBUG
1674       ts = gst_util_get_timestamp () - ts;
1675       GST_INFO_OBJECT (qtdemux,
1676           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1677 #endif
1678     }
1679       if (qtdemux->pullbased) {
1680         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1681       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1682         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1683         res = TRUE;
1684       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1685           && !qtdemux->fragmented) {
1686         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1687       } else {
1688         GST_DEBUG_OBJECT (qtdemux,
1689             "ignoring seek in push mode in current state");
1690         res = FALSE;
1691       }
1692       gst_event_unref (event);
1693       break;
1694     case GST_EVENT_QOS:
1695     case GST_EVENT_NAVIGATION:
1696       res = FALSE;
1697       gst_event_unref (event);
1698       break;
1699     default:
1700     upstream:
1701       res = gst_pad_event_default (pad, parent, event);
1702       break;
1703   }
1704
1705 done:
1706   return res;
1707
1708   /* ERRORS */
1709 index_failed:
1710   {
1711     GST_ERROR_OBJECT (qtdemux, "Index failed");
1712     gst_event_unref (event);
1713     res = FALSE;
1714     goto done;
1715   }
1716 }
1717
1718 /* stream/index return sample that is min/max w.r.t. byte position,
1719  * time is min/max w.r.t. time of samples,
1720  * the latter need not be time of the former sample */
1721 static void
1722 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1723     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1724 {
1725   gint i, n, index;
1726   gint64 time, min_time;
1727   QtDemuxStream *stream;
1728
1729   min_time = -1;
1730   stream = NULL;
1731   index = -1;
1732
1733   for (n = 0; n < qtdemux->n_streams; ++n) {
1734     QtDemuxStream *str;
1735     gint inc;
1736     gboolean set_sample;
1737
1738     str = qtdemux->streams[n];
1739     set_sample = !set;
1740
1741     if (fw) {
1742       i = 0;
1743       inc = 1;
1744     } else {
1745       i = str->n_samples - 1;
1746       inc = -1;
1747     }
1748
1749     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1750       if (str->samples[i].size == 0)
1751         continue;
1752
1753       if (fw && (str->samples[i].offset < byte_pos))
1754         continue;
1755
1756       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1757         continue;
1758
1759       /* move stream to first available sample */
1760       if (set) {
1761         gst_qtdemux_move_stream (qtdemux, str, i);
1762         set_sample = TRUE;
1763       }
1764
1765       /* avoid index from sparse streams since they might be far away */
1766       if (!str->sparse) {
1767         /* determine min/max time */
1768         time = QTSAMPLE_PTS (str, &str->samples[i]);
1769         if (min_time == -1 || (!fw && time > min_time) ||
1770             (fw && time < min_time)) {
1771           min_time = time;
1772         }
1773
1774         /* determine stream with leading sample, to get its position */
1775         if (!stream ||
1776             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1777             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1778           stream = str;
1779           index = i;
1780         }
1781       }
1782       break;
1783     }
1784
1785     /* no sample for this stream, mark eos */
1786     if (!set_sample)
1787       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1788   }
1789
1790   if (_time)
1791     *_time = min_time;
1792   if (_stream)
1793     *_stream = stream;
1794   if (_index)
1795     *_index = index;
1796 }
1797
1798 static QtDemuxStream *
1799 _create_stream (void)
1800 {
1801   QtDemuxStream *stream;
1802
1803   stream = g_new0 (QtDemuxStream, 1);
1804   /* new streams always need a discont */
1805   stream->discont = TRUE;
1806   /* we enable clipping for raw audio/video streams */
1807   stream->need_clip = FALSE;
1808   stream->need_process = FALSE;
1809   stream->segment_index = -1;
1810   stream->time_position = 0;
1811   stream->sample_index = -1;
1812   stream->offset_in_sample = 0;
1813   stream->new_stream = TRUE;
1814   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1815   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1816   stream->protected = FALSE;
1817   stream->protection_scheme_type = 0;
1818   stream->protection_scheme_version = 0;
1819   stream->protection_scheme_info = NULL;
1820   g_queue_init (&stream->protection_scheme_event_queue);
1821   return stream;
1822 }
1823
1824 static gboolean
1825 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1826 {
1827   GstStructure *structure;
1828   const gchar *variant;
1829   const GstCaps *mediacaps = NULL;
1830
1831   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1832
1833   structure = gst_caps_get_structure (caps, 0);
1834   variant = gst_structure_get_string (structure, "variant");
1835
1836   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1837     QtDemuxStream *stream;
1838     const GValue *value;
1839
1840     demux->fragmented = TRUE;
1841     demux->mss_mode = TRUE;
1842
1843     if (demux->n_streams > 1) {
1844       /* can't do this, we can only renegotiate for another mss format */
1845       return FALSE;
1846     }
1847
1848     value = gst_structure_get_value (structure, "media-caps");
1849     /* create stream */
1850     if (value) {
1851       const GValue *timescale_v;
1852
1853       /* TODO update when stream changes during playback */
1854
1855       if (demux->n_streams == 0) {
1856         stream = _create_stream ();
1857         demux->streams[demux->n_streams] = stream;
1858         demux->n_streams = 1;
1859       } else {
1860         stream = demux->streams[0];
1861       }
1862
1863       timescale_v = gst_structure_get_value (structure, "timescale");
1864       if (timescale_v) {
1865         stream->timescale = g_value_get_uint64 (timescale_v);
1866       } else {
1867         /* default mss timescale */
1868         stream->timescale = 10000000;
1869       }
1870       demux->timescale = stream->timescale;
1871
1872       mediacaps = gst_value_get_caps (value);
1873       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1874         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1875             mediacaps);
1876         stream->new_caps = TRUE;
1877       }
1878       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1879       structure = gst_caps_get_structure (mediacaps, 0);
1880       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1881         stream->subtype = FOURCC_vide;
1882
1883         gst_structure_get_int (structure, "width", &stream->width);
1884         gst_structure_get_int (structure, "height", &stream->height);
1885         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1886             &stream->fps_d);
1887       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1888         gint rate = 0;
1889         stream->subtype = FOURCC_soun;
1890         gst_structure_get_int (structure, "channels", &stream->n_channels);
1891         gst_structure_get_int (structure, "rate", &rate);
1892         stream->rate = rate;
1893       }
1894     }
1895     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1896   } else {
1897     demux->mss_mode = FALSE;
1898   }
1899
1900   return TRUE;
1901 }
1902
1903 static void
1904 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1905 {
1906   gint n;
1907
1908   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1909   gst_pad_stop_task (qtdemux->sinkpad);
1910
1911   if (hard || qtdemux->upstream_format_is_time) {
1912     qtdemux->state = QTDEMUX_STATE_INITIAL;
1913     qtdemux->neededbytes = 16;
1914     qtdemux->todrop = 0;
1915     qtdemux->pullbased = FALSE;
1916     qtdemux->posted_redirect = FALSE;
1917     qtdemux->first_mdat = -1;
1918     qtdemux->header_size = 0;
1919     qtdemux->mdatoffset = -1;
1920     qtdemux->restoredata_offset = -1;
1921     if (qtdemux->mdatbuffer)
1922       gst_buffer_unref (qtdemux->mdatbuffer);
1923     if (qtdemux->restoredata_buffer)
1924       gst_buffer_unref (qtdemux->restoredata_buffer);
1925     qtdemux->mdatbuffer = NULL;
1926     qtdemux->restoredata_buffer = NULL;
1927     qtdemux->mdatleft = 0;
1928     if (qtdemux->comp_brands)
1929       gst_buffer_unref (qtdemux->comp_brands);
1930     qtdemux->comp_brands = NULL;
1931     qtdemux->last_moov_offset = -1;
1932     if (qtdemux->moov_node)
1933       g_node_destroy (qtdemux->moov_node);
1934     qtdemux->moov_node = NULL;
1935     qtdemux->moov_node_compressed = NULL;
1936     if (qtdemux->tag_list)
1937       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1938     qtdemux->tag_list = NULL;
1939 #if 0
1940     if (qtdemux->element_index)
1941       gst_object_unref (qtdemux->element_index);
1942     qtdemux->element_index = NULL;
1943 #endif
1944     qtdemux->major_brand = 0;
1945     if (qtdemux->pending_newsegment)
1946       gst_event_unref (qtdemux->pending_newsegment);
1947     qtdemux->pending_newsegment = NULL;
1948     qtdemux->upstream_format_is_time = FALSE;
1949     qtdemux->upstream_seekable = FALSE;
1950     qtdemux->upstream_size = 0;
1951
1952     qtdemux->fragment_start = -1;
1953     qtdemux->fragment_start_offset = -1;
1954     qtdemux->duration = 0;
1955     qtdemux->moof_offset = 0;
1956     qtdemux->chapters_track_id = 0;
1957     qtdemux->have_group_id = FALSE;
1958     qtdemux->group_id = G_MAXUINT;
1959
1960     if (qtdemux->protection_system_ids) {
1961       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
1962       qtdemux->protection_system_ids = NULL;
1963     }
1964     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1965         NULL);
1966     g_queue_clear (&qtdemux->protection_event_queue);
1967   }
1968   qtdemux->offset = 0;
1969   gst_adapter_clear (qtdemux->adapter);
1970   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1971
1972   if (hard) {
1973     for (n = 0; n < qtdemux->n_streams; n++) {
1974       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
1975       qtdemux->streams[n] = NULL;
1976     }
1977     qtdemux->n_streams = 0;
1978     qtdemux->n_video_streams = 0;
1979     qtdemux->n_audio_streams = 0;
1980     qtdemux->n_sub_streams = 0;
1981     qtdemux->exposed = FALSE;
1982     qtdemux->fragmented = FALSE;
1983     qtdemux->mss_mode = FALSE;
1984     gst_caps_replace (&qtdemux->media_caps, NULL);
1985     qtdemux->timescale = 0;
1986     qtdemux->got_moov = FALSE;
1987     qtdemux->pending_configure = FALSE;
1988   } else if (qtdemux->mss_mode) {
1989     gst_flow_combiner_reset (qtdemux->flowcombiner);
1990     for (n = 0; n < qtdemux->n_streams; n++)
1991       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
1992   } else {
1993     gst_flow_combiner_reset (qtdemux->flowcombiner);
1994     for (n = 0; n < qtdemux->n_streams; n++) {
1995       qtdemux->streams[n]->sent_eos = FALSE;
1996       qtdemux->streams[n]->segment_seqnum = 0;
1997       qtdemux->streams[n]->time_position = 0;
1998       qtdemux->streams[n]->accumulated_base = 0;
1999     }
2000     if (!qtdemux->pending_newsegment) {
2001       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2002     }
2003   }
2004 }
2005
2006 static gboolean
2007 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2008     GstEvent * event)
2009 {
2010   GstQTDemux *demux = GST_QTDEMUX (parent);
2011   gboolean res = TRUE;
2012
2013   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2014
2015   switch (GST_EVENT_TYPE (event)) {
2016     case GST_EVENT_SEGMENT:
2017     {
2018       gint64 offset = 0;
2019       QtDemuxStream *stream;
2020       gint idx;
2021       GstSegment segment;
2022       GstEvent *segment_event;
2023
2024       /* some debug output */
2025       gst_event_copy_segment (event, &segment);
2026       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2027           &segment);
2028
2029       if (segment.format == GST_FORMAT_TIME) {
2030         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2031         gst_event_replace (&demux->pending_newsegment, event);
2032         demux->upstream_format_is_time = TRUE;
2033       } else {
2034         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2035             "not in time format");
2036
2037         /* chain will send initial newsegment after pads have been added */
2038         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2039           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2040           goto exit;
2041         }
2042       }
2043
2044       /* check if this matches a time seek we received previously
2045        * FIXME for backwards compatibility reasons we use the
2046        * seek_offset here to compare. In the future we might want to
2047        * change this to use the seqnum as it uniquely should identify
2048        * the segment that corresponds to the seek. */
2049       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2050           ", received segment offset %" G_GINT64_FORMAT,
2051           demux->seek_offset, segment.start);
2052       if (segment.format == GST_FORMAT_BYTES
2053           && demux->seek_offset == segment.start) {
2054         GST_OBJECT_LOCK (demux);
2055         offset = segment.start;
2056
2057         segment.format = GST_FORMAT_TIME;
2058         segment.start = demux->push_seek_start;
2059         segment.stop = demux->push_seek_stop;
2060         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2061             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2062             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2063         GST_OBJECT_UNLOCK (demux);
2064       }
2065
2066       /* we only expect a BYTE segment, e.g. following a seek */
2067       if (segment.format == GST_FORMAT_BYTES) {
2068         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2069           offset = segment.start;
2070
2071           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2072               NULL, (gint64 *) & segment.start);
2073           if ((gint64) segment.start < 0)
2074             segment.start = 0;
2075         }
2076         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2077           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2078               NULL, (gint64 *) & segment.stop);
2079           /* keyframe seeking should already arrange for start >= stop,
2080            * but make sure in other rare cases */
2081           segment.stop = MAX (segment.stop, segment.start);
2082         }
2083       } else if (segment.format == GST_FORMAT_TIME) {
2084         /* push all data on the adapter before starting this
2085          * new segment */
2086         gst_qtdemux_process_adapter (demux, TRUE);
2087       } else {
2088         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2089         goto exit;
2090       }
2091
2092       /* accept upstream's notion of segment and distribute along */
2093       segment.format = GST_FORMAT_TIME;
2094       segment.position = segment.time = segment.start;
2095       segment.duration = demux->segment.duration;
2096       segment.base = gst_segment_to_running_time (&demux->segment,
2097           GST_FORMAT_TIME, demux->segment.position);
2098
2099       gst_segment_copy_into (&segment, &demux->segment);
2100       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2101       segment_event = gst_event_new_segment (&segment);
2102       gst_event_set_seqnum (segment_event, gst_event_get_seqnum (event));
2103       gst_qtdemux_push_event (demux, segment_event);
2104
2105       /* clear leftover in current segment, if any */
2106       gst_adapter_clear (demux->adapter);
2107
2108       /* set up streaming thread */
2109       demux->offset = offset;
2110       if (demux->upstream_format_is_time) {
2111         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2112             "set values to restart reading from a new atom");
2113         demux->neededbytes = 16;
2114         demux->todrop = 0;
2115       } else {
2116         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2117             NULL);
2118         if (stream) {
2119           demux->todrop = stream->samples[idx].offset - offset;
2120           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2121         } else {
2122           /* set up for EOS */
2123           demux->neededbytes = -1;
2124           demux->todrop = 0;
2125         }
2126       }
2127     exit:
2128       gst_event_unref (event);
2129       res = TRUE;
2130       goto drop;
2131     }
2132     case GST_EVENT_FLUSH_START:
2133     {
2134       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2135         gst_event_unref (event);
2136         goto drop;
2137       }
2138       break;
2139     }
2140     case GST_EVENT_FLUSH_STOP:
2141     {
2142       guint64 dur;
2143
2144       dur = demux->segment.duration;
2145       gst_qtdemux_reset (demux, FALSE);
2146       demux->segment.duration = dur;
2147
2148       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2149         gst_event_unref (event);
2150         goto drop;
2151       }
2152       break;
2153     }
2154     case GST_EVENT_EOS:
2155       /* If we are in push mode, and get an EOS before we've seen any streams,
2156        * then error out - we have nowhere to send the EOS */
2157       if (!demux->pullbased) {
2158         gint i;
2159         gboolean has_valid_stream = FALSE;
2160         for (i = 0; i < demux->n_streams; i++) {
2161           if (demux->streams[i]->pad != NULL) {
2162             has_valid_stream = TRUE;
2163             break;
2164           }
2165         }
2166         if (!has_valid_stream)
2167           gst_qtdemux_post_no_playable_stream_error (demux);
2168         else {
2169           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2170               (guint) gst_adapter_available (demux->adapter));
2171           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2172             res = FALSE;
2173           }
2174         }
2175       }
2176       break;
2177     case GST_EVENT_CAPS:{
2178       GstCaps *caps = NULL;
2179
2180       gst_event_parse_caps (event, &caps);
2181       gst_qtdemux_setcaps (demux, caps);
2182       res = TRUE;
2183       gst_event_unref (event);
2184       goto drop;
2185     }
2186     case GST_EVENT_PROTECTION:
2187     {
2188       const gchar *system_id = NULL;
2189
2190       gst_event_parse_protection (event, &system_id, NULL, NULL);
2191       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2192           system_id);
2193       gst_qtdemux_append_protection_system_id (demux, system_id);
2194       /* save the event for later, for source pads that have not been created */
2195       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2196       /* send it to all pads that already exist */
2197       gst_qtdemux_push_event (demux, event);
2198       res = TRUE;
2199       goto drop;
2200     }
2201     default:
2202       break;
2203   }
2204
2205   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2206
2207 drop:
2208   return res;
2209 }
2210
2211 #if 0
2212 static void
2213 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2214 {
2215   GstQTDemux *demux = GST_QTDEMUX (element);
2216
2217   GST_OBJECT_LOCK (demux);
2218   if (demux->element_index)
2219     gst_object_unref (demux->element_index);
2220   if (index) {
2221     demux->element_index = gst_object_ref (index);
2222   } else {
2223     demux->element_index = NULL;
2224   }
2225   GST_OBJECT_UNLOCK (demux);
2226   /* object lock might be taken again */
2227   if (index)
2228     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2229   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2230       demux->element_index, demux->index_id);
2231 }
2232
2233 static GstIndex *
2234 gst_qtdemux_get_index (GstElement * element)
2235 {
2236   GstIndex *result = NULL;
2237   GstQTDemux *demux = GST_QTDEMUX (element);
2238
2239   GST_OBJECT_LOCK (demux);
2240   if (demux->element_index)
2241     result = gst_object_ref (demux->element_index);
2242   GST_OBJECT_UNLOCK (demux);
2243
2244   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2245
2246   return result;
2247 }
2248 #endif
2249
2250 static void
2251 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2252 {
2253   g_free ((gpointer) stream->stco.data);
2254   stream->stco.data = NULL;
2255   g_free ((gpointer) stream->stsz.data);
2256   stream->stsz.data = NULL;
2257   g_free ((gpointer) stream->stsc.data);
2258   stream->stsc.data = NULL;
2259   g_free ((gpointer) stream->stts.data);
2260   stream->stts.data = NULL;
2261   g_free ((gpointer) stream->stss.data);
2262   stream->stss.data = NULL;
2263   g_free ((gpointer) stream->stps.data);
2264   stream->stps.data = NULL;
2265   g_free ((gpointer) stream->ctts.data);
2266   stream->ctts.data = NULL;
2267 }
2268
2269 static void
2270 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2271     QtDemuxStream * stream)
2272 {
2273   g_free (stream->segments);
2274   stream->segments = NULL;
2275   stream->segment_index = -1;
2276   stream->accumulated_base = 0;
2277 }
2278
2279 static void
2280 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2281     QtDemuxStream * stream)
2282 {
2283   g_free (stream->samples);
2284   stream->samples = NULL;
2285   gst_qtdemux_stbl_free (stream);
2286
2287   /* fragments */
2288   g_free (stream->ra_entries);
2289   stream->ra_entries = NULL;
2290   stream->n_ra_entries = 0;
2291
2292   stream->sample_index = -1;
2293   stream->stbl_index = -1;
2294   stream->n_samples = 0;
2295   stream->time_position = 0;
2296 }
2297
2298 static void
2299 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2300 {
2301   if (stream->allocator)
2302     gst_object_unref (stream->allocator);
2303   while (stream->buffers) {
2304     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2305     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2306   }
2307   if (stream->rgb8_palette) {
2308     gst_memory_unref (stream->rgb8_palette);
2309     stream->rgb8_palette = NULL;
2310   }
2311
2312   if (stream->pending_tags)
2313     gst_tag_list_unref (stream->pending_tags);
2314   stream->pending_tags = NULL;
2315   g_free (stream->redirect_uri);
2316   stream->redirect_uri = NULL;
2317   stream->sent_eos = FALSE;
2318   stream->sparse = FALSE;
2319   stream->protected = FALSE;
2320   if (stream->protection_scheme_info) {
2321     if (stream->protection_scheme_type == FOURCC_cenc) {
2322       QtDemuxCencSampleSetInfo *info =
2323           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2324       if (info->default_properties)
2325         gst_structure_free (info->default_properties);
2326       if (info->crypto_info)
2327         g_ptr_array_free (info->crypto_info, TRUE);
2328     }
2329     g_free (stream->protection_scheme_info);
2330     stream->protection_scheme_info = NULL;
2331   }
2332   stream->protection_scheme_type = 0;
2333   stream->protection_scheme_version = 0;
2334   g_queue_foreach (&stream->protection_scheme_event_queue,
2335       (GFunc) gst_event_unref, NULL);
2336   g_queue_clear (&stream->protection_scheme_event_queue);
2337   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2338   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2339 }
2340
2341 static void
2342 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2343 {
2344   gst_qtdemux_stream_clear (qtdemux, stream);
2345   if (stream->caps)
2346     gst_caps_unref (stream->caps);
2347   stream->caps = NULL;
2348   if (stream->pad) {
2349     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2350     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2351   }
2352   g_free (stream);
2353 }
2354
2355 static void
2356 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2357 {
2358   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2359
2360   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2361   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2362   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2363   qtdemux->n_streams--;
2364 }
2365
2366 static GstStateChangeReturn
2367 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2368 {
2369   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2370   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2371
2372   switch (transition) {
2373     case GST_STATE_CHANGE_PAUSED_TO_READY:
2374       break;
2375     default:
2376       break;
2377   }
2378
2379   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2380
2381   switch (transition) {
2382     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2383       gst_qtdemux_reset (qtdemux, TRUE);
2384       break;
2385     }
2386     default:
2387       break;
2388   }
2389
2390   return result;
2391 }
2392
2393 static void
2394 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2395 {
2396   /* counts as header data */
2397   qtdemux->header_size += length;
2398
2399   /* only consider at least a sufficiently complete ftyp atom */
2400   if (length >= 20) {
2401     GstBuffer *buf;
2402
2403     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2404     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2405         GST_FOURCC_ARGS (qtdemux->major_brand));
2406     if (qtdemux->comp_brands)
2407       gst_buffer_unref (qtdemux->comp_brands);
2408     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2409     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2410   }
2411 }
2412
2413 static void
2414 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2415     GstTagList * xmptaglist)
2416 {
2417   /* Strip out bogus fields */
2418   if (xmptaglist) {
2419     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2420       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2421       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2422     } else {
2423       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2424     }
2425
2426     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2427
2428     /* prioritize native tags using _KEEP mode */
2429     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2430     gst_tag_list_unref (xmptaglist);
2431   }
2432 }
2433
2434 static void
2435 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2436 {
2437   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2438     0x97, 0xA9, 0x42, 0xE8,
2439     0x9C, 0x71, 0x99, 0x94,
2440     0x91, 0xE3, 0xAF, 0xAC
2441   };
2442   static const guint8 playready_uuid[] = {
2443     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2444     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2445   };
2446   guint offset;
2447
2448   /* counts as header data */
2449   qtdemux->header_size += length;
2450
2451   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2452
2453   if (length <= offset + 16) {
2454     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2455     return;
2456   }
2457
2458   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2459     GstBuffer *buf;
2460     GstTagList *taglist;
2461
2462     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2463         length - offset - 16, NULL);
2464     taglist = gst_tag_list_from_xmp_buffer (buf);
2465     gst_buffer_unref (buf);
2466
2467     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2468
2469   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2470     int len;
2471     const gunichar2 *s_utf16;
2472     char *contents;
2473
2474     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2475     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2476     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2477     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2478
2479     g_free (contents);
2480
2481     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2482         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2483         (NULL));
2484   } else {
2485     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2486         GST_READ_UINT32_LE (buffer + offset),
2487         GST_READ_UINT32_LE (buffer + offset + 4),
2488         GST_READ_UINT32_LE (buffer + offset + 8),
2489         GST_READ_UINT32_LE (buffer + offset + 12));
2490   }
2491 }
2492
2493 static void
2494 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2495 {
2496   GstSidxParser sidx_parser;
2497   GstIsoffParserResult res;
2498   guint consumed;
2499
2500   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2501
2502   res =
2503       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2504       &consumed);
2505   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2506   if (res == GST_ISOFF_QT_PARSER_DONE) {
2507     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2508   }
2509   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2510 }
2511
2512 /* caller verifies at least 8 bytes in buf */
2513 static void
2514 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2515     guint64 * plength, guint32 * pfourcc)
2516 {
2517   guint64 length;
2518   guint32 fourcc;
2519
2520   length = QT_UINT32 (data);
2521   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2522   fourcc = QT_FOURCC (data + 4);
2523   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2524
2525   if (length == 0) {
2526     length = G_MAXUINT64;
2527   } else if (length == 1 && size >= 16) {
2528     /* this means we have an extended size, which is the 64 bit value of
2529      * the next 8 bytes */
2530     length = QT_UINT64 (data + 8);
2531     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2532   }
2533
2534   if (plength)
2535     *plength = length;
2536   if (pfourcc)
2537     *pfourcc = fourcc;
2538 }
2539
2540 static gboolean
2541 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2542 {
2543   guint32 version = 0;
2544   GstClockTime duration = 0;
2545
2546   if (!gst_byte_reader_get_uint32_be (br, &version))
2547     goto failed;
2548
2549   version >>= 24;
2550   if (version == 1) {
2551     if (!gst_byte_reader_get_uint64_be (br, &duration))
2552       goto failed;
2553   } else {
2554     guint32 dur = 0;
2555
2556     if (!gst_byte_reader_get_uint32_be (br, &dur))
2557       goto failed;
2558     duration = dur;
2559   }
2560
2561   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2562   qtdemux->duration = duration;
2563
2564   return TRUE;
2565
2566 failed:
2567   {
2568     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2569     return FALSE;
2570   }
2571 }
2572
2573 static gboolean
2574 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2575     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2576 {
2577   if (!stream->parsed_trex && qtdemux->moov_node) {
2578     GNode *mvex, *trex;
2579     GstByteReader trex_data;
2580
2581     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2582     if (mvex) {
2583       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2584           &trex_data);
2585       while (trex) {
2586         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2587
2588         /* skip version/flags */
2589         if (!gst_byte_reader_skip (&trex_data, 4))
2590           goto next;
2591         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2592           goto next;
2593         if (id != stream->track_id)
2594           goto next;
2595         /* sample description index; ignore */
2596         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2597           goto next;
2598         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2599           goto next;
2600         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2601           goto next;
2602         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2603           goto next;
2604
2605         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2606             "duration %d,  size %d, flags 0x%x", stream->track_id,
2607             dur, size, flags);
2608
2609         stream->parsed_trex = TRUE;
2610         stream->def_sample_duration = dur;
2611         stream->def_sample_size = size;
2612         stream->def_sample_flags = flags;
2613
2614       next:
2615         /* iterate all siblings */
2616         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2617             &trex_data);
2618       }
2619     }
2620   }
2621
2622   *ds_duration = stream->def_sample_duration;
2623   *ds_size = stream->def_sample_size;
2624   *ds_flags = stream->def_sample_flags;
2625
2626   /* even then, above values are better than random ... */
2627   if (G_UNLIKELY (!stream->parsed_trex)) {
2628     GST_WARNING_OBJECT (qtdemux,
2629         "failed to find fragment defaults for stream %d", stream->track_id);
2630     return FALSE;
2631   }
2632
2633   return TRUE;
2634 }
2635
2636 /* This method should be called whenever a more accurate duration might
2637  * have been found. It will update all relevant variables if/where needed
2638  */
2639 static void
2640 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2641 {
2642   guint i;
2643   guint64 movdur;
2644   GstClockTime prevdur;
2645
2646   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2647
2648   if (movdur > qtdemux->duration) {
2649     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2650     GST_DEBUG_OBJECT (qtdemux,
2651         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2652         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2653     qtdemux->duration = movdur;
2654     GST_DEBUG_OBJECT (qtdemux,
2655         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2656         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2657         GST_TIME_ARGS (qtdemux->segment.stop));
2658     if (qtdemux->segment.duration == prevdur) {
2659       /* If the current segment has duration/stop identical to previous duration
2660        * update them also (because they were set at that point in time with
2661        * the wrong duration */
2662       /* We convert the value *from* the timescale version to avoid rounding errors */
2663       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2664       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2665       qtdemux->segment.duration = fixeddur;
2666       qtdemux->segment.stop = fixeddur;
2667     }
2668   }
2669   for (i = 0; i < qtdemux->n_streams; i++) {
2670     QtDemuxStream *stream = qtdemux->streams[i];
2671     if (stream) {
2672       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2673       if (movdur > stream->duration) {
2674         GST_DEBUG_OBJECT (qtdemux,
2675             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2676             GST_TIME_ARGS (duration));
2677         stream->duration = movdur;
2678         if (stream->dummy_segment) {
2679           /* Update all dummy values to new duration */
2680           stream->segments[0].stop_time = duration;
2681           stream->segments[0].duration = duration;
2682           stream->segments[0].media_stop = duration;
2683         }
2684       }
2685     }
2686   }
2687 }
2688
2689 static gboolean
2690 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2691     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2692     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2693     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2694 {
2695   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2696   guint64 timestamp;
2697   gint32 data_offset = 0;
2698   guint32 flags = 0, first_flags = 0, samples_count = 0;
2699   gint i;
2700   guint8 *data;
2701   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2702   QtDemuxSample *sample;
2703   gboolean ismv = FALSE;
2704
2705   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2706       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2707       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2708       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2709
2710   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2711     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2712     return TRUE;
2713   }
2714
2715   /* presence of stss or not can't really tell us much,
2716    * and flags and so on tend to be marginally reliable in these files */
2717   if (stream->subtype == FOURCC_soun) {
2718     GST_DEBUG_OBJECT (qtdemux,
2719         "sound track in fragmented file; marking all keyframes");
2720     stream->all_keyframe = TRUE;
2721   }
2722
2723   if (!gst_byte_reader_skip (trun, 1) ||
2724       !gst_byte_reader_get_uint24_be (trun, &flags))
2725     goto fail;
2726
2727   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
2728     goto fail;
2729
2730   if (flags & TR_DATA_OFFSET) {
2731     /* note this is really signed */
2732     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
2733       goto fail;
2734     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
2735     /* default base offset = first byte of moof */
2736     if (*base_offset == -1) {
2737       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
2738       *base_offset = moof_offset;
2739     }
2740     *running_offset = *base_offset + data_offset;
2741   } else {
2742     /* if no offset at all, that would mean data starts at moof start,
2743      * which is a bit wrong and is ismv crappy way, so compensate
2744      * assuming data is in mdat following moof */
2745     if (*base_offset == -1) {
2746       *base_offset = moof_offset + moof_length + 8;
2747       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
2748       ismv = TRUE;
2749     }
2750     if (*running_offset == -1)
2751       *running_offset = *base_offset;
2752   }
2753
2754   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
2755       *running_offset);
2756   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
2757       data_offset, flags, samples_count);
2758
2759   if (flags & TR_FIRST_SAMPLE_FLAGS) {
2760     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
2761       GST_DEBUG_OBJECT (qtdemux,
2762           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
2763       flags ^= TR_FIRST_SAMPLE_FLAGS;
2764     } else {
2765       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
2766         goto fail;
2767       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
2768     }
2769   }
2770
2771   /* FIXME ? spec says other bits should also be checked to determine
2772    * entry size (and prefix size for that matter) */
2773   entry_size = 0;
2774   dur_offset = size_offset = 0;
2775   if (flags & TR_SAMPLE_DURATION) {
2776     GST_LOG_OBJECT (qtdemux, "entry duration present");
2777     dur_offset = entry_size;
2778     entry_size += 4;
2779   }
2780   if (flags & TR_SAMPLE_SIZE) {
2781     GST_LOG_OBJECT (qtdemux, "entry size present");
2782     size_offset = entry_size;
2783     entry_size += 4;
2784   }
2785   if (flags & TR_SAMPLE_FLAGS) {
2786     GST_LOG_OBJECT (qtdemux, "entry flags present");
2787     flags_offset = entry_size;
2788     entry_size += 4;
2789   }
2790   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
2791     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
2792     ct_offset = entry_size;
2793     entry_size += 4;
2794   }
2795
2796   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
2797     goto fail;
2798   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
2799
2800   if (stream->n_samples + samples_count >=
2801       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
2802     goto index_too_big;
2803
2804   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
2805       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
2806       (stream->n_samples + samples_count) *
2807       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
2808
2809   /* create a new array of samples if it's the first sample parsed */
2810   if (stream->n_samples == 0) {
2811     g_assert (stream->samples == NULL);
2812     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
2813     /* or try to reallocate it with space enough to insert the new samples */
2814   } else
2815     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
2816         stream->n_samples + samples_count);
2817   if (stream->samples == NULL)
2818     goto out_of_memory;
2819
2820   if (qtdemux->fragment_start != -1) {
2821     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
2822     qtdemux->fragment_start = -1;
2823   } else {
2824     if (stream->n_samples == 0) {
2825       if (decode_ts > 0) {
2826         timestamp = decode_ts;
2827       } else if (stream->pending_seek != NULL) {
2828         /* if we don't have a timestamp from a tfdt box, we'll use the one
2829          * from the mfra seek table */
2830         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
2831             GST_TIME_ARGS (stream->pending_seek->ts));
2832
2833         /* FIXME: this is not fully correct, the timestamp refers to the random
2834          * access sample refered to in the tfra entry, which may not necessarily
2835          * be the first sample in the tfrag/trun (but hopefully/usually is) */
2836         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
2837       } else {
2838         timestamp = 0;
2839       }
2840
2841       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
2842       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
2843           GST_TIME_ARGS (gst_ts));
2844     } else {
2845       /* subsequent fragments extend stream */
2846       timestamp =
2847           stream->samples[stream->n_samples - 1].timestamp +
2848           stream->samples[stream->n_samples - 1].duration;
2849
2850       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
2851       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
2852           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
2853     }
2854   }
2855
2856   sample = stream->samples + stream->n_samples;
2857   for (i = 0; i < samples_count; i++) {
2858     guint32 dur, size, sflags, ct;
2859
2860     /* first read sample data */
2861     if (flags & TR_SAMPLE_DURATION) {
2862       dur = QT_UINT32 (data + dur_offset);
2863     } else {
2864       dur = d_sample_duration;
2865     }
2866     if (flags & TR_SAMPLE_SIZE) {
2867       size = QT_UINT32 (data + size_offset);
2868     } else {
2869       size = d_sample_size;
2870     }
2871     if (flags & TR_FIRST_SAMPLE_FLAGS) {
2872       if (i == 0) {
2873         sflags = first_flags;
2874       } else {
2875         sflags = d_sample_flags;
2876       }
2877     } else if (flags & TR_SAMPLE_FLAGS) {
2878       sflags = QT_UINT32 (data + flags_offset);
2879     } else {
2880       sflags = d_sample_flags;
2881     }
2882     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
2883       ct = QT_UINT32 (data + ct_offset);
2884     } else {
2885       ct = 0;
2886     }
2887     data += entry_size;
2888
2889     /* fill the sample information */
2890     sample->offset = *running_offset;
2891     sample->pts_offset = ct;
2892     sample->size = size;
2893     sample->timestamp = timestamp;
2894     sample->duration = dur;
2895     /* sample-is-difference-sample */
2896     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
2897      * now idea how it relates to bitfield other than massive LE/BE confusion */
2898     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
2899     *running_offset += size;
2900     timestamp += dur;
2901     sample++;
2902   }
2903
2904   /* Update total duration if needed */
2905   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
2906
2907   stream->n_samples += samples_count;
2908
2909   if (stream->pending_seek != NULL)
2910     stream->pending_seek = NULL;
2911
2912   return TRUE;
2913
2914 fail:
2915   {
2916     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
2917     return FALSE;
2918   }
2919 out_of_memory:
2920   {
2921     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
2922         stream->n_samples);
2923     return FALSE;
2924   }
2925 index_too_big:
2926   {
2927     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
2928         "be larger than %uMB (broken file?)", stream->n_samples,
2929         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
2930     return FALSE;
2931   }
2932 }
2933
2934 /* find stream with @id */
2935 static inline QtDemuxStream *
2936 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
2937 {
2938   QtDemuxStream *stream;
2939   gint i;
2940
2941   /* check */
2942   if (G_UNLIKELY (!id)) {
2943     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
2944     return NULL;
2945   }
2946
2947   /* try to get it fast and simple */
2948   if (G_LIKELY (id <= qtdemux->n_streams)) {
2949     stream = qtdemux->streams[id - 1];
2950     if (G_LIKELY (stream->track_id == id))
2951       return stream;
2952   }
2953
2954   /* linear search otherwise */
2955   for (i = 0; i < qtdemux->n_streams; i++) {
2956     stream = qtdemux->streams[i];
2957     if (stream->track_id == id)
2958       return stream;
2959   }
2960   if (qtdemux->mss_mode) {
2961     /* mss should have only 1 stream anyway */
2962     return qtdemux->streams[0];
2963   }
2964
2965   return NULL;
2966 }
2967
2968 static gboolean
2969 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
2970     guint32 * fragment_number)
2971 {
2972   if (!gst_byte_reader_skip (mfhd, 4))
2973     goto fail;
2974   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
2975     goto fail;
2976   return TRUE;
2977 fail:
2978   {
2979     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
2980     return FALSE;
2981   }
2982 }
2983
2984 static gboolean
2985 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
2986     QtDemuxStream ** stream, guint32 * default_sample_duration,
2987     guint32 * default_sample_size, guint32 * default_sample_flags,
2988     gint64 * base_offset)
2989 {
2990   guint32 flags = 0;
2991   guint32 track_id = 0;
2992
2993   if (!gst_byte_reader_skip (tfhd, 1) ||
2994       !gst_byte_reader_get_uint24_be (tfhd, &flags))
2995     goto invalid_track;
2996
2997   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
2998     goto invalid_track;
2999
3000   *stream = qtdemux_find_stream (qtdemux, track_id);
3001   if (G_UNLIKELY (!*stream))
3002     goto unknown_stream;
3003
3004   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3005     *base_offset = qtdemux->moof_offset;
3006
3007   if (flags & TF_BASE_DATA_OFFSET)
3008     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3009       goto invalid_track;
3010
3011   /* obtain stream defaults */
3012   qtdemux_parse_trex (qtdemux, *stream,
3013       default_sample_duration, default_sample_size, default_sample_flags);
3014
3015   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3016   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3017     if (!gst_byte_reader_skip (tfhd, 4))
3018       goto invalid_track;
3019
3020   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3021     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3022       goto invalid_track;
3023
3024   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3025     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3026       goto invalid_track;
3027
3028   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3029     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3030       goto invalid_track;
3031
3032   return TRUE;
3033
3034 invalid_track:
3035   {
3036     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3037     return FALSE;
3038   }
3039 unknown_stream:
3040   {
3041     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3042     return TRUE;
3043   }
3044 }
3045
3046 static gboolean
3047 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3048     guint64 * decode_time)
3049 {
3050   guint32 version = 0;
3051
3052   if (!gst_byte_reader_get_uint32_be (br, &version))
3053     return FALSE;
3054
3055   version >>= 24;
3056   if (version == 1) {
3057     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3058       goto failed;
3059   } else {
3060     guint32 dec_time = 0;
3061     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3062       goto failed;
3063     *decode_time = dec_time;
3064   }
3065
3066   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3067       *decode_time);
3068
3069   return TRUE;
3070
3071 failed:
3072   {
3073     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3074     return FALSE;
3075   }
3076 }
3077
3078 /* Returns a pointer to a GstStructure containing the properties of
3079  * the stream sample identified by @sample_index. The caller must unref
3080  * the returned object after use. Returns NULL if unsuccessful. */
3081 static GstStructure *
3082 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3083     QtDemuxStream * stream, guint sample_index)
3084 {
3085   QtDemuxCencSampleSetInfo *info = NULL;
3086
3087   g_return_val_if_fail (stream != NULL, NULL);
3088   g_return_val_if_fail (stream->protected, NULL);
3089   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3090
3091   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3092
3093   /* Currently, cenc properties for groups of samples are not supported, so
3094    * simply return a copy of the default sample properties */
3095   return gst_structure_copy (info->default_properties);
3096 }
3097
3098 /* Parses the sizes of sample auxiliary information contained within a stream,
3099  * as given in a saiz box. Returns array of sample_count guint8 size values,
3100  * or NULL on failure */
3101 static guint8 *
3102 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3103     GstByteReader * br, guint32 * sample_count)
3104 {
3105   guint32 flags = 0;
3106   guint8 *info_sizes;
3107   guint8 default_info_size;
3108
3109   g_return_val_if_fail (qtdemux != NULL, NULL);
3110   g_return_val_if_fail (stream != NULL, NULL);
3111   g_return_val_if_fail (br != NULL, NULL);
3112   g_return_val_if_fail (sample_count != NULL, NULL);
3113
3114   if (!gst_byte_reader_get_uint32_be (br, &flags))
3115     return NULL;
3116
3117   if (flags & 0x1) {
3118     /* aux_info_type and aux_info_type_parameter are ignored */
3119     if (!gst_byte_reader_skip (br, 8))
3120       return NULL;
3121   }
3122
3123   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3124     return NULL;
3125   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3126
3127   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3128     return NULL;
3129   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3130
3131
3132   if (default_info_size == 0) {
3133     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3134       return NULL;
3135     }
3136   } else {
3137     info_sizes = g_new (guint8, *sample_count);
3138     memset (info_sizes, default_info_size, *sample_count);
3139   }
3140
3141   return info_sizes;
3142 }
3143
3144 /* Parses the offset of sample auxiliary information contained within a stream,
3145  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3146 static gboolean
3147 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3148     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3149     guint64 * offset)
3150 {
3151   guint8 version = 0;
3152   guint32 flags = 0;
3153   guint32 aux_info_type = 0;
3154   guint32 aux_info_type_parameter = 0;
3155   guint32 entry_count;
3156   guint32 off_32;
3157   guint64 off_64;
3158
3159   g_return_val_if_fail (qtdemux != NULL, FALSE);
3160   g_return_val_if_fail (stream != NULL, FALSE);
3161   g_return_val_if_fail (br != NULL, FALSE);
3162   g_return_val_if_fail (offset != NULL, FALSE);
3163
3164   if (!gst_byte_reader_get_uint8 (br, &version))
3165     return FALSE;
3166
3167   if (!gst_byte_reader_get_uint24_be (br, &flags))
3168     return FALSE;
3169
3170   if (flags & 0x1) {
3171     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type))
3172       return FALSE;
3173     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3174       return FALSE;
3175   } else if (stream->protected) {
3176     aux_info_type = stream->protection_scheme_type;
3177   } else {
3178     aux_info_type = stream->fourcc;
3179   }
3180
3181   if (info_type)
3182     *info_type = aux_info_type;
3183   if (info_type_parameter)
3184     *info_type_parameter = aux_info_type_parameter;
3185
3186   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3187       "aux_info_type_parameter:  %#06x",
3188       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3189
3190   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3191     return FALSE;
3192
3193   if (entry_count != 1) {
3194     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3195     return FALSE;
3196   }
3197
3198   if (version == 0) {
3199     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3200       return FALSE;
3201     *offset = (guint64) off_32;
3202   } else {
3203     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3204       return FALSE;
3205     *offset = off_64;
3206   }
3207
3208   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3209   return TRUE;
3210 }
3211
3212 static void
3213 qtdemux_gst_structure_free (GstStructure * gststructure)
3214 {
3215   if (gststructure) {
3216     gst_structure_free (gststructure);
3217   }
3218 }
3219
3220 /* Parses auxiliary information relating to samples protected using Common
3221  * Encryption (cenc); the format of this information is defined in
3222  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3223 static gboolean
3224 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3225     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3226 {
3227   QtDemuxCencSampleSetInfo *ss_info = NULL;
3228   guint8 size;
3229   gint i;
3230
3231   g_return_val_if_fail (qtdemux != NULL, FALSE);
3232   g_return_val_if_fail (stream != NULL, FALSE);
3233   g_return_val_if_fail (br != NULL, FALSE);
3234   g_return_val_if_fail (stream->protected, FALSE);
3235   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3236
3237   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3238
3239   if (ss_info->crypto_info) {
3240     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3241     g_ptr_array_free (ss_info->crypto_info, TRUE);
3242   }
3243
3244   ss_info->crypto_info =
3245       g_ptr_array_new_full (sample_count,
3246       (GDestroyNotify) qtdemux_gst_structure_free);
3247
3248   for (i = 0; i < sample_count; ++i) {
3249     GstStructure *properties;
3250     guint16 n_subsamples = 0;
3251     guint8 *data;
3252     guint iv_size;
3253     GstBuffer *buf;
3254
3255     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3256     if (properties == NULL) {
3257       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3258       return FALSE;
3259     }
3260     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3261       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3262       gst_structure_free (properties);
3263       return FALSE;
3264     }
3265     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3266       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3267       gst_structure_free (properties);
3268       return FALSE;
3269     }
3270     buf = gst_buffer_new_wrapped (data, iv_size);
3271     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3272     size = info_sizes[i];
3273     if (size > iv_size) {
3274       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3275           || !(n_subsamples > 0)) {
3276         gst_structure_free (properties);
3277         GST_ERROR_OBJECT (qtdemux,
3278             "failed to get subsample count for sample %u", i);
3279         return FALSE;
3280       }
3281       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3282       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3283         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3284             i);
3285         gst_structure_free (properties);
3286         return FALSE;
3287       }
3288       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3289       if (!buf) {
3290         gst_structure_free (properties);
3291         return FALSE;
3292       }
3293       gst_structure_set (properties,
3294           "subsample_count", G_TYPE_UINT, n_subsamples,
3295           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3296     } else {
3297       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3298     }
3299     g_ptr_array_add (ss_info->crypto_info, properties);
3300   }
3301   return TRUE;
3302 }
3303
3304 /* Converts a UUID in raw byte form to a string representation, as defined in
3305  * RFC 4122. The caller takes ownership of the returned string and is
3306  * responsible for freeing it after use. */
3307 static gchar *
3308 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3309 {
3310   const guint8 *uuid = (const guint8 *) uuid_bytes;
3311
3312   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3313       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3314       uuid[0], uuid[1], uuid[2], uuid[3],
3315       uuid[4], uuid[5], uuid[6], uuid[7],
3316       uuid[8], uuid[9], uuid[10], uuid[11],
3317       uuid[12], uuid[13], uuid[14], uuid[15]);
3318 }
3319
3320 /* Parses a Protection System Specific Header box (pssh), as defined in the
3321  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3322  * information needed by a specific content protection system in order to
3323  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3324  * otherwise. */
3325 static gboolean
3326 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3327 {
3328   gchar *sysid_string;
3329   guint32 pssh_size = QT_UINT32 (node->data);
3330   GstBuffer *pssh = NULL;
3331   GstEvent *event = NULL;
3332   guint32 parent_box_type;
3333   gint i;
3334
3335   if (G_UNLIKELY (pssh_size < 32U)) {
3336     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3337     return FALSE;
3338   }
3339
3340   sysid_string =
3341       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3342
3343   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3344
3345   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3346   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3347       gst_buffer_get_size (pssh));
3348
3349   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3350
3351   /* Push an event containing the pssh box onto the queues of all streams. */
3352   event = gst_event_new_protection (sysid_string, pssh,
3353       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3354   for (i = 0; i < qtdemux->n_streams; ++i) {
3355     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3356         gst_event_ref (event));
3357   }
3358   g_free (sysid_string);
3359   gst_event_unref (event);
3360   gst_buffer_unref (pssh);
3361   return TRUE;
3362 }
3363
3364 static gboolean
3365 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3366     guint64 moof_offset, QtDemuxStream * stream)
3367 {
3368   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3369   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3370   GNode *saiz_node, *saio_node, *pssh_node;
3371   GstByteReader saiz_data, saio_data;
3372   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3373   gint64 base_offset, running_offset;
3374   guint32 frag_num;
3375
3376   /* NOTE @stream ignored */
3377
3378   moof_node = g_node_new ((guint8 *) buffer);
3379   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3380   qtdemux_node_dump (qtdemux, moof_node);
3381
3382   /* Get fragment number from mfhd and check it's valid */
3383   mfhd_node =
3384       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3385   if (mfhd_node == NULL)
3386     goto missing_mfhd;
3387   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3388     goto fail;
3389   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3390
3391   /* unknown base_offset to start with */
3392   base_offset = running_offset = -1;
3393   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3394   while (traf_node) {
3395     guint64 decode_time = 0;
3396
3397     /* Fragment Header node */
3398     tfhd_node =
3399         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3400         &tfhd_data);
3401     if (!tfhd_node)
3402       goto missing_tfhd;
3403     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3404             &ds_size, &ds_flags, &base_offset))
3405       goto missing_tfhd;
3406
3407     /* The following code assumes at most a single set of sample auxiliary
3408      * data in the fragment (consisting of a saiz box and a corresponding saio
3409      * box); in theory, however, there could be multiple sets of sample
3410      * auxiliary data in a fragment. */
3411     saiz_node =
3412         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3413         &saiz_data);
3414     if (saiz_node) {
3415       guint32 info_type = 0;
3416       guint64 offset = 0;
3417       guint32 info_type_parameter = 0;
3418
3419       g_free (qtdemux->cenc_aux_info_sizes);
3420
3421       qtdemux->cenc_aux_info_sizes =
3422           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3423           &qtdemux->cenc_aux_sample_count);
3424       if (qtdemux->cenc_aux_info_sizes == NULL) {
3425         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3426         goto fail;
3427       }
3428       saio_node =
3429           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3430           &saio_data);
3431       if (!saio_node) {
3432         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3433         g_free (qtdemux->cenc_aux_info_sizes);
3434         qtdemux->cenc_aux_info_sizes = NULL;
3435         goto fail;
3436       }
3437
3438       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3439                   &info_type, &info_type_parameter, &offset))) {
3440         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3441         g_free (qtdemux->cenc_aux_info_sizes);
3442         qtdemux->cenc_aux_info_sizes = NULL;
3443         goto fail;
3444       }
3445       if (base_offset > qtdemux->moof_offset)
3446         offset += (guint64) (base_offset - qtdemux->moof_offset);
3447       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3448         GstByteReader br;
3449         if (offset > length) {
3450           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3451           qtdemux->cenc_aux_info_offset = offset;
3452         } else {
3453           gst_byte_reader_init (&br, buffer + offset, length - offset);
3454           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3455                   qtdemux->cenc_aux_info_sizes,
3456                   qtdemux->cenc_aux_sample_count)) {
3457             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3458             g_free (qtdemux->cenc_aux_info_sizes);
3459             qtdemux->cenc_aux_info_sizes = NULL;
3460             goto fail;
3461           }
3462         }
3463       }
3464     }
3465
3466     tfdt_node =
3467         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3468         &tfdt_data);
3469     if (tfdt_node) {
3470       GstClockTime decode_time_ts;
3471
3472       /* We'll use decode_time to interpolate timestamps
3473        * in case the input timestamps are missing */
3474       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3475
3476       decode_time_ts = QTSTREAMTIME_TO_GSTTIME (stream, decode_time);
3477
3478       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3479           " (%" GST_TIME_FORMAT ")", decode_time,
3480           GST_TIME_ARGS (decode_time_ts));
3481
3482       /* Discard the fragment buffer timestamp info to avoid using it.
3483        * Rely on tfdt instead as it is more accurate than the timestamp
3484        * that is fetched from a manifest/playlist and is usually
3485        * less accurate. */
3486       qtdemux->fragment_start = -1;
3487     }
3488
3489     if (G_UNLIKELY (!stream)) {
3490       /* we lost track of offset, we'll need to regain it,
3491        * but can delay complaining until later or avoid doing so altogether */
3492       base_offset = -2;
3493       goto next;
3494     }
3495     if (G_UNLIKELY (base_offset < -1))
3496       goto lost_offset;
3497
3498     if (qtdemux->upstream_format_is_time)
3499       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3500
3501     /* Track Run node */
3502     trun_node =
3503         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3504         &trun_data);
3505     while (trun_node) {
3506       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3507           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3508           &running_offset, decode_time);
3509       /* iterate all siblings */
3510       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3511           &trun_data);
3512     }
3513     /* if no new base_offset provided for next traf,
3514      * base is end of current traf */
3515     base_offset = running_offset;
3516     running_offset = -1;
3517   next:
3518     /* iterate all siblings */
3519     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3520   }
3521
3522   /* parse any protection system info */
3523   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3524   while (pssh_node) {
3525     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3526     qtdemux_parse_pssh (qtdemux, pssh_node);
3527     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3528   }
3529
3530   g_node_destroy (moof_node);
3531   return TRUE;
3532
3533 missing_tfhd:
3534   {
3535     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3536     goto fail;
3537   }
3538 missing_mfhd:
3539   {
3540     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3541     goto fail;
3542   }
3543 lost_offset:
3544   {
3545     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3546     goto fail;
3547   }
3548 fail:
3549   {
3550     g_node_destroy (moof_node);
3551     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3552         (_("This file is corrupt and cannot be played.")), (NULL));
3553     return FALSE;
3554   }
3555 }
3556
3557 #if 0
3558 /* might be used if some day we actually use mfra & co
3559  * for random access to fragments,
3560  * but that will require quite some modifications and much less relying
3561  * on a sample array */
3562 #endif
3563
3564 static gboolean
3565 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3566 {
3567   QtDemuxStream *stream;
3568   guint32 ver_flags, track_id, len, num_entries, i;
3569   guint value_size, traf_size, trun_size, sample_size;
3570   guint64 time = 0, moof_offset = 0;
3571 #if 0
3572   GstBuffer *buf = NULL;
3573   GstFlowReturn ret;
3574 #endif
3575   GstByteReader tfra;
3576
3577   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3578
3579   if (!gst_byte_reader_skip (&tfra, 8))
3580     return FALSE;
3581
3582   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3583     return FALSE;
3584
3585   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3586       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3587       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3588     return FALSE;
3589
3590   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3591
3592   stream = qtdemux_find_stream (qtdemux, track_id);
3593   if (stream == NULL)
3594     goto unknown_trackid;
3595
3596   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3597   sample_size = (len & 3) + 1;
3598   trun_size = ((len & 12) >> 2) + 1;
3599   traf_size = ((len & 48) >> 4) + 1;
3600
3601   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3602       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3603
3604   if (num_entries == 0)
3605     goto no_samples;
3606
3607   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3608           value_size + value_size + traf_size + trun_size + sample_size))
3609     goto corrupt_file;
3610
3611   g_free (stream->ra_entries);
3612   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3613   stream->n_ra_entries = num_entries;
3614
3615   for (i = 0; i < num_entries; i++) {
3616     qt_atom_parser_get_offset (&tfra, value_size, &time);
3617     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3618     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3619     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3620     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3621
3622     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3623
3624     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3625         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3626
3627     stream->ra_entries[i].ts = time;
3628     stream->ra_entries[i].moof_offset = moof_offset;
3629
3630     /* don't want to go through the entire file and read all moofs at startup */
3631 #if 0
3632     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3633     if (ret != GST_FLOW_OK)
3634       goto corrupt_file;
3635     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3636         moof_offset, stream);
3637     gst_buffer_unref (buf);
3638 #endif
3639   }
3640
3641   check_update_duration (qtdemux, time);
3642
3643   return TRUE;
3644
3645 /* ERRORS */
3646 unknown_trackid:
3647   {
3648     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3649     return FALSE;
3650   }
3651 corrupt_file:
3652   {
3653     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3654     return FALSE;
3655   }
3656 no_samples:
3657   {
3658     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3659     return FALSE;
3660   }
3661 }
3662
3663 static gboolean
3664 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3665 {
3666   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3667   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3668   GstBuffer *mfro = NULL, *mfra = NULL;
3669   GstFlowReturn flow;
3670   gboolean ret = FALSE;
3671   GNode *mfra_node, *tfra_node;
3672   guint64 mfra_offset = 0;
3673   guint32 fourcc, mfra_size;
3674   gint64 len;
3675
3676   /* query upstream size in bytes */
3677   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3678     goto size_query_failed;
3679
3680   /* mfro box should be at the very end of the file */
3681   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3682   if (flow != GST_FLOW_OK)
3683     goto exit;
3684
3685   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3686
3687   fourcc = QT_FOURCC (mfro_map.data + 4);
3688   if (fourcc != FOURCC_mfro)
3689     goto exit;
3690
3691   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3692   if (mfro_map.size < 16)
3693     goto invalid_mfro_size;
3694
3695   mfra_size = QT_UINT32 (mfro_map.data + 12);
3696   if (mfra_size >= len)
3697     goto invalid_mfra_size;
3698
3699   mfra_offset = len - mfra_size;
3700
3701   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
3702       mfra_offset, mfra_size);
3703
3704   /* now get and parse mfra box */
3705   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
3706   if (flow != GST_FLOW_OK)
3707     goto broken_file;
3708
3709   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
3710
3711   mfra_node = g_node_new ((guint8 *) mfra_map.data);
3712   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
3713
3714   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
3715
3716   while (tfra_node) {
3717     qtdemux_parse_tfra (qtdemux, tfra_node);
3718     /* iterate all siblings */
3719     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
3720   }
3721   g_node_destroy (mfra_node);
3722
3723   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
3724   ret = TRUE;
3725
3726 exit:
3727
3728   if (mfro) {
3729     if (mfro_map.memory != NULL)
3730       gst_buffer_unmap (mfro, &mfro_map);
3731     gst_buffer_unref (mfro);
3732   }
3733   if (mfra) {
3734     if (mfra_map.memory != NULL)
3735       gst_buffer_unmap (mfra, &mfra_map);
3736     gst_buffer_unref (mfra);
3737   }
3738   return ret;
3739
3740 /* ERRORS */
3741 size_query_failed:
3742   {
3743     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
3744     goto exit;
3745   }
3746 invalid_mfro_size:
3747   {
3748     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
3749     goto exit;
3750   }
3751 invalid_mfra_size:
3752   {
3753     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
3754     goto exit;
3755   }
3756 broken_file:
3757   {
3758     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
3759     goto exit;
3760   }
3761 }
3762
3763 static guint64
3764 add_offset (guint64 offset, guint64 advance)
3765 {
3766   /* Avoid 64-bit overflow by clamping */
3767   if (offset > G_MAXUINT64 - advance)
3768     return G_MAXUINT64;
3769   return offset + advance;
3770 }
3771
3772 static GstFlowReturn
3773 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
3774 {
3775   guint64 length = 0;
3776   guint32 fourcc = 0;
3777   GstBuffer *buf = NULL;
3778   GstFlowReturn ret = GST_FLOW_OK;
3779   guint64 cur_offset = qtdemux->offset;
3780   GstMapInfo map;
3781
3782   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
3783   if (G_UNLIKELY (ret != GST_FLOW_OK))
3784     goto beach;
3785   gst_buffer_map (buf, &map, GST_MAP_READ);
3786   if (G_LIKELY (map.size >= 8))
3787     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
3788   gst_buffer_unmap (buf, &map);
3789   gst_buffer_unref (buf);
3790
3791   /* maybe we already got most we needed, so only consider this eof */
3792   if (G_UNLIKELY (length == 0)) {
3793     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
3794         (_("Invalid atom size.")),
3795         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
3796             GST_FOURCC_ARGS (fourcc)));
3797     ret = GST_FLOW_EOS;
3798     goto beach;
3799   }
3800
3801   switch (fourcc) {
3802     case FOURCC_moof:
3803       /* record for later parsing when needed */
3804       if (!qtdemux->moof_offset) {
3805         qtdemux->moof_offset = qtdemux->offset;
3806       }
3807       if (qtdemux_pull_mfro_mfra (qtdemux)) {
3808         /* FIXME */
3809       } else {
3810         qtdemux->offset += length;      /* skip moof and keep going */
3811       }
3812       if (qtdemux->got_moov) {
3813         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
3814         ret = GST_FLOW_EOS;
3815         goto beach;
3816       }
3817       break;
3818     case FOURCC_mdat:
3819     case FOURCC_free:
3820     case FOURCC_wide:
3821     case FOURCC_PICT:
3822     case FOURCC_pnot:
3823     {
3824       GST_LOG_OBJECT (qtdemux,
3825           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
3826           GST_FOURCC_ARGS (fourcc), cur_offset);
3827       qtdemux->offset = add_offset (qtdemux->offset, length);
3828       break;
3829     }
3830     case FOURCC_moov:
3831     {
3832       GstBuffer *moov = NULL;
3833
3834       if (qtdemux->got_moov) {
3835         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
3836         qtdemux->offset = add_offset (qtdemux->offset, length);
3837         goto beach;
3838       }
3839
3840       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
3841       if (ret != GST_FLOW_OK)
3842         goto beach;
3843       gst_buffer_map (moov, &map, GST_MAP_READ);
3844
3845       if (length != map.size) {
3846         /* Some files have a 'moov' atom at the end of the file which contains
3847          * a terminal 'free' atom where the body of the atom is missing.
3848          * Check for, and permit, this special case.
3849          */
3850         if (map.size >= 8) {
3851           guint8 *final_data = map.data + (map.size - 8);
3852           guint32 final_length = QT_UINT32 (final_data);
3853           guint32 final_fourcc = QT_FOURCC (final_data + 4);
3854
3855           if (final_fourcc == FOURCC_free
3856               && map.size + final_length - 8 == length) {
3857             /* Ok, we've found that special case. Allocate a new buffer with
3858              * that free atom actually present. */
3859             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
3860             gst_buffer_fill (newmoov, 0, map.data, map.size);
3861             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
3862             gst_buffer_unmap (moov, &map);
3863             gst_buffer_unref (moov);
3864             moov = newmoov;
3865             gst_buffer_map (moov, &map, GST_MAP_READ);
3866           }
3867         }
3868       }
3869
3870       if (length != map.size) {
3871         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3872             (_("This file is incomplete and cannot be played.")),
3873             ("We got less than expected (received %" G_GSIZE_FORMAT
3874                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
3875                 (guint) length, cur_offset));
3876         gst_buffer_unmap (moov, &map);
3877         gst_buffer_unref (moov);
3878         ret = GST_FLOW_ERROR;
3879         goto beach;
3880       }
3881       qtdemux->offset += length;
3882
3883       qtdemux_parse_moov (qtdemux, map.data, length);
3884       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
3885
3886       qtdemux_parse_tree (qtdemux);
3887       g_node_destroy (qtdemux->moov_node);
3888       gst_buffer_unmap (moov, &map);
3889       gst_buffer_unref (moov);
3890       qtdemux->moov_node = NULL;
3891       qtdemux->got_moov = TRUE;
3892
3893       break;
3894     }
3895     case FOURCC_ftyp:
3896     {
3897       GstBuffer *ftyp = NULL;
3898
3899       /* extract major brand; might come in handy for ISO vs QT issues */
3900       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
3901       if (ret != GST_FLOW_OK)
3902         goto beach;
3903       qtdemux->offset += length;
3904       gst_buffer_map (ftyp, &map, GST_MAP_READ);
3905       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
3906       gst_buffer_unmap (ftyp, &map);
3907       gst_buffer_unref (ftyp);
3908       break;
3909     }
3910     case FOURCC_uuid:
3911     {
3912       GstBuffer *uuid = NULL;
3913
3914       /* uuid are extension atoms */
3915       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
3916       if (ret != GST_FLOW_OK)
3917         goto beach;
3918       qtdemux->offset += length;
3919       gst_buffer_map (uuid, &map, GST_MAP_READ);
3920       qtdemux_parse_uuid (qtdemux, map.data, map.size);
3921       gst_buffer_unmap (uuid, &map);
3922       gst_buffer_unref (uuid);
3923       break;
3924     }
3925     case FOURCC_sidx:
3926     {
3927       GstBuffer *sidx = NULL;
3928       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
3929       if (ret != GST_FLOW_OK)
3930         goto beach;
3931       qtdemux->offset += length;
3932       gst_buffer_map (sidx, &map, GST_MAP_READ);
3933       qtdemux_parse_sidx (qtdemux, map.data, map.size);
3934       gst_buffer_unmap (sidx, &map);
3935       gst_buffer_unref (sidx);
3936       break;
3937     }
3938     default:
3939     {
3940       GstBuffer *unknown = NULL;
3941
3942       GST_LOG_OBJECT (qtdemux,
3943           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
3944           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
3945           cur_offset);
3946       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
3947       if (ret != GST_FLOW_OK)
3948         goto beach;
3949       gst_buffer_map (unknown, &map, GST_MAP_READ);
3950       GST_MEMDUMP ("Unknown tag", map.data, map.size);
3951       gst_buffer_unmap (unknown, &map);
3952       gst_buffer_unref (unknown);
3953       qtdemux->offset += length;
3954       break;
3955     }
3956   }
3957
3958 beach:
3959   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
3960     /* digested all data, show what we have */
3961     qtdemux_prepare_streams (qtdemux);
3962     ret = qtdemux_expose_streams (qtdemux);
3963
3964     qtdemux->state = QTDEMUX_STATE_MOVIE;
3965     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
3966         qtdemux->state);
3967     return ret;
3968   }
3969   return ret;
3970 }
3971
3972 /* Seeks to the previous keyframe of the indexed stream and
3973  * aligns other streams with respect to the keyframe timestamp
3974  * of indexed stream. Only called in case of Reverse Playback
3975  */
3976 static GstFlowReturn
3977 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
3978 {
3979   guint8 n = 0;
3980   guint32 seg_idx = 0, k_index = 0;
3981   guint32 ref_seg_idx, ref_k_index;
3982   GstClockTime k_pos = 0, last_stop = 0;
3983   QtDemuxSegment *seg = NULL;
3984   QtDemuxStream *ref_str = NULL;
3985   guint64 seg_media_start_mov;  /* segment media start time in mov format */
3986   guint64 target_ts;
3987
3988   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
3989    * and finally align all the other streams on that timestamp with their
3990    * respective keyframes */
3991   for (n = 0; n < qtdemux->n_streams; n++) {
3992     QtDemuxStream *str = qtdemux->streams[n];
3993
3994     /* No candidate yet, take the first stream */
3995     if (!ref_str) {
3996       ref_str = str;
3997       continue;
3998     }
3999
4000     /* So that stream has a segment, we prefer video streams */
4001     if (str->subtype == FOURCC_vide) {
4002       ref_str = str;
4003       break;
4004     }
4005   }
4006
4007   if (G_UNLIKELY (!ref_str)) {
4008     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4009     goto eos;
4010   }
4011
4012   if (G_UNLIKELY (!ref_str->from_sample)) {
4013     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4014     goto eos;
4015   }
4016
4017   /* So that stream has been playing from from_sample to to_sample. We will
4018    * get the timestamp of the previous sample and search for a keyframe before
4019    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4020   if (ref_str->subtype == FOURCC_vide) {
4021     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4022         ref_str->from_sample - 1);
4023   } else {
4024     if (ref_str->from_sample >= 10)
4025       k_index = ref_str->from_sample - 10;
4026     else
4027       k_index = 0;
4028   }
4029
4030   target_ts =
4031       ref_str->samples[k_index].timestamp +
4032       ref_str->samples[k_index].pts_offset;
4033
4034   /* get current segment for that stream */
4035   seg = &ref_str->segments[ref_str->segment_index];
4036   /* Use segment start in original timescale for comparisons */
4037   seg_media_start_mov = seg->trak_media_start;
4038
4039   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4040       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4041       k_index, target_ts, seg_media_start_mov,
4042       GST_TIME_ARGS (seg->media_start));
4043
4044   /* Crawl back through segments to find the one containing this I frame */
4045   while (target_ts < seg_media_start_mov) {
4046     GST_DEBUG_OBJECT (qtdemux,
4047         "keyframe position (sample %u) is out of segment %u " " target %"
4048         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4049         ref_str->segment_index, target_ts, seg_media_start_mov);
4050
4051     if (G_UNLIKELY (!ref_str->segment_index)) {
4052       /* Reached first segment, let's consider it's EOS */
4053       goto eos;
4054     }
4055     ref_str->segment_index--;
4056     seg = &ref_str->segments[ref_str->segment_index];
4057     /* Use segment start in original timescale for comparisons */
4058     seg_media_start_mov = seg->trak_media_start;
4059   }
4060   /* Calculate time position of the keyframe and where we should stop */
4061   k_pos =
4062       QTSTREAMTIME_TO_GSTTIME (ref_str,
4063       target_ts - seg->trak_media_start) + seg->time;
4064   last_stop =
4065       QTSTREAMTIME_TO_GSTTIME (ref_str,
4066       ref_str->samples[ref_str->from_sample].timestamp -
4067       seg->trak_media_start) + seg->time;
4068
4069   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4070       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4071       k_index, GST_TIME_ARGS (k_pos));
4072
4073   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4074   qtdemux->segment.position = last_stop;
4075   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4076       GST_TIME_ARGS (last_stop));
4077
4078   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4079     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4080     goto eos;
4081   }
4082
4083   ref_seg_idx = ref_str->segment_index;
4084   ref_k_index = k_index;
4085
4086   /* Align them all on this */
4087   for (n = 0; n < qtdemux->n_streams; n++) {
4088     guint32 index = 0;
4089     GstClockTime seg_time = 0;
4090     QtDemuxStream *str = qtdemux->streams[n];
4091
4092     /* aligning reference stream again might lead to backing up to yet another
4093      * keyframe (due to timestamp rounding issues),
4094      * potentially putting more load on downstream; so let's try to avoid */
4095     if (str == ref_str) {
4096       seg_idx = ref_seg_idx;
4097       seg = &str->segments[seg_idx];
4098       k_index = ref_k_index;
4099       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4100           "sample at index %d", n, ref_str->segment_index, k_index);
4101     } else {
4102       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4103       GST_DEBUG_OBJECT (qtdemux,
4104           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4105           seg_idx, GST_TIME_ARGS (k_pos));
4106
4107       /* get segment and time in the segment */
4108       seg = &str->segments[seg_idx];
4109       seg_time = k_pos - seg->time;
4110
4111       /* get the media time in the segment.
4112        * No adjustment for empty "filler" segments */
4113       if (seg->media_start != GST_CLOCK_TIME_NONE)
4114         seg_time += seg->media_start;
4115
4116       /* get the index of the sample with media time */
4117       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4118       GST_DEBUG_OBJECT (qtdemux,
4119           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4120           GST_TIME_ARGS (seg_time), index);
4121
4122       /* find previous keyframe */
4123       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4124     }
4125
4126     /* Remember until where we want to go */
4127     str->to_sample = str->from_sample - 1;
4128     /* Define our time position */
4129     target_ts =
4130         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4131     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4132     if (seg->media_start != GST_CLOCK_TIME_NONE)
4133       str->time_position -= seg->media_start;
4134
4135     /* Now seek back in time */
4136     gst_qtdemux_move_stream (qtdemux, str, k_index);
4137     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4138         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4139         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4140   }
4141
4142   return GST_FLOW_OK;
4143
4144 eos:
4145   return GST_FLOW_EOS;
4146 }
4147
4148 /* activate the given segment number @seg_idx of @stream at time @offset.
4149  * @offset is an absolute global position over all the segments.
4150  *
4151  * This will push out a NEWSEGMENT event with the right values and
4152  * position the stream index to the first decodable sample before
4153  * @offset.
4154  */
4155 static gboolean
4156 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4157     guint32 seg_idx, GstClockTime offset)
4158 {
4159   GstEvent *event;
4160   QtDemuxSegment *segment;
4161   guint32 index, kf_index;
4162   GstClockTime seg_time;
4163   GstClockTime start, stop, time;
4164   gdouble rate;
4165
4166   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4167       seg_idx, GST_TIME_ARGS (offset));
4168
4169   /* update the current segment */
4170   stream->segment_index = seg_idx;
4171
4172   /* get the segment */
4173   segment = &stream->segments[seg_idx];
4174
4175   if (G_UNLIKELY (offset < segment->time)) {
4176     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4177         GST_TIME_ARGS (segment->time));
4178     return FALSE;
4179   }
4180
4181   /* segment lies beyond total indicated duration */
4182   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4183           segment->time > qtdemux->segment.duration)) {
4184     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4185         " < segment->time %" GST_TIME_FORMAT,
4186         GST_TIME_ARGS (qtdemux->segment.duration),
4187         GST_TIME_ARGS (segment->time));
4188     return FALSE;
4189   }
4190
4191   /* get time in this segment */
4192   seg_time = offset - segment->time;
4193
4194   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4195       GST_TIME_ARGS (seg_time));
4196
4197   if (G_UNLIKELY (seg_time > segment->duration)) {
4198     GST_LOG_OBJECT (stream->pad,
4199         "seg_time > segment->duration %" GST_TIME_FORMAT,
4200         GST_TIME_ARGS (segment->duration));
4201     seg_time = segment->duration;
4202   }
4203
4204   /* qtdemux->segment.stop is in outside-time-realm, whereas
4205    * segment->media_stop is in track-time-realm.
4206    *
4207    * In order to compare the two, we need to bring segment.stop
4208    * into the track-time-realm */
4209
4210   stop = qtdemux->segment.stop;
4211   if (stop == GST_CLOCK_TIME_NONE)
4212     stop = qtdemux->segment.duration;
4213   if (stop == GST_CLOCK_TIME_NONE)
4214     stop = segment->media_stop;
4215   else
4216     stop =
4217         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4218
4219   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4220     start = segment->time + seg_time;
4221     time = offset;
4222     stop = start - seg_time + segment->duration;
4223   } else if (qtdemux->segment.rate >= 0) {
4224     start = MIN (segment->media_start + seg_time, stop);
4225     time = offset;
4226   } else {
4227     if (segment->media_start >= qtdemux->segment.start) {
4228       time = segment->time;
4229     } else {
4230       time = segment->time + (qtdemux->segment.start - segment->media_start);
4231     }
4232
4233     start = MAX (segment->media_start, qtdemux->segment.start);
4234     stop = MIN (segment->media_start + seg_time, stop);
4235   }
4236
4237   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4238       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4239       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4240
4241   /* combine global rate with that of the segment */
4242   rate = segment->rate * qtdemux->segment.rate;
4243
4244   /* Copy flags from main segment */
4245   stream->segment.flags = qtdemux->segment.flags;
4246
4247   /* update the segment values used for clipping */
4248   stream->segment.offset = qtdemux->segment.offset;
4249   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4250   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4251   stream->segment.rate = rate;
4252   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4253       stream->cslg_shift);
4254   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4255       stream->cslg_shift);
4256   stream->segment.time = time;
4257   stream->segment.position = stream->segment.start;
4258
4259   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4260       &stream->segment);
4261
4262   /* now prepare and send the segment */
4263   if (stream->pad) {
4264     event = gst_event_new_segment (&stream->segment);
4265     if (stream->segment_seqnum) {
4266       gst_event_set_seqnum (event, stream->segment_seqnum);
4267     }
4268     gst_pad_push_event (stream->pad, event);
4269     /* assume we can send more data now */
4270     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4271     /* clear to send tags on this pad now */
4272     gst_qtdemux_push_tags (qtdemux, stream);
4273   }
4274
4275   /* in the fragmented case, we pick a fragment that starts before our
4276    * desired position and rely on downstream to wait for a keyframe
4277    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4278    * tfra entries tells us which trun/sample the key unit is in, but we don't
4279    * make use of this additional information at the moment) */
4280   if (qtdemux->fragmented) {
4281     stream->to_sample = G_MAXUINT32;
4282     return TRUE;
4283   }
4284
4285   /* We don't need to look for a sample in push-based */
4286   if (!qtdemux->pullbased)
4287     return TRUE;
4288
4289   /* and move to the keyframe before the indicated media time of the
4290    * segment */
4291   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4292     if (qtdemux->segment.rate >= 0) {
4293       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4294       stream->to_sample = G_MAXUINT32;
4295       GST_DEBUG_OBJECT (stream->pad,
4296           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4297           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4298           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4299     } else {
4300       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4301       stream->to_sample = index;
4302       GST_DEBUG_OBJECT (stream->pad,
4303           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4304           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4305           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4306     }
4307   } else {
4308     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4309         "this is an empty segment");
4310     return TRUE;
4311   }
4312
4313   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4314    * encountered an error and printed a message so we return appropriately */
4315   if (index == -1)
4316     return FALSE;
4317
4318   /* we're at the right spot */
4319   if (index == stream->sample_index) {
4320     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4321     return TRUE;
4322   }
4323
4324   /* find keyframe of the target index */
4325   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4326
4327 /* *INDENT-OFF* */
4328 /* indent does stupid stuff with stream->samples[].timestamp */
4329
4330   /* if we move forwards, we don't have to go back to the previous
4331    * keyframe since we already sent that. We can also just jump to
4332    * the keyframe right before the target index if there is one. */
4333   if (index > stream->sample_index) {
4334     /* moving forwards check if we move past a keyframe */
4335     if (kf_index > stream->sample_index) {
4336       GST_DEBUG_OBJECT (stream->pad,
4337            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4338            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4339            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4340       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4341     } else {
4342       GST_DEBUG_OBJECT (stream->pad,
4343           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4344           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4345           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4346     }
4347   } else {
4348     GST_DEBUG_OBJECT (stream->pad,
4349         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4350         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4351         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4352     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4353   }
4354
4355 /* *INDENT-ON* */
4356
4357   return TRUE;
4358 }
4359
4360 /* prepare to get the current sample of @stream, getting essential values.
4361  *
4362  * This function will also prepare and send the segment when needed.
4363  *
4364  * Return FALSE if the stream is EOS.
4365  *
4366  * PULL-BASED
4367  */
4368 static gboolean
4369 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4370     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4371     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4372     gboolean * keyframe)
4373 {
4374   QtDemuxSample *sample;
4375   GstClockTime time_position;
4376   guint32 seg_idx;
4377
4378   g_return_val_if_fail (stream != NULL, FALSE);
4379
4380   time_position = stream->time_position;
4381   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4382     goto eos;
4383
4384   seg_idx = stream->segment_index;
4385   if (G_UNLIKELY (seg_idx == -1)) {
4386     /* find segment corresponding to time_position if we are looking
4387      * for a segment. */
4388     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4389   }
4390
4391   /* different segment, activate it, sample_index will be set. */
4392   if (G_UNLIKELY (stream->segment_index != seg_idx))
4393     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4394
4395   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4396                   segment_index]))) {
4397     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4398
4399     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4400         " prepare empty sample");
4401
4402     *empty = TRUE;
4403     *pts = *dts = time_position;
4404     *duration = seg->duration - (time_position - seg->time);
4405
4406     return TRUE;
4407   }
4408
4409   *empty = FALSE;
4410
4411   if (stream->sample_index == -1)
4412     stream->sample_index = 0;
4413
4414   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4415       stream->sample_index, stream->n_samples);
4416
4417   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4418     if (!qtdemux->fragmented)
4419       goto eos;
4420
4421     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4422     do {
4423       GstFlowReturn flow;
4424
4425       GST_OBJECT_LOCK (qtdemux);
4426       flow = qtdemux_add_fragmented_samples (qtdemux);
4427       GST_OBJECT_UNLOCK (qtdemux);
4428
4429       if (flow != GST_FLOW_OK)
4430         goto eos;
4431     }
4432     while (stream->sample_index >= stream->n_samples);
4433   }
4434
4435   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4436     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4437         stream->sample_index);
4438     return FALSE;
4439   }
4440
4441   /* now get the info for the sample we're at */
4442   sample = &stream->samples[stream->sample_index];
4443
4444   *dts = QTSAMPLE_DTS (stream, sample);
4445   *pts = QTSAMPLE_PTS (stream, sample);
4446   *offset = sample->offset;
4447   *size = sample->size;
4448   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4449   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4450
4451   return TRUE;
4452
4453   /* special cases */
4454 eos:
4455   {
4456     stream->time_position = GST_CLOCK_TIME_NONE;
4457     return FALSE;
4458   }
4459 }
4460
4461 /* move to the next sample in @stream.
4462  *
4463  * Moves to the next segment when needed.
4464  */
4465 static void
4466 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4467 {
4468   QtDemuxSample *sample;
4469   QtDemuxSegment *segment;
4470
4471   /* get current segment */
4472   segment = &stream->segments[stream->segment_index];
4473
4474   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4475     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4476     goto next_segment;
4477   }
4478
4479   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4480     /* Mark the stream as EOS */
4481     GST_DEBUG_OBJECT (qtdemux,
4482         "reached max allowed sample %u, mark EOS", stream->to_sample);
4483     stream->time_position = GST_CLOCK_TIME_NONE;
4484     return;
4485   }
4486
4487   /* move to next sample */
4488   stream->sample_index++;
4489   stream->offset_in_sample = 0;
4490
4491   /* reached the last sample, we need the next segment */
4492   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4493     goto next_segment;
4494
4495   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4496     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4497         stream->sample_index);
4498     return;
4499   }
4500
4501   /* get next sample */
4502   sample = &stream->samples[stream->sample_index];
4503
4504   /* see if we are past the segment */
4505   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4506     goto next_segment;
4507
4508   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4509     /* inside the segment, update time_position, looks very familiar to
4510      * GStreamer segments, doesn't it? */
4511     stream->time_position =
4512         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4513   } else {
4514     /* not yet in segment, time does not yet increment. This means
4515      * that we are still prerolling keyframes to the decoder so it can
4516      * decode the first sample of the segment. */
4517     stream->time_position = segment->time;
4518   }
4519   return;
4520
4521   /* move to the next segment */
4522 next_segment:
4523   {
4524     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4525
4526     if (stream->segment_index == stream->n_segments - 1) {
4527       /* are we at the end of the last segment, we're EOS */
4528       stream->time_position = GST_CLOCK_TIME_NONE;
4529     } else {
4530       /* else we're only at the end of the current segment */
4531       stream->time_position = segment->stop_time;
4532     }
4533     /* make sure we select a new segment */
4534
4535     /* accumulate previous segments */
4536     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4537       stream->accumulated_base +=
4538           (stream->segment.stop -
4539           stream->segment.start) / ABS (stream->segment.rate);
4540
4541     stream->segment_index = -1;
4542   }
4543 }
4544
4545 static void
4546 gst_qtdemux_sync_streams (GstQTDemux * demux)
4547 {
4548   gint i;
4549
4550   if (demux->n_streams <= 1)
4551     return;
4552
4553   for (i = 0; i < demux->n_streams; i++) {
4554     QtDemuxStream *stream;
4555     GstClockTime end_time;
4556
4557     stream = demux->streams[i];
4558
4559     if (!stream->pad)
4560       continue;
4561
4562     /* TODO advance time on subtitle streams here, if any some day */
4563
4564     /* some clips/trailers may have unbalanced streams at the end,
4565      * so send EOS on shorter stream to prevent stalling others */
4566
4567     /* do not mess with EOS if SEGMENT seeking */
4568     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4569       continue;
4570
4571     if (demux->pullbased) {
4572       /* loop mode is sample time based */
4573       if (!STREAM_IS_EOS (stream))
4574         continue;
4575     } else {
4576       /* push mode is byte position based */
4577       if (stream->n_samples &&
4578           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4579         continue;
4580     }
4581
4582     if (stream->sent_eos)
4583       continue;
4584
4585     /* only act if some gap */
4586     end_time = stream->segments[stream->n_segments - 1].stop_time;
4587     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4588         ", stream end: %" GST_TIME_FORMAT,
4589         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4590     if (GST_CLOCK_TIME_IS_VALID (end_time)
4591         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4592       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4593           GST_PAD_NAME (stream->pad));
4594       stream->sent_eos = TRUE;
4595       gst_pad_push_event (stream->pad, gst_event_new_eos ());
4596     }
4597   }
4598 }
4599
4600 /* EOS and NOT_LINKED need to be combined. This means that we return:
4601  *
4602  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4603  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4604  */
4605 static GstFlowReturn
4606 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4607     GstFlowReturn ret)
4608 {
4609   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4610
4611   if (stream->pad)
4612     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4613         ret);
4614   else
4615     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4616
4617   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4618   return ret;
4619 }
4620
4621 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4622  * completely clipped
4623  *
4624  * Should be used only with raw buffers */
4625 static GstBuffer *
4626 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4627     GstBuffer * buf)
4628 {
4629   guint64 start, stop, cstart, cstop, diff;
4630   GstClockTime pts, duration;
4631   gsize size, osize;
4632   gint num_rate, denom_rate;
4633   gint frame_size;
4634   gboolean clip_data;
4635   guint offset;
4636
4637   osize = size = gst_buffer_get_size (buf);
4638   offset = 0;
4639
4640   /* depending on the type, setup the clip parameters */
4641   if (stream->subtype == FOURCC_soun) {
4642     frame_size = stream->bytes_per_frame;
4643     num_rate = GST_SECOND;
4644     denom_rate = (gint) stream->rate;
4645     clip_data = TRUE;
4646   } else if (stream->subtype == FOURCC_vide) {
4647     frame_size = size;
4648     num_rate = stream->fps_n;
4649     denom_rate = stream->fps_d;
4650     clip_data = FALSE;
4651   } else
4652     goto wrong_type;
4653
4654   if (frame_size <= 0)
4655     goto bad_frame_size;
4656
4657   /* we can only clip if we have a valid pts */
4658   pts = GST_BUFFER_PTS (buf);
4659   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
4660     goto no_pts;
4661
4662   duration = GST_BUFFER_DURATION (buf);
4663
4664   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
4665     duration =
4666         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
4667   }
4668
4669   start = pts;
4670   stop = start + duration;
4671
4672   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
4673               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
4674     goto clipped;
4675
4676   /* see if some clipping happened */
4677   diff = cstart - start;
4678   if (diff > 0) {
4679     pts += diff;
4680     duration -= diff;
4681
4682     if (clip_data) {
4683       /* bring clipped time to samples and to bytes */
4684       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4685       diff *= frame_size;
4686
4687       GST_DEBUG_OBJECT (qtdemux,
4688           "clipping start to %" GST_TIME_FORMAT " %"
4689           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
4690
4691       offset = diff;
4692       size -= diff;
4693     }
4694   }
4695   diff = stop - cstop;
4696   if (diff > 0) {
4697     duration -= diff;
4698
4699     if (clip_data) {
4700       /* bring clipped time to samples and then to bytes */
4701       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4702       diff *= frame_size;
4703       GST_DEBUG_OBJECT (qtdemux,
4704           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
4705           " bytes", GST_TIME_ARGS (cstop), diff);
4706       size -= diff;
4707     }
4708   }
4709
4710   if (offset != 0 || size != osize)
4711     gst_buffer_resize (buf, offset, size);
4712
4713   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
4714   GST_BUFFER_PTS (buf) = pts;
4715   GST_BUFFER_DURATION (buf) = duration;
4716
4717   return buf;
4718
4719   /* dropped buffer */
4720 wrong_type:
4721   {
4722     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
4723     return buf;
4724   }
4725 bad_frame_size:
4726   {
4727     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
4728     return buf;
4729   }
4730 no_pts:
4731   {
4732     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
4733     return buf;
4734   }
4735 clipped:
4736   {
4737     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
4738     gst_buffer_unref (buf);
4739     return NULL;
4740   }
4741 }
4742
4743 /* the input buffer metadata must be writable,
4744  * but time/duration etc not yet set and need not be preserved */
4745 static GstBuffer *
4746 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4747     GstBuffer * buf)
4748 {
4749   GstMapInfo map;
4750   guint nsize = 0;
4751   gchar *str;
4752
4753   /* not many cases for now */
4754   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
4755     /* send a one time dvd clut event */
4756     if (stream->pending_event && stream->pad)
4757       gst_pad_push_event (stream->pad, stream->pending_event);
4758     stream->pending_event = NULL;
4759   }
4760
4761   if (G_UNLIKELY (stream->subtype != FOURCC_text
4762           && stream->subtype != FOURCC_sbtl &&
4763           stream->subtype != FOURCC_subp)) {
4764     return buf;
4765   }
4766
4767   gst_buffer_map (buf, &map, GST_MAP_READ);
4768
4769   /* empty buffer is sent to terminate previous subtitle */
4770   if (map.size <= 2) {
4771     gst_buffer_unmap (buf, &map);
4772     gst_buffer_unref (buf);
4773     return NULL;
4774   }
4775   if (stream->subtype == FOURCC_subp) {
4776     /* That's all the processing needed for subpictures */
4777     gst_buffer_unmap (buf, &map);
4778     return buf;
4779   }
4780
4781   nsize = GST_READ_UINT16_BE (map.data);
4782   nsize = MIN (nsize, map.size - 2);
4783
4784   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
4785       nsize, map.size);
4786
4787   /* takes care of UTF-8 validation or UTF-16 recognition,
4788    * no other encoding expected */
4789   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
4790   gst_buffer_unmap (buf, &map);
4791   if (str) {
4792     gst_buffer_unref (buf);
4793     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
4794   } else {
4795     /* this should not really happen unless the subtitle is corrupted */
4796     gst_buffer_unref (buf);
4797     buf = NULL;
4798   }
4799
4800   /* FIXME ? convert optional subsequent style info to markup */
4801
4802   return buf;
4803 }
4804
4805 /* Sets a buffer's attributes properly and pushes it downstream.
4806  * Also checks for additional actions and custom processing that may
4807  * need to be done first.
4808  */
4809 static GstFlowReturn
4810 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
4811     QtDemuxStream * stream, GstBuffer * buf,
4812     GstClockTime dts, GstClockTime pts, GstClockTime duration,
4813     gboolean keyframe, GstClockTime position, guint64 byte_position)
4814 {
4815   GstFlowReturn ret = GST_FLOW_OK;
4816
4817   /* offset the timestamps according to the edit list */
4818
4819   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
4820     gchar *url;
4821     GstMapInfo map;
4822
4823     gst_buffer_map (buf, &map, GST_MAP_READ);
4824     url = g_strndup ((gchar *) map.data, map.size);
4825     gst_buffer_unmap (buf, &map);
4826     if (url != NULL && strlen (url) != 0) {
4827       /* we have RTSP redirect now */
4828       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
4829           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
4830               gst_structure_new ("redirect",
4831                   "new-location", G_TYPE_STRING, url, NULL)));
4832       qtdemux->posted_redirect = TRUE;
4833     } else {
4834       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
4835           "posting");
4836     }
4837     g_free (url);
4838   }
4839
4840   /* position reporting */
4841   if (qtdemux->segment.rate >= 0) {
4842     qtdemux->segment.position = position;
4843     gst_qtdemux_sync_streams (qtdemux);
4844   }
4845
4846   if (G_UNLIKELY (!stream->pad)) {
4847     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
4848     gst_buffer_unref (buf);
4849     goto exit;
4850   }
4851
4852   /* send out pending buffers */
4853   while (stream->buffers) {
4854     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
4855
4856     if (G_UNLIKELY (stream->discont)) {
4857       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4858       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
4859       stream->discont = FALSE;
4860     } else {
4861       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4862     }
4863
4864     gst_pad_push (stream->pad, buffer);
4865
4866     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
4867   }
4868
4869   /* we're going to modify the metadata */
4870   buf = gst_buffer_make_writable (buf);
4871
4872   if (G_UNLIKELY (stream->need_process))
4873     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
4874
4875   if (!buf) {
4876     goto exit;
4877   }
4878
4879   GST_BUFFER_DTS (buf) = dts;
4880   GST_BUFFER_PTS (buf) = pts;
4881   GST_BUFFER_DURATION (buf) = duration;
4882   GST_BUFFER_OFFSET (buf) = -1;
4883   GST_BUFFER_OFFSET_END (buf) = -1;
4884
4885   if (G_UNLIKELY (stream->rgb8_palette))
4886     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
4887
4888   if (G_UNLIKELY (stream->padding)) {
4889     gst_buffer_resize (buf, stream->padding, -1);
4890   }
4891 #if 0
4892   if (G_UNLIKELY (qtdemux->element_index)) {
4893     GstClockTime stream_time;
4894
4895     stream_time =
4896         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
4897         timestamp);
4898     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
4899       GST_LOG_OBJECT (qtdemux,
4900           "adding association %" GST_TIME_FORMAT "-> %"
4901           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
4902       gst_index_add_association (qtdemux->element_index,
4903           qtdemux->index_id,
4904           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
4905           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
4906           GST_FORMAT_BYTES, byte_position, NULL);
4907     }
4908   }
4909 #endif
4910
4911   if (stream->need_clip)
4912     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
4913
4914   if (G_UNLIKELY (buf == NULL))
4915     goto exit;
4916
4917   if (G_UNLIKELY (stream->discont)) {
4918     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4919     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
4920     stream->discont = FALSE;
4921   } else {
4922     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4923   }
4924
4925   if (!keyframe) {
4926     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
4927     stream->on_keyframe = FALSE;
4928   } else {
4929     stream->on_keyframe = TRUE;
4930   }
4931
4932
4933   GST_LOG_OBJECT (qtdemux,
4934       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
4935       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
4936       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
4937       GST_PAD_NAME (stream->pad));
4938
4939   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
4940     GstStructure *crypto_info;
4941     QtDemuxCencSampleSetInfo *info =
4942         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4943     gint index;
4944     GstEvent *event;
4945
4946     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
4947       gst_pad_push_event (stream->pad, event);
4948     }
4949
4950     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
4951     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
4952       /* steal structure from array */
4953       crypto_info = g_ptr_array_index (info->crypto_info, index);
4954       g_ptr_array_index (info->crypto_info, index) = NULL;
4955       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
4956       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
4957         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
4958     }
4959   }
4960
4961   ret = gst_pad_push (stream->pad, buf);
4962
4963   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
4964     /* mark position in stream, we'll need this to know when to send GAP event */
4965     stream->segment.position = pts + duration;
4966   }
4967
4968 exit:
4969   return ret;
4970 }
4971
4972 static const QtDemuxRandomAccessEntry *
4973 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4974     GstClockTime pos, gboolean after)
4975 {
4976   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
4977   guint n_entries = stream->n_ra_entries;
4978   guint i;
4979
4980   /* we assume the table is sorted */
4981   for (i = 0; i < n_entries; ++i) {
4982     if (entries[i].ts > pos)
4983       break;
4984   }
4985
4986   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
4987    * probably okay to assume that the index lists the very first fragment */
4988   if (i == 0)
4989     return &entries[0];
4990
4991   if (after)
4992     return &entries[i];
4993   else
4994     return &entries[i - 1];
4995 }
4996
4997 static gboolean
4998 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
4999 {
5000   const QtDemuxRandomAccessEntry *best_entry = NULL;
5001   guint i;
5002
5003   GST_OBJECT_LOCK (qtdemux);
5004
5005   g_assert (qtdemux->n_streams > 0);
5006
5007   for (i = 0; i < qtdemux->n_streams; i++) {
5008     const QtDemuxRandomAccessEntry *entry;
5009     QtDemuxStream *stream;
5010     gboolean is_audio_or_video;
5011
5012     stream = qtdemux->streams[i];
5013
5014     g_free (stream->samples);
5015     stream->samples = NULL;
5016     stream->n_samples = 0;
5017     stream->stbl_index = -1;    /* no samples have yet been parsed */
5018     stream->sample_index = -1;
5019
5020     if (stream->ra_entries == NULL)
5021       continue;
5022
5023     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5024       is_audio_or_video = TRUE;
5025     else
5026       is_audio_or_video = FALSE;
5027
5028     entry =
5029         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5030         stream->time_position, !is_audio_or_video);
5031
5032     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5033         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5034
5035     stream->pending_seek = entry;
5036
5037     /* decide position to jump to just based on audio/video tracks, not subs */
5038     if (!is_audio_or_video)
5039       continue;
5040
5041     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5042       best_entry = entry;
5043   }
5044
5045   if (best_entry == NULL) {
5046     GST_OBJECT_UNLOCK (qtdemux);
5047     return FALSE;
5048   }
5049
5050   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5051       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5052       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5053       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5054
5055   qtdemux->moof_offset = best_entry->moof_offset;
5056
5057   qtdemux_add_fragmented_samples (qtdemux);
5058
5059   GST_OBJECT_UNLOCK (qtdemux);
5060   return TRUE;
5061 }
5062
5063 static GstFlowReturn
5064 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5065 {
5066   GstFlowReturn ret = GST_FLOW_OK;
5067   GstBuffer *buf = NULL;
5068   QtDemuxStream *stream;
5069   GstClockTime min_time;
5070   guint64 offset = 0;
5071   GstClockTime dts = GST_CLOCK_TIME_NONE;
5072   GstClockTime pts = GST_CLOCK_TIME_NONE;
5073   GstClockTime duration = 0;
5074   gboolean keyframe = FALSE;
5075   guint sample_size = 0;
5076   gboolean empty = 0;
5077   guint size;
5078   gint index;
5079   gint i;
5080
5081   gst_qtdemux_push_pending_newsegment (qtdemux);
5082
5083   if (qtdemux->fragmented_seek_pending) {
5084     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5085     gst_qtdemux_do_fragmented_seek (qtdemux);
5086     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5087     qtdemux->fragmented_seek_pending = FALSE;
5088   }
5089
5090   /* Figure out the next stream sample to output, min_time is expressed in
5091    * global time and runs over the edit list segments. */
5092   min_time = G_MAXUINT64;
5093   index = -1;
5094   for (i = 0; i < qtdemux->n_streams; i++) {
5095     GstClockTime position;
5096
5097     stream = qtdemux->streams[i];
5098     position = stream->time_position;
5099
5100     /* position of -1 is EOS */
5101     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5102       min_time = position;
5103       index = i;
5104     }
5105   }
5106   /* all are EOS */
5107   if (G_UNLIKELY (index == -1)) {
5108     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5109     goto eos;
5110   }
5111
5112   /* check for segment end */
5113   if (G_UNLIKELY (qtdemux->segment.stop != -1
5114           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5115               || (qtdemux->segment.rate < 0
5116                   && qtdemux->segment.start > min_time))
5117           && qtdemux->streams[index]->on_keyframe)) {
5118     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5119     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5120     goto eos_stream;
5121   }
5122
5123   /* gap events for subtitle streams */
5124   for (i = 0; i < qtdemux->n_streams; i++) {
5125     stream = qtdemux->streams[i];
5126     if (stream->pad && (stream->subtype == FOURCC_subp
5127             || stream->subtype == FOURCC_text
5128             || stream->subtype == FOURCC_sbtl)) {
5129       /* send one second gap events until the stream catches up */
5130       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5131       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5132           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5133           stream->segment.position + GST_SECOND < min_time) {
5134         GstEvent *gap =
5135             gst_event_new_gap (stream->segment.position, GST_SECOND);
5136         gst_pad_push_event (stream->pad, gap);
5137         stream->segment.position += GST_SECOND;
5138       }
5139     }
5140   }
5141
5142   stream = qtdemux->streams[index];
5143   if (stream->new_caps) {
5144     gst_qtdemux_configure_stream (qtdemux, stream);
5145     qtdemux_do_allocation (qtdemux, stream);
5146   }
5147
5148   /* fetch info for the current sample of this stream */
5149   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5150               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5151     goto eos_stream;
5152
5153   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5154   if (G_UNLIKELY (qtdemux->
5155           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5156     if (stream->subtype == FOURCC_vide && !keyframe) {
5157       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5158       goto next;
5159     }
5160   }
5161
5162   GST_DEBUG_OBJECT (qtdemux,
5163       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5164       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5165       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5166       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5167
5168   if (G_UNLIKELY (empty)) {
5169     /* empty segment, push a gap and move to the next one */
5170     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5171     stream->segment.position = pts + duration;
5172     goto next;
5173   }
5174
5175   /* hmm, empty sample, skip and move to next sample */
5176   if (G_UNLIKELY (sample_size <= 0))
5177     goto next;
5178
5179   /* last pushed sample was out of boundary, goto next sample */
5180   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5181     goto next;
5182
5183   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5184     size = sample_size;
5185   } else {
5186     GST_DEBUG_OBJECT (qtdemux,
5187         "size %d larger than stream max_buffer_size %d, trimming",
5188         sample_size, stream->max_buffer_size);
5189     size =
5190         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5191   }
5192
5193   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5194       offset);
5195
5196   if (stream->use_allocator) {
5197     /* if we have a per-stream allocator, use it */
5198     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5199   }
5200
5201   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5202       size, &buf);
5203   if (G_UNLIKELY (ret != GST_FLOW_OK))
5204     goto beach;
5205
5206   if (size != sample_size) {
5207     pts += gst_util_uint64_scale_int (GST_SECOND,
5208         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5209     dts += gst_util_uint64_scale_int (GST_SECOND,
5210         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5211     duration = gst_util_uint64_scale_int (GST_SECOND,
5212         size / stream->bytes_per_frame, stream->timescale);
5213   }
5214
5215   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5216       dts, pts, duration, keyframe, min_time, offset);
5217
5218   if (size != sample_size) {
5219     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5220     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5221
5222     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5223         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5224     if (time_position >= segment->media_start) {
5225       /* inside the segment, update time_position, looks very familiar to
5226        * GStreamer segments, doesn't it? */
5227       stream->time_position = (time_position - segment->media_start) +
5228           segment->time;
5229     } else {
5230       /* not yet in segment, time does not yet increment. This means
5231        * that we are still prerolling keyframes to the decoder so it can
5232        * decode the first sample of the segment. */
5233       stream->time_position = segment->time;
5234     }
5235   }
5236
5237   /* combine flows */
5238   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5239   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5240    * we have no more data for the pad to push */
5241   if (ret == GST_FLOW_EOS)
5242     ret = GST_FLOW_OK;
5243
5244   stream->offset_in_sample += size;
5245   if (stream->offset_in_sample >= sample_size) {
5246     gst_qtdemux_advance_sample (qtdemux, stream);
5247   }
5248   goto beach;
5249
5250 next:
5251   gst_qtdemux_advance_sample (qtdemux, stream);
5252
5253 beach:
5254   return ret;
5255
5256   /* special cases */
5257 eos:
5258   {
5259     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5260     ret = GST_FLOW_EOS;
5261     goto beach;
5262   }
5263 eos_stream:
5264   {
5265     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5266     /* EOS will be raised if all are EOS */
5267     ret = GST_FLOW_OK;
5268     goto beach;
5269   }
5270 }
5271
5272 static void
5273 gst_qtdemux_loop (GstPad * pad)
5274 {
5275   GstQTDemux *qtdemux;
5276   guint64 cur_offset;
5277   GstFlowReturn ret;
5278
5279   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5280
5281   cur_offset = qtdemux->offset;
5282   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
5283       cur_offset, qtdemux->state);
5284
5285   switch (qtdemux->state) {
5286     case QTDEMUX_STATE_INITIAL:
5287     case QTDEMUX_STATE_HEADER:
5288       ret = gst_qtdemux_loop_state_header (qtdemux);
5289       break;
5290     case QTDEMUX_STATE_MOVIE:
5291       ret = gst_qtdemux_loop_state_movie (qtdemux);
5292       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5293         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5294       }
5295       break;
5296     default:
5297       /* ouch */
5298       goto invalid_state;
5299   }
5300
5301   /* if something went wrong, pause */
5302   if (ret != GST_FLOW_OK)
5303     goto pause;
5304
5305 done:
5306   gst_object_unref (qtdemux);
5307   return;
5308
5309   /* ERRORS */
5310 invalid_state:
5311   {
5312     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5313         (NULL), ("streaming stopped, invalid state"));
5314     gst_pad_pause_task (pad);
5315     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5316     goto done;
5317   }
5318 pause:
5319   {
5320     const gchar *reason = gst_flow_get_name (ret);
5321
5322     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5323
5324     gst_pad_pause_task (pad);
5325
5326     /* fatal errors need special actions */
5327     /* check EOS */
5328     if (ret == GST_FLOW_EOS) {
5329       if (qtdemux->n_streams == 0) {
5330         /* we have no streams, post an error */
5331         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5332       }
5333       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5334         gint64 stop;
5335
5336         if ((stop = qtdemux->segment.stop) == -1)
5337           stop = qtdemux->segment.duration;
5338
5339         if (qtdemux->segment.rate >= 0) {
5340           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5341           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5342               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5343                   GST_FORMAT_TIME, stop));
5344           gst_qtdemux_push_event (qtdemux,
5345               gst_event_new_segment_done (GST_FORMAT_TIME, stop));
5346         } else {
5347           /*  For Reverse Playback */
5348           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5349           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5350               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5351                   GST_FORMAT_TIME, qtdemux->segment.start));
5352           gst_qtdemux_push_event (qtdemux,
5353               gst_event_new_segment_done (GST_FORMAT_TIME,
5354                   qtdemux->segment.start));
5355         }
5356       } else {
5357         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5358         gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5359       }
5360     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5361       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5362           (NULL), ("streaming stopped, reason %s", reason));
5363       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5364     }
5365     goto done;
5366   }
5367 }
5368
5369 /*
5370  * has_next_entry
5371  *
5372  * Returns if there are samples to be played.
5373  */
5374 static gboolean
5375 has_next_entry (GstQTDemux * demux)
5376 {
5377   QtDemuxStream *stream;
5378   int i;
5379
5380   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5381
5382   for (i = 0; i < demux->n_streams; i++) {
5383     stream = demux->streams[i];
5384
5385     if (stream->sample_index == -1) {
5386       stream->sample_index = 0;
5387       stream->offset_in_sample = 0;
5388     }
5389
5390     if (stream->sample_index >= stream->n_samples) {
5391       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5392       continue;
5393     }
5394     GST_DEBUG_OBJECT (demux, "Found a sample");
5395     return TRUE;
5396   }
5397
5398   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5399   return FALSE;
5400 }
5401
5402 /*
5403  * next_entry_size
5404  *
5405  * Returns the size of the first entry at the current offset.
5406  * If -1, there are none (which means EOS or empty file).
5407  */
5408 static guint64
5409 next_entry_size (GstQTDemux * demux)
5410 {
5411   QtDemuxStream *stream;
5412   int i;
5413   int smallidx = -1;
5414   guint64 smalloffs = (guint64) - 1;
5415   QtDemuxSample *sample;
5416
5417   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5418       demux->offset);
5419
5420   for (i = 0; i < demux->n_streams; i++) {
5421     stream = demux->streams[i];
5422
5423     if (stream->sample_index == -1) {
5424       stream->sample_index = 0;
5425       stream->offset_in_sample = 0;
5426     }
5427
5428     if (stream->sample_index >= stream->n_samples) {
5429       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5430       continue;
5431     }
5432
5433     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5434       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5435           stream->sample_index);
5436       return -1;
5437     }
5438
5439     sample = &stream->samples[stream->sample_index];
5440
5441     GST_LOG_OBJECT (demux,
5442         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5443         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5444         sample->offset, sample->size);
5445
5446     if (((smalloffs == -1)
5447             || (sample->offset < smalloffs)) && (sample->size)) {
5448       smallidx = i;
5449       smalloffs = sample->offset;
5450     }
5451   }
5452
5453   GST_LOG_OBJECT (demux,
5454       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5455       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5456
5457   if (smallidx == -1)
5458     return -1;
5459
5460   stream = demux->streams[smallidx];
5461   sample = &stream->samples[stream->sample_index];
5462
5463   if (sample->offset >= demux->offset) {
5464     demux->todrop = sample->offset - demux->offset;
5465     return sample->size + demux->todrop;
5466   }
5467
5468   GST_DEBUG_OBJECT (demux,
5469       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5470   return -1;
5471 }
5472
5473 static void
5474 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5475 {
5476   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5477
5478   gst_element_post_message (GST_ELEMENT_CAST (demux),
5479       gst_message_new_element (GST_OBJECT_CAST (demux),
5480           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5481 }
5482
5483 static gboolean
5484 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5485 {
5486   GstEvent *event;
5487   gboolean res = 0;
5488
5489   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5490
5491   event =
5492       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5493       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5494       GST_SEEK_TYPE_NONE, -1);
5495
5496   /* store seqnum to drop flush events, they don't need to reach downstream */
5497   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5498   res = gst_pad_push_event (demux->sinkpad, event);
5499   demux->offset_seek_seqnum = 0;
5500
5501   return res;
5502 }
5503
5504 /* check for seekable upstream, above and beyond a mere query */
5505 static void
5506 gst_qtdemux_check_seekability (GstQTDemux * demux)
5507 {
5508   GstQuery *query;
5509   gboolean seekable = FALSE;
5510   gint64 start = -1, stop = -1;
5511
5512   if (demux->upstream_size)
5513     return;
5514
5515   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5516   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5517     GST_DEBUG_OBJECT (demux, "seeking query failed");
5518     goto done;
5519   }
5520
5521   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5522
5523   /* try harder to query upstream size if we didn't get it the first time */
5524   if (seekable && stop == -1) {
5525     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5526     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5527   }
5528
5529   /* if upstream doesn't know the size, it's likely that it's not seekable in
5530    * practice even if it technically may be seekable */
5531   if (seekable && (start != 0 || stop <= start)) {
5532     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5533     seekable = FALSE;
5534   }
5535
5536 done:
5537   gst_query_unref (query);
5538
5539   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5540       G_GUINT64_FORMAT ")", seekable, start, stop);
5541   demux->upstream_seekable = seekable;
5542   demux->upstream_size = seekable ? stop : -1;
5543 }
5544
5545 static void
5546 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5547 {
5548   g_return_if_fail (bytes <= demux->todrop);
5549
5550   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5551   gst_adapter_flush (demux->adapter, bytes);
5552   demux->neededbytes -= bytes;
5553   demux->offset += bytes;
5554   demux->todrop -= bytes;
5555 }
5556
5557 static void
5558 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5559 {
5560   if (G_UNLIKELY (demux->pending_newsegment)) {
5561     gint i;
5562
5563     gst_qtdemux_push_pending_newsegment (demux);
5564     /* clear to send tags on all streams */
5565     for (i = 0; i < demux->n_streams; i++) {
5566       QtDemuxStream *stream;
5567       stream = demux->streams[i];
5568       gst_qtdemux_push_tags (demux, stream);
5569       if (stream->sparse) {
5570         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5571         gst_pad_push_event (stream->pad,
5572             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
5573       }
5574     }
5575   }
5576 }
5577
5578 static void
5579 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
5580     QtDemuxStream * stream)
5581 {
5582   gint i;
5583
5584   /* Push any initial gap segments before proceeding to the
5585    * 'real' data */
5586   for (i = 0; i < stream->n_segments; i++) {
5587     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
5588
5589     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
5590       GstClockTime ts, dur;
5591       GstEvent *gap;
5592
5593       ts = stream->time_position;
5594       dur =
5595           stream->segments[i].duration - (stream->time_position -
5596           stream->segments[i].time);
5597       gap = gst_event_new_gap (ts, dur);
5598       stream->time_position += dur;
5599
5600       GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
5601           "segment: %" GST_PTR_FORMAT, gap);
5602       gst_pad_push_event (stream->pad, gap);
5603     } else {
5604       /* Only support empty segment at the beginning followed by
5605        * one non-empty segment, this was checked when parsing the
5606        * edts atom, arriving here is unexpected */
5607       g_assert (i + 1 == stream->n_segments);
5608       break;
5609     }
5610   }
5611 }
5612
5613 static GstFlowReturn
5614 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
5615 {
5616   GstQTDemux *demux;
5617
5618   demux = GST_QTDEMUX (parent);
5619
5620   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
5621     gint i;
5622
5623     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
5624
5625     for (i = 0; i < demux->n_streams; i++) {
5626       demux->streams[i]->discont = TRUE;
5627     }
5628
5629     /* Reverse fragmented playback, need to flush all we have before
5630      * consuming a new fragment.
5631      * The samples array have the timestamps calculated by accumulating the
5632      * durations but this won't work for reverse playback of fragments as
5633      * the timestamps of a subsequent fragment should be smaller than the
5634      * previously received one. */
5635     if (demux->fragmented && demux->segment.rate < 0) {
5636       gst_qtdemux_process_adapter (demux, TRUE);
5637       for (i = 0; i < demux->n_streams; i++)
5638         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
5639     }
5640   }
5641
5642   gst_adapter_push (demux->adapter, inbuf);
5643
5644   GST_DEBUG_OBJECT (demux,
5645       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
5646       demux->neededbytes, gst_adapter_available (demux->adapter));
5647
5648   return gst_qtdemux_process_adapter (demux, FALSE);
5649 }
5650
5651 static GstFlowReturn
5652 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
5653 {
5654   GstFlowReturn ret = GST_FLOW_OK;
5655
5656   /* we never really mean to buffer that much */
5657   if (demux->neededbytes == -1) {
5658     goto eos;
5659   }
5660
5661   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
5662       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
5663
5664     GST_DEBUG_OBJECT (demux,
5665         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
5666         demux->state, demux->neededbytes, demux->offset);
5667
5668     switch (demux->state) {
5669       case QTDEMUX_STATE_INITIAL:{
5670         const guint8 *data;
5671         guint32 fourcc;
5672         guint64 size;
5673
5674         gst_qtdemux_check_seekability (demux);
5675
5676         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5677
5678         /* get fourcc/length, set neededbytes */
5679         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
5680             &size, &fourcc);
5681         gst_adapter_unmap (demux->adapter);
5682         data = NULL;
5683         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
5684             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
5685         if (size == 0) {
5686           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5687               (_("This file is invalid and cannot be played.")),
5688               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
5689                   GST_FOURCC_ARGS (fourcc)));
5690           ret = GST_FLOW_ERROR;
5691           break;
5692         }
5693         if (fourcc == FOURCC_mdat) {
5694           gint next_entry = next_entry_size (demux);
5695           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
5696             /* we have the headers, start playback */
5697             demux->state = QTDEMUX_STATE_MOVIE;
5698             demux->neededbytes = next_entry;
5699             demux->mdatleft = size;
5700           } else {
5701             /* no headers yet, try to get them */
5702             guint bs;
5703             gboolean res;
5704             guint64 old, target;
5705
5706           buffer_data:
5707             old = demux->offset;
5708             target = old + size;
5709
5710             /* try to jump over the atom with a seek */
5711             /* only bother if it seems worth doing so,
5712              * and avoids possible upstream/server problems */
5713             if (demux->upstream_seekable &&
5714                 demux->upstream_size > 4 * (1 << 20)) {
5715               res = qtdemux_seek_offset (demux, target);
5716             } else {
5717               GST_DEBUG_OBJECT (demux, "skipping seek");
5718               res = FALSE;
5719             }
5720
5721             if (res) {
5722               GST_DEBUG_OBJECT (demux, "seek success");
5723               /* remember the offset fo the first mdat so we can seek back to it
5724                * after we have the headers */
5725               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
5726                 demux->first_mdat = old;
5727                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
5728                     demux->first_mdat);
5729               }
5730               /* seek worked, continue reading */
5731               demux->offset = target;
5732               demux->neededbytes = 16;
5733               demux->state = QTDEMUX_STATE_INITIAL;
5734             } else {
5735               /* seek failed, need to buffer */
5736               demux->offset = old;
5737               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
5738               /* there may be multiple mdat (or alike) buffers */
5739               /* sanity check */
5740               if (demux->mdatbuffer)
5741                 bs = gst_buffer_get_size (demux->mdatbuffer);
5742               else
5743                 bs = 0;
5744               if (size + bs > 10 * (1 << 20))
5745                 goto no_moov;
5746               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
5747               demux->neededbytes = size;
5748               if (!demux->mdatbuffer)
5749                 demux->mdatoffset = demux->offset;
5750             }
5751           }
5752         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
5753           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5754               (_("This file is invalid and cannot be played.")),
5755               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
5756                   GST_FOURCC_ARGS (fourcc), size));
5757           ret = GST_FLOW_ERROR;
5758           break;
5759         } else {
5760           /* this means we already started buffering and still no moov header,
5761            * let's continue buffering everything till we get moov */
5762           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
5763                   || fourcc == FOURCC_moof))
5764             goto buffer_data;
5765           demux->neededbytes = size;
5766           demux->state = QTDEMUX_STATE_HEADER;
5767         }
5768         break;
5769       }
5770       case QTDEMUX_STATE_HEADER:{
5771         const guint8 *data;
5772         guint32 fourcc;
5773
5774         GST_DEBUG_OBJECT (demux, "In header");
5775
5776         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5777
5778         /* parse the header */
5779         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
5780             &fourcc);
5781         if (fourcc == FOURCC_moov) {
5782           gint n;
5783           gboolean got_samples = FALSE;
5784
5785           /* in usual fragmented setup we could try to scan for more
5786            * and end up at the the moov (after mdat) again */
5787           if (demux->got_moov && demux->n_streams > 0 &&
5788               (!demux->fragmented
5789                   || demux->last_moov_offset == demux->offset)) {
5790             GST_DEBUG_OBJECT (demux,
5791                 "Skipping moov atom as we have (this) one already");
5792           } else {
5793             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
5794
5795             if (demux->got_moov && demux->fragmented) {
5796               GST_DEBUG_OBJECT (demux,
5797                   "Got a second moov, clean up data from old one");
5798               if (demux->moov_node)
5799                 g_node_destroy (demux->moov_node);
5800               demux->moov_node = NULL;
5801               demux->moov_node_compressed = NULL;
5802             } else {
5803               /* prepare newsegment to send when streaming actually starts */
5804               if (!demux->pending_newsegment)
5805                 demux->pending_newsegment =
5806                     gst_event_new_segment (&demux->segment);
5807             }
5808
5809             demux->last_moov_offset = demux->offset;
5810
5811             qtdemux_parse_moov (demux, data, demux->neededbytes);
5812             qtdemux_node_dump (demux, demux->moov_node);
5813             qtdemux_parse_tree (demux);
5814             qtdemux_prepare_streams (demux);
5815
5816             for (n = 0; n < demux->n_streams; n++) {
5817               QtDemuxStream *stream = demux->streams[n];
5818               got_samples |= stream->stbl_index >= 0;
5819             }
5820             if (!demux->fragmented || got_samples) {
5821               if (!demux->got_moov) {
5822                 qtdemux_expose_streams (demux);
5823               } else {
5824                 for (n = 0; n < demux->n_streams; n++) {
5825                   QtDemuxStream *stream = demux->streams[n];
5826                   gst_qtdemux_configure_stream (demux, stream);
5827                 }
5828               }
5829               gst_qtdemux_check_send_pending_segment (demux);
5830               demux->pending_configure = FALSE;
5831             } else {
5832               demux->pending_configure = TRUE;
5833             }
5834
5835             demux->got_moov = TRUE;
5836
5837             /* fragmented streams headers shouldn't contain edts atoms */
5838             if (!demux->fragmented) {
5839               for (n = 0; n < demux->n_streams; n++) {
5840                 gst_qtdemux_stream_send_initial_gap_segments (demux,
5841                     demux->streams[n]);
5842               }
5843             }
5844
5845             g_node_destroy (demux->moov_node);
5846             demux->moov_node = NULL;
5847             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
5848           }
5849         } else if (fourcc == FOURCC_moof) {
5850           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
5851             guint64 dist = 0;
5852             GstClockTime prev_pts;
5853             guint64 prev_offset;
5854             gint n;
5855
5856             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
5857
5858             /*
5859              * The timestamp of the moof buffer is relevant as some scenarios
5860              * won't have the initial timestamp in the atoms. Whenever a new
5861              * buffer has started, we get that buffer's PTS and use it as a base
5862              * timestamp for the trun entries.
5863              *
5864              * To keep track of the current buffer timestamp and starting point
5865              * we use gst_adapter_prev_pts that gives us the PTS and the distance
5866              * from the beggining of the buffer, with the distance and demux->offset
5867              * we know if it is still the same buffer or not.
5868              */
5869             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
5870             prev_offset = demux->offset - dist;
5871             if (demux->fragment_start_offset == -1
5872                 || prev_offset > demux->fragment_start_offset) {
5873               demux->fragment_start_offset = prev_offset;
5874               demux->fragment_start = prev_pts;
5875               GST_DEBUG_OBJECT (demux,
5876                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
5877                   GST_TIME_FORMAT, demux->fragment_start_offset,
5878                   GST_TIME_ARGS (demux->fragment_start));
5879             }
5880
5881             demux->moof_offset = demux->offset;
5882             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
5883                     demux->offset, NULL)) {
5884               gst_adapter_unmap (demux->adapter);
5885               ret = GST_FLOW_ERROR;
5886               goto done;
5887             }
5888             /* in MSS we need to expose the pads after the first moof as we won't get a moov 
5889              * Also, fragmented format need to be exposed if a moov have no valid sample data */
5890             if (demux->mss_mode || demux->pending_configure) {
5891               if (!demux->exposed) {
5892                 if (!demux->pending_newsegment) {
5893                   GstSegment segment;
5894                   gst_segment_init (&segment, GST_FORMAT_TIME);
5895                   GST_DEBUG_OBJECT (demux, "new pending_newsegment");
5896                   demux->pending_newsegment = gst_event_new_segment (&segment);
5897                 }
5898                 qtdemux_expose_streams (demux);
5899               } else {
5900                 for (n = 0; n < demux->n_streams; n++) {
5901                   QtDemuxStream *stream = demux->streams[n];
5902                   gst_qtdemux_configure_stream (demux, stream);
5903                 }
5904               }
5905               gst_qtdemux_check_send_pending_segment (demux);
5906               demux->pending_configure = FALSE;
5907             }
5908           } else {
5909             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
5910           }
5911         } else if (fourcc == FOURCC_ftyp) {
5912           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
5913           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
5914         } else if (fourcc == FOURCC_uuid) {
5915           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
5916           qtdemux_parse_uuid (demux, data, demux->neededbytes);
5917         } else if (fourcc == FOURCC_sidx) {
5918           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
5919           qtdemux_parse_sidx (demux, data, demux->neededbytes);
5920         } else {
5921           GST_WARNING_OBJECT (demux,
5922               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
5923               GST_FOURCC_ARGS (fourcc));
5924           /* Let's jump that one and go back to initial state */
5925         }
5926         gst_adapter_unmap (demux->adapter);
5927         data = NULL;
5928
5929         if (demux->mdatbuffer && demux->n_streams) {
5930           gsize remaining_data_size = 0;
5931
5932           /* the mdat was before the header */
5933           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
5934               demux->n_streams, demux->mdatbuffer);
5935           /* restore our adapter/offset view of things with upstream;
5936            * put preceding buffered data ahead of current moov data.
5937            * This should also handle evil mdat, moov, mdat cases and alike */
5938           gst_adapter_flush (demux->adapter, demux->neededbytes);
5939
5940           /* Store any remaining data after the mdat for later usage */
5941           remaining_data_size = gst_adapter_available (demux->adapter);
5942           if (remaining_data_size > 0) {
5943             g_assert (demux->restoredata_buffer == NULL);
5944             demux->restoredata_buffer =
5945                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
5946             demux->restoredata_offset = demux->offset + demux->neededbytes;
5947             GST_DEBUG_OBJECT (demux,
5948                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
5949                 G_GUINT64_FORMAT, remaining_data_size,
5950                 demux->restoredata_offset);
5951           }
5952
5953           gst_adapter_push (demux->adapter, demux->mdatbuffer);
5954           demux->mdatbuffer = NULL;
5955           demux->offset = demux->mdatoffset;
5956           demux->neededbytes = next_entry_size (demux);
5957           demux->state = QTDEMUX_STATE_MOVIE;
5958           demux->mdatleft = gst_adapter_available (demux->adapter);
5959         } else {
5960           GST_DEBUG_OBJECT (demux, "Carrying on normally");
5961           gst_adapter_flush (demux->adapter, demux->neededbytes);
5962
5963           /* only go back to the mdat if there are samples to play */
5964           if (demux->got_moov && demux->first_mdat != -1
5965               && has_next_entry (demux)) {
5966             gboolean res;
5967
5968             /* we need to seek back */
5969             res = qtdemux_seek_offset (demux, demux->first_mdat);
5970             if (res) {
5971               demux->offset = demux->first_mdat;
5972             } else {
5973               GST_DEBUG_OBJECT (demux, "Seek back failed");
5974             }
5975           } else {
5976             demux->offset += demux->neededbytes;
5977           }
5978           demux->neededbytes = 16;
5979           demux->state = QTDEMUX_STATE_INITIAL;
5980         }
5981
5982         break;
5983       }
5984       case QTDEMUX_STATE_BUFFER_MDAT:{
5985         GstBuffer *buf;
5986         guint8 fourcc[4];
5987
5988         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
5989             demux->offset);
5990         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
5991         gst_buffer_extract (buf, 0, fourcc, 4);
5992         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
5993             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
5994         if (demux->mdatbuffer)
5995           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
5996         else
5997           demux->mdatbuffer = buf;
5998         demux->offset += demux->neededbytes;
5999         demux->neededbytes = 16;
6000         demux->state = QTDEMUX_STATE_INITIAL;
6001         gst_qtdemux_post_progress (demux, 1, 1);
6002
6003         break;
6004       }
6005       case QTDEMUX_STATE_MOVIE:{
6006         QtDemuxStream *stream = NULL;
6007         QtDemuxSample *sample;
6008         int i = -1;
6009         GstClockTime dts, pts, duration;
6010         gboolean keyframe;
6011
6012         GST_DEBUG_OBJECT (demux,
6013             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6014
6015         if (demux->fragmented) {
6016           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6017               demux->mdatleft);
6018           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6019             /* if needed data starts within this atom,
6020              * then it should not exceed this atom */
6021             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6022               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6023                   (_("This file is invalid and cannot be played.")),
6024                   ("sample data crosses atom boundary"));
6025               ret = GST_FLOW_ERROR;
6026               break;
6027             }
6028             demux->mdatleft -= demux->neededbytes;
6029           } else {
6030             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6031             /* so we are dropping more than left in this atom */
6032             gst_qtdemux_drop_data (demux, demux->mdatleft);
6033             demux->mdatleft = 0;
6034
6035             /* need to resume atom parsing so we do not miss any other pieces */
6036             demux->state = QTDEMUX_STATE_INITIAL;
6037             demux->neededbytes = 16;
6038
6039             /* check if there was any stored post mdat data from previous buffers */
6040             if (demux->restoredata_buffer) {
6041               g_assert (gst_adapter_available (demux->adapter) == 0);
6042
6043               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6044               demux->restoredata_buffer = NULL;
6045               demux->offset = demux->restoredata_offset;
6046             }
6047
6048             break;
6049           }
6050         }
6051
6052         if (demux->todrop) {
6053           if (demux->cenc_aux_info_offset > 0) {
6054             GstByteReader br;
6055             const guint8 *data;
6056
6057             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6058             data = gst_adapter_map (demux->adapter, demux->todrop);
6059             gst_byte_reader_init (&br, data + 8, demux->todrop);
6060             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6061                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6062               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6063               ret = GST_FLOW_ERROR;
6064               gst_adapter_unmap (demux->adapter);
6065               g_free (demux->cenc_aux_info_sizes);
6066               demux->cenc_aux_info_sizes = NULL;
6067               goto done;
6068             }
6069             demux->cenc_aux_info_offset = 0;
6070             g_free (demux->cenc_aux_info_sizes);
6071             demux->cenc_aux_info_sizes = NULL;
6072             gst_adapter_unmap (demux->adapter);
6073           }
6074           gst_qtdemux_drop_data (demux, demux->todrop);
6075         }
6076
6077         /* first buffer? */
6078         /* initial newsegment sent here after having added pads,
6079          * possible others in sink_event */
6080         gst_qtdemux_check_send_pending_segment (demux);
6081
6082         /* Figure out which stream this packet belongs to */
6083         for (i = 0; i < demux->n_streams; i++) {
6084           stream = demux->streams[i];
6085           if (stream->sample_index >= stream->n_samples)
6086             continue;
6087           GST_LOG_OBJECT (demux,
6088               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6089               " / size:%d)", i, stream->sample_index,
6090               stream->samples[stream->sample_index].offset,
6091               stream->samples[stream->sample_index].size);
6092
6093           if (stream->samples[stream->sample_index].offset == demux->offset)
6094             break;
6095         }
6096
6097         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6098           goto unknown_stream;
6099
6100         if (stream->new_caps) {
6101           gst_qtdemux_configure_stream (demux, stream);
6102         }
6103
6104         /* Put data in a buffer, set timestamps, caps, ... */
6105         sample = &stream->samples[stream->sample_index];
6106
6107         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6108           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6109               GST_FOURCC_ARGS (stream->fourcc));
6110
6111           dts = QTSAMPLE_DTS (stream, sample);
6112           pts = QTSAMPLE_PTS (stream, sample);
6113           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6114           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6115
6116           /* check for segment end */
6117           if (G_UNLIKELY (demux->segment.stop != -1
6118                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6119             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6120             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6121
6122             /* skip this data, stream is EOS */
6123             gst_adapter_flush (demux->adapter, demux->neededbytes);
6124
6125             /* check if all streams are eos */
6126             ret = GST_FLOW_EOS;
6127             for (i = 0; i < demux->n_streams; i++) {
6128               if (!STREAM_IS_EOS (demux->streams[i])) {
6129                 ret = GST_FLOW_OK;
6130                 break;
6131               }
6132             }
6133
6134             if (ret == GST_FLOW_EOS) {
6135               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6136               goto eos;
6137             }
6138           } else {
6139             GstBuffer *outbuf;
6140
6141             outbuf =
6142                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6143
6144             /* FIXME: should either be an assert or a plain check */
6145             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6146
6147             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6148                 dts, pts, duration, keyframe, dts, demux->offset);
6149           }
6150
6151           /* combine flows */
6152           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6153           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6154             goto non_ok_unlinked_flow;
6155         } else {
6156           /* skip this data, stream is EOS */
6157           gst_adapter_flush (demux->adapter, demux->neededbytes);
6158         }
6159
6160         stream->sample_index++;
6161         stream->offset_in_sample = 0;
6162
6163         /* update current offset and figure out size of next buffer */
6164         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6165             demux->offset, demux->neededbytes);
6166         demux->offset += demux->neededbytes;
6167         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6168             demux->offset);
6169
6170         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6171           if (demux->fragmented) {
6172             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6173             /* there may be more to follow, only finish this atom */
6174             demux->todrop = demux->mdatleft;
6175             demux->neededbytes = demux->todrop;
6176             break;
6177           }
6178           goto eos;
6179         }
6180         break;
6181       }
6182       default:
6183         goto invalid_state;
6184     }
6185   }
6186
6187   /* when buffering movie data, at least show user something is happening */
6188   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6189       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6190     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6191         demux->neededbytes);
6192   }
6193 done:
6194
6195   return ret;
6196
6197   /* ERRORS */
6198 non_ok_unlinked_flow:
6199   {
6200     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6201         gst_flow_get_name (ret));
6202     return ret;
6203   }
6204 unknown_stream:
6205   {
6206     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6207     ret = GST_FLOW_ERROR;
6208     goto done;
6209   }
6210 eos:
6211   {
6212     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6213     ret = GST_FLOW_EOS;
6214     goto done;
6215   }
6216 invalid_state:
6217   {
6218     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6219         (NULL), ("qtdemuxer invalid state %d", demux->state));
6220     ret = GST_FLOW_ERROR;
6221     goto done;
6222   }
6223 no_moov:
6224   {
6225     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6226         (NULL), ("no 'moov' atom within the first 10 MB"));
6227     ret = GST_FLOW_ERROR;
6228     goto done;
6229   }
6230 }
6231
6232 static gboolean
6233 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6234 {
6235   GstQuery *query;
6236   gboolean pull_mode;
6237
6238   query = gst_query_new_scheduling ();
6239
6240   if (!gst_pad_peer_query (sinkpad, query)) {
6241     gst_query_unref (query);
6242     goto activate_push;
6243   }
6244
6245   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6246       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6247   gst_query_unref (query);
6248
6249   if (!pull_mode)
6250     goto activate_push;
6251
6252   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6253   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6254
6255 activate_push:
6256   {
6257     GST_DEBUG_OBJECT (sinkpad, "activating push");
6258     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6259   }
6260 }
6261
6262 static gboolean
6263 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6264     GstPadMode mode, gboolean active)
6265 {
6266   gboolean res;
6267   GstQTDemux *demux = GST_QTDEMUX (parent);
6268
6269   switch (mode) {
6270     case GST_PAD_MODE_PUSH:
6271       demux->pullbased = FALSE;
6272       res = TRUE;
6273       break;
6274     case GST_PAD_MODE_PULL:
6275       if (active) {
6276         demux->pullbased = TRUE;
6277         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6278             sinkpad, NULL);
6279       } else {
6280         res = gst_pad_stop_task (sinkpad);
6281       }
6282       break;
6283     default:
6284       res = FALSE;
6285       break;
6286   }
6287   return res;
6288 }
6289
6290 #ifdef HAVE_ZLIB
6291 static void *
6292 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6293 {
6294   return g_malloc (items * size);
6295 }
6296
6297 static void
6298 qtdemux_zfree (void *opaque, void *addr)
6299 {
6300   g_free (addr);
6301 }
6302
6303 static void *
6304 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6305 {
6306   guint8 *buffer;
6307   z_stream *z;
6308   int ret;
6309
6310   z = g_new0 (z_stream, 1);
6311   z->zalloc = qtdemux_zalloc;
6312   z->zfree = qtdemux_zfree;
6313   z->opaque = NULL;
6314
6315   z->next_in = z_buffer;
6316   z->avail_in = z_length;
6317
6318   buffer = (guint8 *) g_malloc (length);
6319   ret = inflateInit (z);
6320   while (z->avail_in > 0) {
6321     if (z->avail_out == 0) {
6322       length += 1024;
6323       buffer = (guint8 *) g_realloc (buffer, length);
6324       z->next_out = buffer + z->total_out;
6325       z->avail_out = 1024;
6326     }
6327     ret = inflate (z, Z_SYNC_FLUSH);
6328     if (ret != Z_OK)
6329       break;
6330   }
6331   if (ret != Z_STREAM_END) {
6332     g_warning ("inflate() returned %d", ret);
6333   }
6334
6335   g_free (z);
6336   return buffer;
6337 }
6338 #endif /* HAVE_ZLIB */
6339
6340 static gboolean
6341 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6342 {
6343   GNode *cmov;
6344
6345   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6346
6347   /* counts as header data */
6348   qtdemux->header_size += length;
6349
6350   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6351   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6352
6353   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6354   if (cmov) {
6355     guint32 method;
6356     GNode *dcom;
6357     GNode *cmvd;
6358
6359     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6360     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6361     if (dcom == NULL || cmvd == NULL)
6362       goto invalid_compression;
6363
6364     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6365     switch (method) {
6366 #ifdef HAVE_ZLIB
6367       case FOURCC_zlib:{
6368         guint uncompressed_length;
6369         guint compressed_length;
6370         guint8 *buf;
6371
6372         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6373         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6374         GST_LOG ("length = %u", uncompressed_length);
6375
6376         buf =
6377             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6378             compressed_length, uncompressed_length);
6379
6380         qtdemux->moov_node_compressed = qtdemux->moov_node;
6381         qtdemux->moov_node = g_node_new (buf);
6382
6383         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6384             uncompressed_length);
6385         break;
6386       }
6387 #endif /* HAVE_ZLIB */
6388       default:
6389         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6390             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6391         break;
6392     }
6393   }
6394   return TRUE;
6395
6396   /* ERRORS */
6397 invalid_compression:
6398   {
6399     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6400     return FALSE;
6401   }
6402 }
6403
6404 static gboolean
6405 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6406     const guint8 * end)
6407 {
6408   while (G_UNLIKELY (buf < end)) {
6409     GNode *child;
6410     guint32 len;
6411
6412     if (G_UNLIKELY (buf + 4 > end)) {
6413       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6414       break;
6415     }
6416     len = QT_UINT32 (buf);
6417     if (G_UNLIKELY (len == 0)) {
6418       GST_LOG_OBJECT (qtdemux, "empty container");
6419       break;
6420     }
6421     if (G_UNLIKELY (len < 8)) {
6422       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6423       break;
6424     }
6425     if (G_UNLIKELY (len > (end - buf))) {
6426       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6427           (gint) (end - buf));
6428       break;
6429     }
6430
6431     child = g_node_new ((guint8 *) buf);
6432     g_node_append (node, child);
6433     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6434     qtdemux_parse_node (qtdemux, child, buf, len);
6435
6436     buf += len;
6437   }
6438   return TRUE;
6439 }
6440
6441 static gboolean
6442 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6443     GNode * xdxt)
6444 {
6445   int len = QT_UINT32 (xdxt->data);
6446   guint8 *buf = xdxt->data;
6447   guint8 *end = buf + len;
6448   GstBuffer *buffer;
6449
6450   /* skip size and type */
6451   buf += 8;
6452   end -= 8;
6453
6454   while (buf < end) {
6455     gint size;
6456     guint32 type;
6457
6458     size = QT_UINT32 (buf);
6459     type = QT_FOURCC (buf + 4);
6460
6461     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6462
6463     if (buf + size > end || size <= 0)
6464       break;
6465
6466     buf += 8;
6467     size -= 8;
6468
6469     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6470         GST_FOURCC_ARGS (type));
6471
6472     switch (type) {
6473       case FOURCC_tCtH:
6474         buffer = gst_buffer_new_and_alloc (size);
6475         gst_buffer_fill (buffer, 0, buf, size);
6476         stream->buffers = g_slist_append (stream->buffers, buffer);
6477         GST_LOG_OBJECT (qtdemux, "parsing theora header");
6478         break;
6479       case FOURCC_tCt_:
6480         buffer = gst_buffer_new_and_alloc (size);
6481         gst_buffer_fill (buffer, 0, buf, size);
6482         stream->buffers = g_slist_append (stream->buffers, buffer);
6483         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6484         break;
6485       case FOURCC_tCtC:
6486         buffer = gst_buffer_new_and_alloc (size);
6487         gst_buffer_fill (buffer, 0, buf, size);
6488         stream->buffers = g_slist_append (stream->buffers, buffer);
6489         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6490         break;
6491       default:
6492         GST_WARNING_OBJECT (qtdemux,
6493             "unknown theora cookie %" GST_FOURCC_FORMAT,
6494             GST_FOURCC_ARGS (type));
6495         break;
6496     }
6497     buf += size;
6498   }
6499   return TRUE;
6500 }
6501
6502 static gboolean
6503 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
6504     guint length)
6505 {
6506   guint32 fourcc = 0;
6507   guint32 node_length = 0;
6508   const QtNodeType *type;
6509   const guint8 *end;
6510
6511   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
6512
6513   if (G_UNLIKELY (length < 8))
6514     goto not_enough_data;
6515
6516   node_length = QT_UINT32 (buffer);
6517   fourcc = QT_FOURCC (buffer + 4);
6518
6519   /* ignore empty nodes */
6520   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
6521     return TRUE;
6522
6523   type = qtdemux_type_get (fourcc);
6524
6525   end = buffer + length;
6526
6527   GST_LOG_OBJECT (qtdemux,
6528       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
6529       GST_FOURCC_ARGS (fourcc), node_length, type->name);
6530
6531   if (node_length > length)
6532     goto broken_atom_size;
6533
6534   if (type->flags & QT_FLAG_CONTAINER) {
6535     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
6536   } else {
6537     switch (fourcc) {
6538       case FOURCC_stsd:
6539       {
6540         if (node_length < 20) {
6541           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
6542           break;
6543         }
6544         GST_DEBUG_OBJECT (qtdemux,
6545             "parsing stsd (sample table, sample description) atom");
6546         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
6547         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6548         break;
6549       }
6550       case FOURCC_mp4a:
6551       case FOURCC_alac:
6552       {
6553         guint32 version;
6554         guint32 offset;
6555         guint min_size;
6556
6557         /* also read alac (or whatever) in stead of mp4a in the following,
6558          * since a similar layout is used in other cases as well */
6559         if (fourcc == FOURCC_mp4a)
6560           min_size = 20;
6561         else
6562           min_size = 40;
6563
6564         /* There are two things we might encounter here: a true mp4a atom, and
6565            an mp4a entry in an stsd atom. The latter is what we're interested
6566            in, and it looks like an atom, but isn't really one. The true mp4a
6567            atom is short, so we detect it based on length here. */
6568         if (length < min_size) {
6569           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
6570               GST_FOURCC_ARGS (fourcc));
6571           break;
6572         }
6573
6574         /* 'version' here is the sound sample description version. Types 0 and
6575            1 are documented in the QTFF reference, but type 2 is not: it's
6576            described in Apple header files instead (struct SoundDescriptionV2
6577            in Movies.h) */
6578         version = QT_UINT16 (buffer + 16);
6579
6580         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
6581             GST_FOURCC_ARGS (fourcc), version);
6582
6583         /* parse any esds descriptors */
6584         switch (version) {
6585           case 0:
6586             offset = 0x24;
6587             break;
6588           case 1:
6589             offset = 0x34;
6590             break;
6591           case 2:
6592             offset = 0x48;
6593             break;
6594           default:
6595             GST_WARNING_OBJECT (qtdemux,
6596                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
6597                 GST_FOURCC_ARGS (fourcc), version);
6598             offset = 0;
6599             break;
6600         }
6601         if (offset)
6602           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6603         break;
6604       }
6605       case FOURCC_mp4v:
6606       case FOURCC_MP4V:
6607       case FOURCC_fmp4:
6608       case FOURCC_FMP4:
6609       case FOURCC_apcs:
6610       case FOURCC_apch:
6611       case FOURCC_apcn:
6612       case FOURCC_apco:
6613       case FOURCC_ap4h:
6614       {
6615         const guint8 *buf;
6616         guint32 version;
6617         int tlen;
6618
6619         /* codec_data is contained inside these atoms, which all have
6620          * the same format. */
6621
6622         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
6623             GST_FOURCC_ARGS (fourcc));
6624         version = QT_UINT32 (buffer + 16);
6625         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
6626         if (1 || version == 0x00000000) {
6627           buf = buffer + 0x32;
6628
6629           /* FIXME Quicktime uses PASCAL string while
6630            * the iso format uses C strings. Check the file
6631            * type before attempting to parse the string here. */
6632           tlen = QT_UINT8 (buf);
6633           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
6634           buf++;
6635           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
6636           /* the string has a reserved space of 32 bytes so skip
6637            * the remaining 31 */
6638           buf += 31;
6639           buf += 4;             /* and 4 bytes reserved */
6640
6641           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
6642
6643           qtdemux_parse_container (qtdemux, node, buf, end);
6644         }
6645         break;
6646       }
6647       case FOURCC_H264:
6648       {
6649         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
6650         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6651         break;
6652       }
6653       case FOURCC_avc1:
6654       {
6655         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
6656         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6657         break;
6658       }
6659       case FOURCC_avc3:
6660       {
6661         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
6662         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6663         break;
6664       }
6665       case FOURCC_H265:
6666       {
6667         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
6668         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6669         break;
6670       }
6671       case FOURCC_hvc1:
6672       {
6673         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
6674         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6675         break;
6676       }
6677       case FOURCC_hev1:
6678       {
6679         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
6680         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6681         break;
6682       }
6683       case FOURCC_mjp2:
6684       {
6685         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6686         break;
6687       }
6688       case FOURCC_meta:
6689       {
6690         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
6691         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
6692         break;
6693       }
6694       case FOURCC_mp4s:
6695       {
6696         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
6697         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
6698         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6699         break;
6700       }
6701       case FOURCC_XiTh:
6702       {
6703         guint32 version;
6704         guint32 offset;
6705
6706         version = QT_UINT32 (buffer + 12);
6707         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
6708
6709         switch (version) {
6710           case 0x00000001:
6711             offset = 0x62;
6712             break;
6713           default:
6714             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
6715             offset = 0;
6716             break;
6717         }
6718         if (offset)
6719           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6720         break;
6721       }
6722       case FOURCC_in24:
6723       {
6724         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
6725         break;
6726       }
6727       case FOURCC_uuid:
6728       {
6729         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
6730         break;
6731       }
6732       case FOURCC_encv:
6733       {
6734         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6735         break;
6736       }
6737       case FOURCC_enca:
6738       {
6739         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
6740         break;
6741       }
6742       default:
6743         if (!strcmp (type->name, "unknown"))
6744           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
6745         break;
6746     }
6747   }
6748   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
6749       GST_FOURCC_ARGS (fourcc));
6750   return TRUE;
6751
6752 /* ERRORS */
6753 not_enough_data:
6754   {
6755     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6756         (_("This file is corrupt and cannot be played.")),
6757         ("Not enough data for an atom header, got only %u bytes", length));
6758     return FALSE;
6759   }
6760 broken_atom_size:
6761   {
6762     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6763         (_("This file is corrupt and cannot be played.")),
6764         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
6765             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
6766             length));
6767     return FALSE;
6768   }
6769 }
6770
6771 static GNode *
6772 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
6773 {
6774   GNode *child;
6775   guint8 *buffer;
6776   guint32 child_fourcc;
6777
6778   for (child = g_node_first_child (node); child;
6779       child = g_node_next_sibling (child)) {
6780     buffer = (guint8 *) child->data;
6781
6782     child_fourcc = QT_FOURCC (buffer + 4);
6783
6784     if (G_UNLIKELY (child_fourcc == fourcc)) {
6785       return child;
6786     }
6787   }
6788   return NULL;
6789 }
6790
6791 static GNode *
6792 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
6793     GstByteReader * parser)
6794 {
6795   GNode *child;
6796   guint8 *buffer;
6797   guint32 child_fourcc, child_len;
6798
6799   for (child = g_node_first_child (node); child;
6800       child = g_node_next_sibling (child)) {
6801     buffer = (guint8 *) child->data;
6802
6803     child_len = QT_UINT32 (buffer);
6804     child_fourcc = QT_FOURCC (buffer + 4);
6805
6806     if (G_UNLIKELY (child_fourcc == fourcc)) {
6807       if (G_UNLIKELY (child_len < (4 + 4)))
6808         return NULL;
6809       /* FIXME: must verify if atom length < parent atom length */
6810       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6811       return child;
6812     }
6813   }
6814   return NULL;
6815 }
6816
6817 static GNode *
6818 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
6819     GstByteReader * parser)
6820 {
6821   GNode *child;
6822   guint8 *buffer;
6823   guint32 child_fourcc, child_len;
6824
6825   for (child = g_node_next_sibling (node); child;
6826       child = g_node_next_sibling (child)) {
6827     buffer = (guint8 *) child->data;
6828
6829     child_fourcc = QT_FOURCC (buffer + 4);
6830
6831     if (child_fourcc == fourcc) {
6832       if (parser) {
6833         child_len = QT_UINT32 (buffer);
6834         if (G_UNLIKELY (child_len < (4 + 4)))
6835           return NULL;
6836         /* FIXME: must verify if atom length < parent atom length */
6837         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6838       }
6839       return child;
6840     }
6841   }
6842   return NULL;
6843 }
6844
6845 static GNode *
6846 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
6847 {
6848   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
6849 }
6850
6851 static void
6852 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
6853 {
6854 /* FIXME: This can only reliably work if demuxers have a
6855  * separate streaming thread per srcpad. This should be
6856  * done in a demuxer base class, which integrates parts
6857  * of multiqueue
6858  *
6859  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
6860  */
6861 #if 0
6862   GstQuery *query;
6863
6864   query = gst_query_new_allocation (stream->caps, FALSE);
6865
6866   if (!gst_pad_peer_query (stream->pad, query)) {
6867     /* not a problem, just debug a little */
6868     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
6869   }
6870
6871   if (stream->allocator)
6872     gst_object_unref (stream->allocator);
6873
6874   if (gst_query_get_n_allocation_params (query) > 0) {
6875     /* try the allocator */
6876     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
6877         &stream->params);
6878     stream->use_allocator = TRUE;
6879   } else {
6880     stream->allocator = NULL;
6881     gst_allocation_params_init (&stream->params);
6882     stream->use_allocator = FALSE;
6883   }
6884   gst_query_unref (query);
6885 #endif
6886 }
6887
6888 static gboolean
6889 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
6890     QtDemuxStream * stream)
6891 {
6892   GstStructure *s;
6893   const gchar *selected_system;
6894
6895   g_return_val_if_fail (qtdemux != NULL, FALSE);
6896   g_return_val_if_fail (stream != NULL, FALSE);
6897   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
6898
6899   if (stream->protection_scheme_type != FOURCC_cenc) {
6900     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
6901     return FALSE;
6902   }
6903   if (qtdemux->protection_system_ids == NULL) {
6904     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
6905         "cenc protection system information has been found");
6906     return FALSE;
6907   }
6908   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
6909   selected_system = gst_protection_select_system ((const gchar **)
6910       qtdemux->protection_system_ids->pdata);
6911   g_ptr_array_remove_index (qtdemux->protection_system_ids,
6912       qtdemux->protection_system_ids->len - 1);
6913   if (!selected_system) {
6914     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
6915         "suitable decryptor element has been found");
6916     return FALSE;
6917   }
6918
6919   s = gst_caps_get_structure (stream->caps, 0);
6920   gst_structure_set (s,
6921       "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
6922       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
6923       NULL);
6924   gst_structure_set_name (s, "application/x-cenc");
6925   return TRUE;
6926 }
6927
6928 static gboolean
6929 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
6930 {
6931   if (stream->subtype == FOURCC_vide) {
6932     /* fps is calculated base on the duration of the average framerate since
6933      * qt does not have a fixed framerate. */
6934     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
6935       /* still frame */
6936       stream->fps_n = 0;
6937       stream->fps_d = 1;
6938     } else {
6939       if (stream->duration == 0 || stream->n_samples < 2) {
6940         stream->fps_n = stream->timescale;
6941         stream->fps_d = 1;
6942       } else {
6943         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
6944         /* stream->duration is guint64, timescale, n_samples are guint32 */
6945         GstClockTime avg_duration =
6946             gst_util_uint64_scale_round (stream->duration -
6947             stream->first_duration, GST_SECOND,
6948             (guint64) (stream->timescale) * (stream->n_samples - 1));
6949
6950         GST_LOG_OBJECT (qtdemux,
6951             "Calculating avg sample duration based on stream duration %"
6952             G_GUINT64_FORMAT
6953             " minus first sample %u, leaving %d samples gives %"
6954             GST_TIME_FORMAT, stream->duration, stream->first_duration,
6955             stream->n_samples - 1, GST_TIME_ARGS (avg_duration));
6956
6957         gst_video_guess_framerate (avg_duration, &stream->fps_n,
6958             &stream->fps_d);
6959       }
6960       GST_DEBUG_OBJECT (qtdemux,
6961           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
6962           stream->timescale, stream->fps_n, stream->fps_d);
6963     }
6964
6965     if (stream->caps) {
6966       stream->caps = gst_caps_make_writable (stream->caps);
6967
6968       gst_caps_set_simple (stream->caps,
6969           "width", G_TYPE_INT, stream->width,
6970           "height", G_TYPE_INT, stream->height,
6971           "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
6972
6973       /* calculate pixel-aspect-ratio using display width and height */
6974       GST_DEBUG_OBJECT (qtdemux,
6975           "video size %dx%d, target display size %dx%d", stream->width,
6976           stream->height, stream->display_width, stream->display_height);
6977       /* qt file might have pasp atom */
6978       if (stream->par_w > 0 && stream->par_h > 0) {
6979         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
6980         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
6981             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
6982       } else if (stream->display_width > 0 && stream->display_height > 0 &&
6983           stream->width > 0 && stream->height > 0) {
6984         gint n, d;
6985
6986         /* calculate the pixel aspect ratio using the display and pixel w/h */
6987         n = stream->display_width * stream->height;
6988         d = stream->display_height * stream->width;
6989         if (n == d)
6990           n = d = 1;
6991         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
6992         stream->par_w = n;
6993         stream->par_h = d;
6994         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
6995             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
6996       }
6997
6998       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
6999         guint par_w = 1, par_h = 1;
7000
7001         if (stream->par_w > 0 && stream->par_h > 0) {
7002           par_w = stream->par_w;
7003           par_h = stream->par_h;
7004         }
7005
7006         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7007                 stream->width, stream->height, par_w, par_h)) {
7008           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7009         }
7010
7011         gst_caps_set_simple (stream->caps,
7012             "multiview-mode", G_TYPE_STRING,
7013             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7014             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7015             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7016       }
7017     }
7018   }
7019
7020   else if (stream->subtype == FOURCC_soun) {
7021     if (stream->caps) {
7022       stream->caps = gst_caps_make_writable (stream->caps);
7023       if (stream->rate > 0)
7024         gst_caps_set_simple (stream->caps,
7025             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7026       if (stream->n_channels > 0)
7027         gst_caps_set_simple (stream->caps,
7028             "channels", G_TYPE_INT, stream->n_channels, NULL);
7029       if (stream->n_channels > 2) {
7030         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7031          * correctly; this is just the minimum we can do - assume
7032          * we don't actually have any channel positions. */
7033         gst_caps_set_simple (stream->caps,
7034             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7035       }
7036     }
7037   }
7038
7039   if (stream->pad) {
7040     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7041     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7042     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7043     gst_pad_set_active (stream->pad, TRUE);
7044
7045     gst_pad_use_fixed_caps (stream->pad);
7046
7047     if (stream->protected) {
7048       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7049         GST_ERROR_OBJECT (qtdemux,
7050             "Failed to configure protected stream caps.");
7051         return FALSE;
7052       }
7053     }
7054
7055     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7056     if (stream->new_stream) {
7057       gchar *stream_id;
7058       GstEvent *event;
7059       GstStreamFlags stream_flags;
7060
7061       event =
7062           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7063           0);
7064       if (event) {
7065         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7066           qtdemux->have_group_id = TRUE;
7067         else
7068           qtdemux->have_group_id = FALSE;
7069         gst_event_unref (event);
7070       } else if (!qtdemux->have_group_id) {
7071         qtdemux->have_group_id = TRUE;
7072         qtdemux->group_id = gst_util_group_id_next ();
7073       }
7074
7075       stream->new_stream = FALSE;
7076       stream_id =
7077           gst_pad_create_stream_id_printf (stream->pad,
7078           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7079       event = gst_event_new_stream_start (stream_id);
7080       if (qtdemux->have_group_id)
7081         gst_event_set_group_id (event, qtdemux->group_id);
7082       stream_flags = GST_STREAM_FLAG_NONE;
7083       if (stream->disabled)
7084         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7085       if (stream->sparse)
7086         stream_flags |= GST_STREAM_FLAG_SPARSE;
7087       gst_event_set_stream_flags (event, stream_flags);
7088       gst_pad_push_event (stream->pad, event);
7089       g_free (stream_id);
7090     }
7091     gst_pad_set_caps (stream->pad, stream->caps);
7092     stream->new_caps = FALSE;
7093   }
7094   return TRUE;
7095 }
7096
7097 static gboolean
7098 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7099     QtDemuxStream * stream, GstTagList * list)
7100 {
7101   /* consistent default for push based mode */
7102   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7103
7104   if (stream->subtype == FOURCC_vide) {
7105     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7106
7107     stream->pad =
7108         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7109     g_free (name);
7110
7111     gst_qtdemux_configure_stream (qtdemux, stream);
7112     qtdemux->n_video_streams++;
7113   } else if (stream->subtype == FOURCC_soun) {
7114     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7115
7116     stream->pad =
7117         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7118     g_free (name);
7119     gst_qtdemux_configure_stream (qtdemux, stream);
7120     qtdemux->n_audio_streams++;
7121   } else if (stream->subtype == FOURCC_strm) {
7122     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7123   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7124       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7125     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7126
7127     stream->pad =
7128         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7129     g_free (name);
7130     gst_qtdemux_configure_stream (qtdemux, stream);
7131     qtdemux->n_sub_streams++;
7132   } else if (stream->caps) {
7133     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7134
7135     stream->pad =
7136         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7137     g_free (name);
7138     gst_qtdemux_configure_stream (qtdemux, stream);
7139     qtdemux->n_video_streams++;
7140   } else {
7141     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7142     goto done;
7143   }
7144
7145   if (stream->pad) {
7146     GList *l;
7147
7148     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7149         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7150     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7151     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7152
7153     if (stream->pending_tags)
7154       gst_tag_list_unref (stream->pending_tags);
7155     stream->pending_tags = list;
7156     list = NULL;
7157     /* global tags go on each pad anyway */
7158     stream->send_global_tags = TRUE;
7159     /* send upstream GST_EVENT_PROTECTION events that were received before
7160        this source pad was created */
7161     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7162       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7163   }
7164 done:
7165   if (list)
7166     gst_tag_list_unref (list);
7167   return TRUE;
7168 }
7169
7170 /* find next atom with @fourcc starting at @offset */
7171 static GstFlowReturn
7172 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7173     guint64 * length, guint32 fourcc)
7174 {
7175   GstFlowReturn ret;
7176   guint32 lfourcc;
7177   GstBuffer *buf;
7178
7179   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7180       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7181
7182   while (TRUE) {
7183     GstMapInfo map;
7184
7185     buf = NULL;
7186     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7187     if (G_UNLIKELY (ret != GST_FLOW_OK))
7188       goto locate_failed;
7189     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7190       /* likely EOF */
7191       ret = GST_FLOW_EOS;
7192       gst_buffer_unref (buf);
7193       goto locate_failed;
7194     }
7195     gst_buffer_map (buf, &map, GST_MAP_READ);
7196     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7197     gst_buffer_unmap (buf, &map);
7198     gst_buffer_unref (buf);
7199
7200     if (G_UNLIKELY (*length == 0)) {
7201       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7202       ret = GST_FLOW_ERROR;
7203       goto locate_failed;
7204     }
7205
7206     if (lfourcc == fourcc) {
7207       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7208           *offset);
7209       break;
7210     } else {
7211       GST_LOG_OBJECT (qtdemux,
7212           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7213           GST_FOURCC_ARGS (fourcc), *offset);
7214       *offset += *length;
7215     }
7216   }
7217
7218   return GST_FLOW_OK;
7219
7220 locate_failed:
7221   {
7222     /* might simply have had last one */
7223     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7224     return ret;
7225   }
7226 }
7227
7228 /* should only do something in pull mode */
7229 /* call with OBJECT lock */
7230 static GstFlowReturn
7231 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7232 {
7233   guint64 length, offset;
7234   GstBuffer *buf = NULL;
7235   GstFlowReturn ret = GST_FLOW_OK;
7236   GstFlowReturn res = GST_FLOW_OK;
7237   GstMapInfo map;
7238
7239   offset = qtdemux->moof_offset;
7240   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7241
7242   if (!offset) {
7243     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7244     return GST_FLOW_EOS;
7245   }
7246
7247   /* best not do pull etc with lock held */
7248   GST_OBJECT_UNLOCK (qtdemux);
7249
7250   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7251   if (ret != GST_FLOW_OK)
7252     goto flow_failed;
7253
7254   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7255   if (G_UNLIKELY (ret != GST_FLOW_OK))
7256     goto flow_failed;
7257   gst_buffer_map (buf, &map, GST_MAP_READ);
7258   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7259     gst_buffer_unmap (buf, &map);
7260     gst_buffer_unref (buf);
7261     buf = NULL;
7262     goto parse_failed;
7263   }
7264
7265   gst_buffer_unmap (buf, &map);
7266   gst_buffer_unref (buf);
7267   buf = NULL;
7268
7269   offset += length;
7270   /* look for next moof */
7271   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7272   if (G_UNLIKELY (ret != GST_FLOW_OK))
7273     goto flow_failed;
7274
7275 exit:
7276   GST_OBJECT_LOCK (qtdemux);
7277
7278   qtdemux->moof_offset = offset;
7279
7280   return res;
7281
7282 parse_failed:
7283   {
7284     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7285     offset = 0;
7286     res = GST_FLOW_ERROR;
7287     goto exit;
7288   }
7289 flow_failed:
7290   {
7291     /* maybe upstream temporarily flushing */
7292     if (ret != GST_FLOW_FLUSHING) {
7293       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7294       offset = 0;
7295     } else {
7296       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7297       /* resume at current position next time */
7298     }
7299     res = ret;
7300     goto exit;
7301   }
7302 }
7303
7304 /* initialise bytereaders for stbl sub-atoms */
7305 static gboolean
7306 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7307 {
7308   stream->stbl_index = -1;      /* no samples have yet been parsed */
7309   stream->sample_index = -1;
7310
7311   /* time-to-sample atom */
7312   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7313     goto corrupt_file;
7314
7315   /* copy atom data into a new buffer for later use */
7316   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7317
7318   /* skip version + flags */
7319   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7320       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7321     goto corrupt_file;
7322   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7323
7324   /* make sure there's enough data */
7325   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7326     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7327     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7328         stream->n_sample_times);
7329     if (!stream->n_sample_times)
7330       goto corrupt_file;
7331   }
7332
7333   /* sync sample atom */
7334   stream->stps_present = FALSE;
7335   if ((stream->stss_present =
7336           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7337               &stream->stss) ? TRUE : FALSE) == TRUE) {
7338     /* copy atom data into a new buffer for later use */
7339     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7340
7341     /* skip version + flags */
7342     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7343         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7344       goto corrupt_file;
7345
7346     if (stream->n_sample_syncs) {
7347       /* make sure there's enough data */
7348       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7349         goto corrupt_file;
7350     }
7351
7352     /* partial sync sample atom */
7353     if ((stream->stps_present =
7354             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7355                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7356       /* copy atom data into a new buffer for later use */
7357       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7358
7359       /* skip version + flags */
7360       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7361           !gst_byte_reader_get_uint32_be (&stream->stps,
7362               &stream->n_sample_partial_syncs))
7363         goto corrupt_file;
7364
7365       /* if there are no entries, the stss table contains the real
7366        * sync samples */
7367       if (stream->n_sample_partial_syncs) {
7368         /* make sure there's enough data */
7369         if (!qt_atom_parser_has_chunks (&stream->stps,
7370                 stream->n_sample_partial_syncs, 4))
7371           goto corrupt_file;
7372       }
7373     }
7374   }
7375
7376   /* sample size */
7377   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7378     goto no_samples;
7379
7380   /* copy atom data into a new buffer for later use */
7381   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7382
7383   /* skip version + flags */
7384   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7385       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7386     goto corrupt_file;
7387
7388   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7389     goto corrupt_file;
7390
7391   if (!stream->n_samples)
7392     goto no_samples;
7393
7394   /* sample-to-chunk atom */
7395   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7396     goto corrupt_file;
7397
7398   /* copy atom data into a new buffer for later use */
7399   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7400
7401   /* skip version + flags */
7402   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7403       !gst_byte_reader_get_uint32_be (&stream->stsc,
7404           &stream->n_samples_per_chunk))
7405     goto corrupt_file;
7406
7407   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7408       stream->n_samples_per_chunk);
7409
7410   /* make sure there's enough data */
7411   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7412           12))
7413     goto corrupt_file;
7414
7415
7416   /* chunk offset */
7417   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7418     stream->co_size = sizeof (guint32);
7419   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7420           &stream->stco))
7421     stream->co_size = sizeof (guint64);
7422   else
7423     goto corrupt_file;
7424
7425   /* copy atom data into a new buffer for later use */
7426   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7427
7428   /* skip version + flags */
7429   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7430     goto corrupt_file;
7431
7432   /* chunks_are_samples == TRUE means treat chunks as samples */
7433   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7434   if (stream->chunks_are_samples) {
7435     /* treat chunks as samples */
7436     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7437       goto corrupt_file;
7438   } else {
7439     /* skip number of entries */
7440     if (!gst_byte_reader_skip (&stream->stco, 4))
7441       goto corrupt_file;
7442
7443     /* make sure there are enough data in the stsz atom */
7444     if (!stream->sample_size) {
7445       /* different sizes for each sample */
7446       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7447         goto corrupt_file;
7448     }
7449   }
7450
7451   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7452       stream->n_samples, (guint) sizeof (QtDemuxSample),
7453       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7454
7455   if (stream->n_samples >=
7456       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7457     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7458         "be larger than %uMB (broken file?)", stream->n_samples,
7459         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7460     return FALSE;
7461   }
7462
7463   g_assert (stream->samples == NULL);
7464   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7465   if (!stream->samples) {
7466     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7467         stream->n_samples);
7468     return FALSE;
7469   }
7470
7471   /* composition time-to-sample */
7472   if ((stream->ctts_present =
7473           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7474               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7475     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7476
7477     /* copy atom data into a new buffer for later use */
7478     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7479
7480     /* skip version + flags */
7481     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7482         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7483             &stream->n_composition_times))
7484       goto corrupt_file;
7485
7486     /* make sure there's enough data */
7487     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7488             4 + 4))
7489       goto corrupt_file;
7490
7491     /* This is optional, if missing we iterate the ctts */
7492     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7493       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7494           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7495         g_free ((gpointer) cslg.data);
7496         goto corrupt_file;
7497       }
7498     } else {
7499       gint32 cslg_least = 0;
7500       guint num_entries, pos;
7501       gint i;
7502
7503       pos = gst_byte_reader_get_pos (&stream->ctts);
7504       num_entries = stream->n_composition_times;
7505
7506       stream->cslg_shift = 0;
7507
7508       for (i = 0; i < num_entries; i++) {
7509         gint32 offset;
7510
7511         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7512         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7513
7514         if (offset < cslg_least)
7515           cslg_least = offset;
7516       }
7517
7518       if (cslg_least < 0)
7519         stream->cslg_shift = ABS (cslg_least);
7520       else
7521         stream->cslg_shift = 0;
7522
7523       /* reset the reader so we can generate sample table */
7524       gst_byte_reader_set_pos (&stream->ctts, pos);
7525     }
7526   } else {
7527     /* Ensure the cslg_shift value is consistent so we can use it
7528      * unconditionnally to produce TS and Segment */
7529     stream->cslg_shift = 0;
7530   }
7531
7532   return TRUE;
7533
7534 corrupt_file:
7535   {
7536     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7537         (_("This file is corrupt and cannot be played.")), (NULL));
7538     return FALSE;
7539   }
7540 no_samples:
7541   {
7542     gst_qtdemux_stbl_free (stream);
7543     if (!qtdemux->fragmented) {
7544       /* not quite good */
7545       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
7546       return FALSE;
7547     } else {
7548       /* may pick up samples elsewhere */
7549       return TRUE;
7550     }
7551   }
7552 }
7553
7554 /* collect samples from the next sample to be parsed up to sample @n for @stream
7555  * by reading the info from @stbl
7556  *
7557  * This code can be executed from both the streaming thread and the seeking
7558  * thread so it takes the object lock to protect itself
7559  */
7560 static gboolean
7561 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
7562 {
7563   gint i, j, k;
7564   QtDemuxSample *samples, *first, *cur, *last;
7565   guint32 n_samples_per_chunk;
7566   guint32 n_samples;
7567
7568   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
7569       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
7570       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
7571
7572   n_samples = stream->n_samples;
7573
7574   if (n >= n_samples)
7575     goto out_of_samples;
7576
7577   GST_OBJECT_LOCK (qtdemux);
7578   if (n <= stream->stbl_index)
7579     goto already_parsed;
7580
7581   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
7582
7583   if (!stream->stsz.data) {
7584     /* so we already parsed and passed all the moov samples;
7585      * onto fragmented ones */
7586     g_assert (qtdemux->fragmented);
7587     goto done;
7588   }
7589
7590   /* pointer to the sample table */
7591   samples = stream->samples;
7592
7593   /* starts from -1, moves to the next sample index to parse */
7594   stream->stbl_index++;
7595
7596   /* keep track of the first and last sample to fill */
7597   first = &samples[stream->stbl_index];
7598   last = &samples[n];
7599
7600   if (!stream->chunks_are_samples) {
7601     /* set the sample sizes */
7602     if (stream->sample_size == 0) {
7603       /* different sizes for each sample */
7604       for (cur = first; cur <= last; cur++) {
7605         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
7606         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
7607             (guint) (cur - samples), cur->size);
7608       }
7609     } else {
7610       /* samples have the same size */
7611       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
7612       for (cur = first; cur <= last; cur++)
7613         cur->size = stream->sample_size;
7614     }
7615   }
7616
7617   n_samples_per_chunk = stream->n_samples_per_chunk;
7618   cur = first;
7619
7620   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
7621     guint32 last_chunk;
7622
7623     if (stream->stsc_chunk_index >= stream->last_chunk
7624         || stream->stsc_chunk_index < stream->first_chunk) {
7625       stream->first_chunk =
7626           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7627       stream->samples_per_chunk =
7628           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7629       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
7630
7631       /* chunk numbers are counted from 1 it seems */
7632       if (G_UNLIKELY (stream->first_chunk == 0))
7633         goto corrupt_file;
7634
7635       --stream->first_chunk;
7636
7637       /* the last chunk of each entry is calculated by taking the first chunk
7638        * of the next entry; except if there is no next, where we fake it with
7639        * INT_MAX */
7640       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
7641         stream->last_chunk = G_MAXUINT32;
7642       } else {
7643         stream->last_chunk =
7644             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
7645         if (G_UNLIKELY (stream->last_chunk == 0))
7646           goto corrupt_file;
7647
7648         --stream->last_chunk;
7649       }
7650
7651       GST_LOG_OBJECT (qtdemux,
7652           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
7653           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
7654
7655       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
7656         goto corrupt_file;
7657
7658       if (stream->last_chunk != G_MAXUINT32) {
7659         if (!qt_atom_parser_peek_sub (&stream->stco,
7660                 stream->first_chunk * stream->co_size,
7661                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
7662                 &stream->co_chunk))
7663           goto corrupt_file;
7664
7665       } else {
7666         stream->co_chunk = stream->stco;
7667         if (!gst_byte_reader_skip (&stream->co_chunk,
7668                 stream->first_chunk * stream->co_size))
7669           goto corrupt_file;
7670       }
7671
7672       stream->stsc_chunk_index = stream->first_chunk;
7673     }
7674
7675     last_chunk = stream->last_chunk;
7676
7677     if (stream->chunks_are_samples) {
7678       cur = &samples[stream->stsc_chunk_index];
7679
7680       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7681         if (j > n) {
7682           /* save state */
7683           stream->stsc_chunk_index = j;
7684           goto done;
7685         }
7686
7687         cur->offset =
7688             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
7689             stream->co_size);
7690
7691         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
7692             "%" G_GUINT64_FORMAT, j, cur->offset);
7693
7694         if (stream->samples_per_frame * stream->bytes_per_frame) {
7695           cur->size =
7696               (stream->samples_per_chunk * stream->n_channels) /
7697               stream->samples_per_frame * stream->bytes_per_frame;
7698         } else {
7699           cur->size = stream->samples_per_chunk;
7700         }
7701
7702         GST_DEBUG_OBJECT (qtdemux,
7703             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
7704             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
7705                     stream->stco_sample_index)), cur->size);
7706
7707         cur->timestamp = stream->stco_sample_index;
7708         cur->duration = stream->samples_per_chunk;
7709         cur->keyframe = TRUE;
7710         cur++;
7711
7712         stream->stco_sample_index += stream->samples_per_chunk;
7713       }
7714       stream->stsc_chunk_index = j;
7715     } else {
7716       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7717         guint32 samples_per_chunk;
7718         guint64 chunk_offset;
7719
7720         if (!stream->stsc_sample_index
7721             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
7722                 &stream->chunk_offset))
7723           goto corrupt_file;
7724
7725         samples_per_chunk = stream->samples_per_chunk;
7726         chunk_offset = stream->chunk_offset;
7727
7728         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
7729           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
7730               G_GUINT64_FORMAT " and size %d",
7731               (guint) (cur - samples), chunk_offset, cur->size);
7732
7733           cur->offset = chunk_offset;
7734           chunk_offset += cur->size;
7735           cur++;
7736
7737           if (G_UNLIKELY (cur > last)) {
7738             /* save state */
7739             stream->stsc_sample_index = k + 1;
7740             stream->chunk_offset = chunk_offset;
7741             stream->stsc_chunk_index = j;
7742             goto done2;
7743           }
7744         }
7745         stream->stsc_sample_index = 0;
7746       }
7747       stream->stsc_chunk_index = j;
7748     }
7749     stream->stsc_index++;
7750   }
7751
7752   if (stream->chunks_are_samples)
7753     goto ctts;
7754 done2:
7755   {
7756     guint32 n_sample_times;
7757
7758     n_sample_times = stream->n_sample_times;
7759     cur = first;
7760
7761     for (i = stream->stts_index; i < n_sample_times; i++) {
7762       guint32 stts_samples;
7763       gint32 stts_duration;
7764       gint64 stts_time;
7765
7766       if (stream->stts_sample_index >= stream->stts_samples
7767           || !stream->stts_sample_index) {
7768
7769         stream->stts_samples =
7770             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7771         stream->stts_duration =
7772             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7773
7774         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
7775             i, stream->stts_samples, stream->stts_duration);
7776
7777         stream->stts_sample_index = 0;
7778       }
7779
7780       stts_samples = stream->stts_samples;
7781       stts_duration = stream->stts_duration;
7782       stts_time = stream->stts_time;
7783
7784       for (j = stream->stts_sample_index; j < stts_samples; j++) {
7785         GST_DEBUG_OBJECT (qtdemux,
7786             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
7787             (guint) (cur - samples), j,
7788             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
7789
7790         cur->timestamp = stts_time;
7791         cur->duration = stts_duration;
7792
7793         /* avoid 32-bit wrap-around,
7794          * but still mind possible 'negative' duration */
7795         stts_time += (gint64) stts_duration;
7796         cur++;
7797
7798         if (G_UNLIKELY (cur > last)) {
7799           /* save values */
7800           stream->stts_time = stts_time;
7801           stream->stts_sample_index = j + 1;
7802           goto done3;
7803         }
7804       }
7805       stream->stts_sample_index = 0;
7806       stream->stts_time = stts_time;
7807       stream->stts_index++;
7808     }
7809     /* fill up empty timestamps with the last timestamp, this can happen when
7810      * the last samples do not decode and so we don't have timestamps for them.
7811      * We however look at the last timestamp to estimate the track length so we
7812      * need something in here. */
7813     for (; cur < last; cur++) {
7814       GST_DEBUG_OBJECT (qtdemux,
7815           "fill sample %d: timestamp %" GST_TIME_FORMAT,
7816           (guint) (cur - samples),
7817           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
7818       cur->timestamp = stream->stts_time;
7819       cur->duration = -1;
7820     }
7821   }
7822 done3:
7823   {
7824     /* sample sync, can be NULL */
7825     if (stream->stss_present == TRUE) {
7826       guint32 n_sample_syncs;
7827
7828       n_sample_syncs = stream->n_sample_syncs;
7829
7830       if (!n_sample_syncs) {
7831         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
7832         stream->all_keyframe = TRUE;
7833       } else {
7834         for (i = stream->stss_index; i < n_sample_syncs; i++) {
7835           /* note that the first sample is index 1, not 0 */
7836           guint32 index;
7837
7838           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
7839
7840           if (G_LIKELY (index > 0 && index <= n_samples)) {
7841             index -= 1;
7842             samples[index].keyframe = TRUE;
7843             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7844             /* and exit if we have enough samples */
7845             if (G_UNLIKELY (index >= n)) {
7846               i++;
7847               break;
7848             }
7849           }
7850         }
7851         /* save state */
7852         stream->stss_index = i;
7853       }
7854
7855       /* stps marks partial sync frames like open GOP I-Frames */
7856       if (stream->stps_present == TRUE) {
7857         guint32 n_sample_partial_syncs;
7858
7859         n_sample_partial_syncs = stream->n_sample_partial_syncs;
7860
7861         /* if there are no entries, the stss table contains the real
7862          * sync samples */
7863         if (n_sample_partial_syncs) {
7864           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
7865             /* note that the first sample is index 1, not 0 */
7866             guint32 index;
7867
7868             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
7869
7870             if (G_LIKELY (index > 0 && index <= n_samples)) {
7871               index -= 1;
7872               samples[index].keyframe = TRUE;
7873               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7874               /* and exit if we have enough samples */
7875               if (G_UNLIKELY (index >= n)) {
7876                 i++;
7877                 break;
7878               }
7879             }
7880           }
7881           /* save state */
7882           stream->stps_index = i;
7883         }
7884       }
7885     } else {
7886       /* no stss, all samples are keyframes */
7887       stream->all_keyframe = TRUE;
7888       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
7889     }
7890   }
7891
7892 ctts:
7893   /* composition time to sample */
7894   if (stream->ctts_present == TRUE) {
7895     guint32 n_composition_times;
7896     guint32 ctts_count;
7897     gint32 ctts_soffset;
7898
7899     /* Fill in the pts_offsets */
7900     cur = first;
7901     n_composition_times = stream->n_composition_times;
7902
7903     for (i = stream->ctts_index; i < n_composition_times; i++) {
7904       if (stream->ctts_sample_index >= stream->ctts_count
7905           || !stream->ctts_sample_index) {
7906         stream->ctts_count =
7907             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
7908         stream->ctts_soffset =
7909             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7910         stream->ctts_sample_index = 0;
7911       }
7912
7913       ctts_count = stream->ctts_count;
7914       ctts_soffset = stream->ctts_soffset;
7915
7916       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
7917         cur->pts_offset = ctts_soffset;
7918         cur++;
7919
7920         if (G_UNLIKELY (cur > last)) {
7921           /* save state */
7922           stream->ctts_sample_index = j + 1;
7923           goto done;
7924         }
7925       }
7926       stream->ctts_sample_index = 0;
7927       stream->ctts_index++;
7928     }
7929   }
7930 done:
7931   stream->stbl_index = n;
7932   /* if index has been completely parsed, free data that is no-longer needed */
7933   if (n + 1 == stream->n_samples) {
7934     gst_qtdemux_stbl_free (stream);
7935     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
7936     if (qtdemux->pullbased) {
7937       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
7938       while (n + 1 == stream->n_samples)
7939         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
7940           break;
7941     }
7942   }
7943   GST_OBJECT_UNLOCK (qtdemux);
7944
7945   return TRUE;
7946
7947   /* SUCCESS */
7948 already_parsed:
7949   {
7950     GST_LOG_OBJECT (qtdemux,
7951         "Tried to parse up to sample %u but this sample has already been parsed",
7952         n);
7953     /* if fragmented, there may be more */
7954     if (qtdemux->fragmented && n == stream->stbl_index)
7955       goto done;
7956     GST_OBJECT_UNLOCK (qtdemux);
7957     return TRUE;
7958   }
7959   /* ERRORS */
7960 out_of_samples:
7961   {
7962     GST_LOG_OBJECT (qtdemux,
7963         "Tried to parse up to sample %u but there are only %u samples", n + 1,
7964         stream->n_samples);
7965     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7966         (_("This file is corrupt and cannot be played.")), (NULL));
7967     return FALSE;
7968   }
7969 corrupt_file:
7970   {
7971     GST_OBJECT_UNLOCK (qtdemux);
7972     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7973         (_("This file is corrupt and cannot be played.")), (NULL));
7974     return FALSE;
7975   }
7976 }
7977
7978 /* collect all segment info for @stream.
7979  */
7980 static gboolean
7981 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
7982     GNode * trak)
7983 {
7984   GNode *edts;
7985   /* accept edts if they contain gaps at start and there is only
7986    * one media segment */
7987   gboolean allow_pushbased_edts = TRUE;
7988   gint media_segments_count = 0;
7989
7990   /* parse and prepare segment info from the edit list */
7991   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
7992   stream->n_segments = 0;
7993   stream->segments = NULL;
7994   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
7995     GNode *elst;
7996     gint n_segments;
7997     gint i, count;
7998     guint64 time;
7999     GstClockTime stime;
8000     guint8 *buffer;
8001
8002     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8003     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8004       goto done;
8005
8006     buffer = elst->data;
8007
8008     n_segments = QT_UINT32 (buffer + 12);
8009
8010     /* we might allocate a bit too much, at least allocate 1 segment */
8011     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8012
8013     /* segments always start from 0 */
8014     time = 0;
8015     stime = 0;
8016     count = 0;
8017     for (i = 0; i < n_segments; i++) {
8018       guint64 duration;
8019       guint64 media_time;
8020       QtDemuxSegment *segment;
8021       guint32 rate_int;
8022
8023       media_time = QT_UINT32 (buffer + 20 + i * 12);
8024       duration = QT_UINT32 (buffer + 16 + i * 12);
8025
8026       segment = &stream->segments[count++];
8027
8028       /* time and duration expressed in global timescale */
8029       segment->time = stime;
8030       /* add non scaled values so we don't cause roundoff errors */
8031       time += duration;
8032       stime = QTTIME_TO_GSTTIME (qtdemux, time);
8033       segment->stop_time = stime;
8034       segment->duration = stime - segment->time;
8035
8036       segment->trak_media_start = media_time;
8037       /* media_time expressed in stream timescale */
8038       if (media_time != G_MAXUINT32) {
8039         segment->media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8040         segment->media_stop = segment->media_start + segment->duration;
8041         media_segments_count++;
8042       } else {
8043         segment->media_start = GST_CLOCK_TIME_NONE;
8044         segment->media_stop = GST_CLOCK_TIME_NONE;
8045       }
8046       rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
8047
8048       if (rate_int <= 1) {
8049         /* 0 is not allowed, some programs write 1 instead of the floating point
8050          * value */
8051         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8052             rate_int);
8053         segment->rate = 1;
8054       } else {
8055         segment->rate = rate_int / 65536.0;
8056       }
8057
8058       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8059           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8060           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8061           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8062           i, GST_TIME_ARGS (segment->time),
8063           GST_TIME_ARGS (segment->duration),
8064           GST_TIME_ARGS (segment->media_start), media_time,
8065           GST_TIME_ARGS (segment->media_stop),
8066           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8067           stream->timescale);
8068       if (segment->stop_time > qtdemux->segment.stop) {
8069         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8070             " extends to %" GST_TIME_FORMAT
8071             " past the end of the file duration %" GST_TIME_FORMAT
8072             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8073             GST_TIME_ARGS (qtdemux->segment.stop));
8074         qtdemux->segment.stop = segment->stop_time;
8075       }
8076     }
8077     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8078     stream->n_segments = count;
8079     if (media_segments_count != 1)
8080       allow_pushbased_edts = FALSE;
8081   }
8082 done:
8083
8084   /* push based does not handle segments, so act accordingly here,
8085    * and warn if applicable */
8086   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8087     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8088     /* remove and use default one below, we stream like it anyway */
8089     g_free (stream->segments);
8090     stream->segments = NULL;
8091     stream->n_segments = 0;
8092   }
8093
8094   /* no segments, create one to play the complete trak */
8095   if (stream->n_segments == 0) {
8096     GstClockTime stream_duration =
8097         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8098
8099     if (stream->segments == NULL)
8100       stream->segments = g_new (QtDemuxSegment, 1);
8101
8102     /* represent unknown our way */
8103     if (stream_duration == 0)
8104       stream_duration = GST_CLOCK_TIME_NONE;
8105
8106     stream->segments[0].time = 0;
8107     stream->segments[0].stop_time = stream_duration;
8108     stream->segments[0].duration = stream_duration;
8109     stream->segments[0].media_start = 0;
8110     stream->segments[0].media_stop = stream_duration;
8111     stream->segments[0].rate = 1.0;
8112     stream->segments[0].trak_media_start = 0;
8113
8114     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8115         GST_TIME_ARGS (stream_duration));
8116     stream->n_segments = 1;
8117     stream->dummy_segment = TRUE;
8118   }
8119   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8120
8121   return TRUE;
8122 }
8123
8124 /*
8125  * Parses the stsd atom of a svq3 trak looking for
8126  * the SMI and gama atoms.
8127  */
8128 static void
8129 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8130     guint8 ** gamma, GstBuffer ** seqh)
8131 {
8132   guint8 *_gamma = NULL;
8133   GstBuffer *_seqh = NULL;
8134   guint8 *stsd_data = stsd->data;
8135   guint32 length = QT_UINT32 (stsd_data);
8136   guint16 version;
8137
8138   if (length < 32) {
8139     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8140     goto end;
8141   }
8142
8143   stsd_data += 32;
8144   length -= 32;
8145   version = QT_UINT16 (stsd_data);
8146   if (version == 3) {
8147     if (length >= 70) {
8148       length -= 70;
8149       stsd_data += 70;
8150       while (length > 8) {
8151         guint32 fourcc, size;
8152         guint8 *data;
8153         size = QT_UINT32 (stsd_data);
8154         fourcc = QT_FOURCC (stsd_data + 4);
8155         data = stsd_data + 8;
8156
8157         if (size == 0) {
8158           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8159               "svq3 atom parsing");
8160           goto end;
8161         }
8162
8163         switch (fourcc) {
8164           case FOURCC_gama:{
8165             if (size == 12) {
8166               _gamma = data;
8167             } else {
8168               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8169                   " for gama atom, expected 12", size);
8170             }
8171             break;
8172           }
8173           case FOURCC_SMI_:{
8174             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8175               guint32 seqh_size;
8176               if (_seqh != NULL) {
8177                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8178                     " found, ignoring");
8179               } else {
8180                 seqh_size = QT_UINT32 (data + 4);
8181                 if (seqh_size > 0) {
8182                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8183                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8184                 }
8185               }
8186             }
8187             break;
8188           }
8189           default:{
8190             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8191                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8192           }
8193         }
8194
8195         if (size <= length) {
8196           length -= size;
8197           stsd_data += size;
8198         }
8199       }
8200     } else {
8201       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8202     }
8203   } else {
8204     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8205         G_GUINT16_FORMAT, version);
8206     goto end;
8207   }
8208
8209 end:
8210   if (gamma) {
8211     *gamma = _gamma;
8212   }
8213   if (seqh) {
8214     *seqh = _seqh;
8215   } else if (_seqh) {
8216     gst_buffer_unref (_seqh);
8217   }
8218 }
8219
8220 static gchar *
8221 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8222 {
8223   GNode *dinf;
8224   GstByteReader dref;
8225   gchar *uri = NULL;
8226
8227   /*
8228    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8229    * atom that might contain a 'data' atom with the rtsp uri.
8230    * This case was reported in bug #597497, some info about
8231    * the hndl atom can be found in TN1195
8232    */
8233   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8234   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8235
8236   if (dinf) {
8237     guint32 dref_num_entries = 0;
8238     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8239         gst_byte_reader_skip (&dref, 4) &&
8240         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8241       gint i;
8242
8243       /* search dref entries for hndl atom */
8244       for (i = 0; i < dref_num_entries; i++) {
8245         guint32 size = 0, type;
8246         guint8 string_len = 0;
8247         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8248             qt_atom_parser_get_fourcc (&dref, &type)) {
8249           if (type == FOURCC_hndl) {
8250             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8251
8252             /* skip data reference handle bytes and the
8253              * following pascal string and some extra 4
8254              * bytes I have no idea what are */
8255             if (!gst_byte_reader_skip (&dref, 4) ||
8256                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8257                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8258               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8259               break;
8260             }
8261
8262             /* iterate over the atoms to find the data atom */
8263             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8264               guint32 atom_size;
8265               guint32 atom_type;
8266
8267               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8268                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8269                 if (atom_type == FOURCC_data) {
8270                   const guint8 *uri_aux = NULL;
8271
8272                   /* found the data atom that might contain the rtsp uri */
8273                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8274                       "hndl atom, interpreting it as an URI");
8275                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8276                           &uri_aux)) {
8277                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8278                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8279                     else
8280                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8281                           "didn't contain a rtsp address");
8282                   } else {
8283                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8284                         "atom contents");
8285                   }
8286                   break;
8287                 }
8288                 /* skipping to the next entry */
8289                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8290                   break;
8291               } else {
8292                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8293                     "atom header");
8294                 break;
8295               }
8296             }
8297             break;
8298           }
8299           /* skip to the next entry */
8300           if (!gst_byte_reader_skip (&dref, size - 8))
8301             break;
8302         } else {
8303           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8304         }
8305       }
8306       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8307     }
8308   }
8309   return uri;
8310 }
8311
8312 #define AMR_NB_ALL_MODES        0x81ff
8313 #define AMR_WB_ALL_MODES        0x83ff
8314 static guint
8315 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8316 {
8317   /* The 'damr' atom is of the form:
8318    *
8319    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8320    *    32 b       8 b          16 b           8 b                 8 b
8321    *
8322    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8323    * represents the highest mode used in the stream (and thus the maximum
8324    * bitrate), with a couple of special cases as seen below.
8325    */
8326
8327   /* Map of frame type ID -> bitrate */
8328   static const guint nb_bitrates[] = {
8329     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8330   };
8331   static const guint wb_bitrates[] = {
8332     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8333   };
8334   GstMapInfo map;
8335   gsize max_mode;
8336   guint16 mode_set;
8337
8338   gst_buffer_map (buf, &map, GST_MAP_READ);
8339
8340   if (map.size != 0x11) {
8341     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8342     goto bad_data;
8343   }
8344
8345   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8346     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8347         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8348     goto bad_data;
8349   }
8350
8351   mode_set = QT_UINT16 (map.data + 13);
8352
8353   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8354     max_mode = 7 + (wb ? 1 : 0);
8355   else
8356     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8357     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8358
8359   if (max_mode == -1) {
8360     GST_DEBUG ("No mode indication was found (mode set) = %x",
8361         (guint) mode_set);
8362     goto bad_data;
8363   }
8364
8365   gst_buffer_unmap (buf, &map);
8366   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8367
8368 bad_data:
8369   gst_buffer_unmap (buf, &map);
8370   return 0;
8371 }
8372
8373 static gboolean
8374 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8375     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8376 {
8377   /*
8378    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8379    * [0 1 2]
8380    * [3 4 5]
8381    * [6 7 8]
8382    */
8383
8384   if (gst_byte_reader_get_remaining (reader) < 36)
8385     return FALSE;
8386
8387   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8388   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8389   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8390   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8391   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8392   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8393   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8394   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8395   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8396
8397   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8398   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8399       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8400       matrix[2] & 0xFF);
8401   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8402       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8403       matrix[5] & 0xFF);
8404   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8405       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8406       matrix[8] & 0xFF);
8407
8408   return TRUE;
8409 }
8410
8411 static void
8412 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8413     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8414 {
8415
8416 /* [a b c]
8417  * [d e f]
8418  * [g h i]
8419  *
8420  * This macro will only compare value abdegh, it expects cfi to have already
8421  * been checked
8422  */
8423 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8424                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8425
8426   /* only handle the cases where the last column has standard values */
8427   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8428     const gchar *rotation_tag = NULL;
8429
8430     /* no rotation needed */
8431     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8432       /* NOP */
8433     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8434       rotation_tag = "rotate-90";
8435     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8436       rotation_tag = "rotate-180";
8437     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8438       rotation_tag = "rotate-270";
8439     } else {
8440       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8441     }
8442
8443     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8444         rotation_tag);
8445     if (rotation_tag != NULL) {
8446       if (*taglist == NULL)
8447         *taglist = gst_tag_list_new_empty ();
8448       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8449           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8450     }
8451   } else {
8452     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8453   }
8454 }
8455
8456 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8457  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8458  * Common Encryption (cenc), the function will also parse the tenc box (defined
8459  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8460  * (typically an enc[v|a|t|s] sample entry); the function will set
8461  * @original_fmt to the fourcc of the original unencrypted stream format.
8462  * Returns TRUE if successful; FALSE otherwise. */
8463 static gboolean
8464 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8465     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8466 {
8467   GNode *sinf;
8468   GNode *frma;
8469   GNode *schm;
8470   GNode *schi;
8471
8472   g_return_val_if_fail (qtdemux != NULL, FALSE);
8473   g_return_val_if_fail (stream != NULL, FALSE);
8474   g_return_val_if_fail (container != NULL, FALSE);
8475   g_return_val_if_fail (original_fmt != NULL, FALSE);
8476
8477   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8478   if (G_UNLIKELY (!sinf)) {
8479     if (stream->protection_scheme_type == FOURCC_cenc) {
8480       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8481           "mandatory for Common Encryption");
8482       return FALSE;
8483     }
8484     return TRUE;
8485   }
8486
8487   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8488   if (G_UNLIKELY (!frma)) {
8489     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8490     return FALSE;
8491   }
8492
8493   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8494   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8495       GST_FOURCC_ARGS (*original_fmt));
8496
8497   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8498   if (!schm) {
8499     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8500     return FALSE;
8501   }
8502   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
8503   stream->protection_scheme_version =
8504       QT_UINT32 ((const guint8 *) schm->data + 16);
8505
8506   GST_DEBUG_OBJECT (qtdemux,
8507       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
8508       "protection_scheme_version: %#010x",
8509       GST_FOURCC_ARGS (stream->protection_scheme_type),
8510       stream->protection_scheme_version);
8511
8512   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
8513   if (!schi) {
8514     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
8515     return FALSE;
8516   }
8517   if (stream->protection_scheme_type == FOURCC_cenc) {
8518     QtDemuxCencSampleSetInfo *info;
8519     GNode *tenc;
8520     const guint8 *tenc_data;
8521     guint32 isEncrypted;
8522     guint8 iv_size;
8523     const guint8 *default_kid;
8524     GstBuffer *kid_buf;
8525
8526     if (G_UNLIKELY (!stream->protection_scheme_info))
8527       stream->protection_scheme_info =
8528           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
8529
8530     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
8531
8532     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
8533     if (!tenc) {
8534       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
8535           "which is mandatory for Common Encryption");
8536       return FALSE;
8537     }
8538     tenc_data = (const guint8 *) tenc->data + 12;
8539     isEncrypted = QT_UINT24 (tenc_data);
8540     iv_size = QT_UINT8 (tenc_data + 3);
8541     default_kid = (tenc_data + 4);
8542     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
8543     gst_buffer_fill (kid_buf, 0, default_kid, 16);
8544     if (info->default_properties)
8545       gst_structure_free (info->default_properties);
8546     info->default_properties =
8547         gst_structure_new ("application/x-cenc",
8548         "iv_size", G_TYPE_UINT, iv_size,
8549         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
8550         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
8551     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
8552         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
8553     gst_buffer_unref (kid_buf);
8554   }
8555   return TRUE;
8556 }
8557
8558 /* parse the traks.
8559  * With each track we associate a new QtDemuxStream that contains all the info
8560  * about the trak.
8561  * traks that do not decode to something (like strm traks) will not have a pad.
8562  */
8563 static gboolean
8564 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
8565 {
8566   GstByteReader tkhd;
8567   int offset;
8568   GNode *mdia;
8569   GNode *mdhd;
8570   GNode *hdlr;
8571   GNode *minf;
8572   GNode *stbl;
8573   GNode *stsd;
8574   GNode *mp4a;
8575   GNode *mp4v;
8576   GNode *wave;
8577   GNode *esds;
8578   GNode *pasp;
8579   GNode *tref;
8580   GNode *udta;
8581   GNode *svmi;
8582
8583   QtDemuxStream *stream = NULL;
8584   gboolean new_stream = FALSE;
8585   gchar *codec = NULL;
8586   const guint8 *stsd_data;
8587   guint16 lang_code;            /* quicktime lang code or packed iso code */
8588   guint32 version;
8589   guint32 tkhd_flags = 0;
8590   guint8 tkhd_version = 0;
8591   guint32 fourcc;
8592   guint value_size, stsd_len, len;
8593   guint32 track_id;
8594   guint32 dummy;
8595
8596   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
8597
8598   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
8599       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
8600       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
8601     goto corrupt_file;
8602
8603   /* pick between 64 or 32 bits */
8604   value_size = tkhd_version == 1 ? 8 : 4;
8605   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
8606       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
8607     goto corrupt_file;
8608
8609   if (!qtdemux->got_moov) {
8610     if (qtdemux_find_stream (qtdemux, track_id))
8611       goto existing_stream;
8612     stream = _create_stream ();
8613     stream->track_id = track_id;
8614     new_stream = TRUE;
8615   } else {
8616     stream = qtdemux_find_stream (qtdemux, track_id);
8617     if (!stream) {
8618       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
8619       goto skip_track;
8620     }
8621
8622     /* flush samples data from this track from previous moov */
8623     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
8624     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
8625   }
8626   /* need defaults for fragments */
8627   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
8628
8629   if (stream->pending_tags == NULL)
8630     stream->pending_tags = gst_tag_list_new_empty ();
8631
8632   if ((tkhd_flags & 1) == 0)
8633     stream->disabled = TRUE;
8634
8635   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
8636       tkhd_version, tkhd_flags, stream->track_id);
8637
8638   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
8639     goto corrupt_file;
8640
8641   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
8642     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
8643     if (qtdemux->major_brand != FOURCC_mjp2 ||
8644         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
8645       goto corrupt_file;
8646   }
8647
8648   len = QT_UINT32 ((guint8 *) mdhd->data);
8649   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
8650   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
8651   if (version == 0x01000000) {
8652     if (len < 38)
8653       goto corrupt_file;
8654     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
8655     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
8656     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
8657   } else {
8658     if (len < 30)
8659       goto corrupt_file;
8660     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
8661     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
8662     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
8663   }
8664
8665   if (lang_code < 0x400) {
8666     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
8667   } else if (lang_code == 0x7fff) {
8668     stream->lang_id[0] = 0;     /* unspecified */
8669   } else {
8670     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
8671     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
8672     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
8673     stream->lang_id[3] = 0;
8674   }
8675
8676   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
8677       stream->timescale);
8678   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
8679       stream->duration);
8680   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
8681       lang_code, stream->lang_id);
8682
8683   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
8684     goto corrupt_file;
8685
8686   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
8687     /* chapters track reference */
8688     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
8689     if (chap) {
8690       gsize length = GST_READ_UINT32_BE (chap->data);
8691       if (qtdemux->chapters_track_id)
8692         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
8693
8694       if (length >= 12) {
8695         qtdemux->chapters_track_id =
8696             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
8697       }
8698     }
8699   }
8700
8701   /* fragmented files may have bogus duration in moov */
8702   if (!qtdemux->fragmented &&
8703       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
8704     guint64 tdur1, tdur2;
8705
8706     /* don't overflow */
8707     tdur1 = stream->timescale * (guint64) qtdemux->duration;
8708     tdur2 = qtdemux->timescale * (guint64) stream->duration;
8709
8710     /* HACK:
8711      * some of those trailers, nowadays, have prologue images that are
8712      * themselves vide tracks as well. I haven't really found a way to
8713      * identify those yet, except for just looking at their duration. */
8714     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
8715       GST_WARNING_OBJECT (qtdemux,
8716           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
8717           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
8718           "found, assuming preview image or something; skipping track",
8719           stream->duration, stream->timescale, qtdemux->duration,
8720           qtdemux->timescale);
8721       if (new_stream)
8722         gst_qtdemux_stream_free (qtdemux, stream);
8723       return TRUE;
8724     }
8725   }
8726
8727   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
8728     goto corrupt_file;
8729
8730   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
8731       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
8732
8733   len = QT_UINT32 ((guint8 *) hdlr->data);
8734   if (len >= 20)
8735     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
8736   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
8737       GST_FOURCC_ARGS (stream->subtype));
8738
8739   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
8740     goto corrupt_file;
8741
8742   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
8743     goto corrupt_file;
8744
8745   /*parse svmi header if existing */
8746   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
8747   if (svmi) {
8748     len = QT_UINT32 ((guint8 *) svmi->data);
8749     version = QT_UINT32 ((guint8 *) svmi->data + 8);
8750     if (!version) {
8751       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
8752       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
8753       guint8 frame_type, frame_layout;
8754
8755       /* MPEG-A stereo video */
8756       if (qtdemux->major_brand == FOURCC_ss02)
8757         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
8758
8759       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
8760       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
8761       switch (frame_type) {
8762         case 0:
8763           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
8764           break;
8765         case 1:
8766           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
8767           break;
8768         case 2:
8769           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
8770           break;
8771         case 3:
8772           /* mode 3 is primary/secondary view sequence, ie
8773            * left/right views in separate tracks. See section 7.2
8774            * of ISO/IEC 23000-11:2009 */
8775           GST_FIXME_OBJECT (qtdemux,
8776               "Implement stereo video in separate streams");
8777       }
8778
8779       if ((frame_layout & 0x1) == 0)
8780         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
8781
8782       GST_LOG_OBJECT (qtdemux,
8783           "StereoVideo: composition type: %u, is_left_first: %u",
8784           frame_type, frame_layout);
8785       stream->multiview_mode = mode;
8786       stream->multiview_flags = flags;
8787     }
8788   }
8789
8790   /* parse stsd */
8791   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
8792     goto corrupt_file;
8793   stsd_data = (const guint8 *) stsd->data;
8794
8795   /* stsd should at least have one entry */
8796   stsd_len = QT_UINT32 (stsd_data);
8797   if (stsd_len < 24) {
8798     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
8799     if (stream->subtype == FOURCC_vivo) {
8800       if (new_stream)
8801         gst_qtdemux_stream_free (qtdemux, stream);
8802       return TRUE;
8803     } else {
8804       goto corrupt_file;
8805     }
8806   }
8807
8808   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
8809
8810   /* and that entry should fit within stsd */
8811   len = QT_UINT32 (stsd_data + 16);
8812   if (len > stsd_len + 16)
8813     goto corrupt_file;
8814
8815   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
8816   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
8817       GST_FOURCC_ARGS (stream->fourcc));
8818   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
8819
8820   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
8821     goto error_encrypted;
8822
8823   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
8824     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
8825     stream->protected = TRUE;
8826     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
8827       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
8828   }
8829
8830   if (stream->subtype == FOURCC_vide) {
8831     guint32 w = 0, h = 0;
8832     gboolean gray;
8833     gint depth, palette_size, palette_count;
8834     guint32 matrix[9];
8835     guint32 *palette_data = NULL;
8836
8837     stream->sampled = TRUE;
8838
8839     /* version 1 uses some 64-bit ints */
8840     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
8841       goto corrupt_file;
8842
8843     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
8844       goto corrupt_file;
8845
8846     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
8847         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
8848       goto corrupt_file;
8849
8850     stream->display_width = w >> 16;
8851     stream->display_height = h >> 16;
8852
8853     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
8854         &stream->pending_tags);
8855
8856     offset = 16;
8857     if (len < 86)
8858       goto corrupt_file;
8859
8860     stream->width = QT_UINT16 (stsd_data + offset + 32);
8861     stream->height = QT_UINT16 (stsd_data + offset + 34);
8862     stream->fps_n = 0;          /* this is filled in later */
8863     stream->fps_d = 0;          /* this is filled in later */
8864     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
8865     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
8866
8867     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
8868         stream->width, stream->height, stream->bits_per_sample,
8869         stream->color_table_id);
8870
8871     depth = stream->bits_per_sample;
8872
8873     /* more than 32 bits means grayscale */
8874     gray = (depth > 32);
8875     /* low 32 bits specify the depth  */
8876     depth &= 0x1F;
8877
8878     /* different number of palette entries is determined by depth. */
8879     palette_count = 0;
8880     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
8881       palette_count = (1 << depth);
8882     palette_size = palette_count * 4;
8883
8884     if (stream->color_table_id) {
8885       switch (palette_count) {
8886         case 0:
8887           break;
8888         case 2:
8889           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
8890           break;
8891         case 4:
8892           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
8893           break;
8894         case 16:
8895           if (gray)
8896             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
8897           else
8898             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
8899           break;
8900         case 256:
8901           if (gray)
8902             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
8903           else
8904             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
8905           break;
8906         default:
8907           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
8908               (_("The video in this file might not play correctly.")),
8909               ("unsupported palette depth %d", depth));
8910           break;
8911       }
8912     } else {
8913       gint i, j, start, end;
8914
8915       if (len < 94)
8916         goto corrupt_file;
8917
8918       /* read table */
8919       start = QT_UINT32 (stsd_data + offset + 86);
8920       palette_count = QT_UINT16 (stsd_data + offset + 90);
8921       end = QT_UINT16 (stsd_data + offset + 92);
8922
8923       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
8924           start, end, palette_count);
8925
8926       if (end > 255)
8927         end = 255;
8928       if (start > end)
8929         start = end;
8930
8931       if (len < 94 + (end - start) * 8)
8932         goto corrupt_file;
8933
8934       /* palette is always the same size */
8935       palette_data = g_malloc0 (256 * 4);
8936       palette_size = 256 * 4;
8937
8938       for (j = 0, i = start; i <= end; j++, i++) {
8939         guint32 a, r, g, b;
8940
8941         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
8942         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
8943         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
8944         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
8945
8946         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
8947             (g & 0xff00) | (b >> 8);
8948       }
8949     }
8950
8951     if (stream->caps)
8952       gst_caps_unref (stream->caps);
8953
8954     stream->caps =
8955         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
8956     if (G_UNLIKELY (!stream->caps)) {
8957       g_free (palette_data);
8958       goto unknown_stream;
8959     }
8960
8961     if (codec) {
8962       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
8963           GST_TAG_VIDEO_CODEC, codec, NULL);
8964       g_free (codec);
8965       codec = NULL;
8966     }
8967
8968
8969     if (palette_data) {
8970       GstStructure *s;
8971
8972       if (stream->rgb8_palette)
8973         gst_memory_unref (stream->rgb8_palette);
8974       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
8975           palette_data, palette_size, 0, palette_size, palette_data, g_free);
8976
8977       s = gst_caps_get_structure (stream->caps, 0);
8978
8979       /* non-raw video has a palette_data property. raw video has the palette as
8980        * an extra plane that we append to the output buffers before we push
8981        * them*/
8982       if (!gst_structure_has_name (s, "video/x-raw")) {
8983         GstBuffer *palette;
8984
8985         palette = gst_buffer_new ();
8986         gst_buffer_append_memory (palette, stream->rgb8_palette);
8987         stream->rgb8_palette = NULL;
8988
8989         gst_caps_set_simple (stream->caps, "palette_data",
8990             GST_TYPE_BUFFER, palette, NULL);
8991         gst_buffer_unref (palette);
8992       }
8993     } else if (palette_count != 0) {
8994       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
8995           (NULL), ("Unsupported palette depth %d", depth));
8996     }
8997
8998     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
8999         QT_UINT16 (stsd_data + offset + 48));
9000
9001     esds = NULL;
9002     pasp = NULL;
9003     /* pick 'the' stsd child */
9004     if (!stream->protected)
9005       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9006     else
9007       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9008
9009     if (mp4v) {
9010       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9011       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9012     }
9013
9014     if (pasp) {
9015       const guint8 *pasp_data = (const guint8 *) pasp->data;
9016
9017       stream->par_w = QT_UINT32 (pasp_data + 8);
9018       stream->par_h = QT_UINT32 (pasp_data + 12);
9019     } else {
9020       stream->par_w = 0;
9021       stream->par_h = 0;
9022     }
9023
9024     if (esds) {
9025       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9026     } else {
9027       switch (fourcc) {
9028         case FOURCC_H264:
9029         case FOURCC_avc1:
9030         case FOURCC_avc3:
9031         {
9032           gint len = QT_UINT32 (stsd_data) - 0x66;
9033           const guint8 *avc_data = stsd_data + 0x66;
9034
9035           /* find avcC */
9036           while (len >= 0x8) {
9037             gint size;
9038
9039             if (QT_UINT32 (avc_data) <= len)
9040               size = QT_UINT32 (avc_data) - 0x8;
9041             else
9042               size = len - 0x8;
9043
9044             if (size < 1)
9045               /* No real data, so break out */
9046               break;
9047
9048             switch (QT_FOURCC (avc_data + 0x4)) {
9049               case FOURCC_avcC:
9050               {
9051                 /* parse, if found */
9052                 GstBuffer *buf;
9053
9054                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9055
9056                 /* First 4 bytes are the length of the atom, the next 4 bytes
9057                  * are the fourcc, the next 1 byte is the version, and the
9058                  * subsequent bytes are profile_tier_level structure like data. */
9059                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9060                     avc_data + 8 + 1, size - 1);
9061                 buf = gst_buffer_new_and_alloc (size);
9062                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9063                 gst_caps_set_simple (stream->caps,
9064                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9065                 gst_buffer_unref (buf);
9066
9067                 break;
9068               }
9069               case FOURCC_strf:
9070               {
9071                 GstBuffer *buf;
9072
9073                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9074
9075                 /* First 4 bytes are the length of the atom, the next 4 bytes
9076                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9077                  * next 1 byte is the version, and the
9078                  * subsequent bytes are sequence parameter set like data. */
9079
9080                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9081                 if (size > 1) {
9082                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9083                       avc_data + 8 + 40 + 1, size - 1);
9084
9085                   buf = gst_buffer_new_and_alloc (size);
9086                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9087                   gst_caps_set_simple (stream->caps,
9088                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9089                   gst_buffer_unref (buf);
9090                 }
9091                 break;
9092               }
9093               case FOURCC_btrt:
9094               {
9095                 guint avg_bitrate, max_bitrate;
9096
9097                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9098                 if (size < 12)
9099                   break;
9100
9101                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9102                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9103
9104                 if (!max_bitrate && !avg_bitrate)
9105                   break;
9106
9107                 /* Some muxers seem to swap the average and maximum bitrates
9108                  * (I'm looking at you, YouTube), so we swap for sanity. */
9109                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9110                   guint temp = avg_bitrate;
9111
9112                   avg_bitrate = max_bitrate;
9113                   max_bitrate = temp;
9114                 }
9115
9116                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9117                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9118                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9119                 }
9120                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9121                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9122                       GST_TAG_BITRATE, avg_bitrate, NULL);
9123                 }
9124
9125                 break;
9126               }
9127
9128               default:
9129                 break;
9130             }
9131
9132             len -= size + 8;
9133             avc_data += size + 8;
9134           }
9135
9136           break;
9137         }
9138         case FOURCC_H265:
9139         case FOURCC_hvc1:
9140         case FOURCC_hev1:
9141         {
9142           gint len = QT_UINT32 (stsd_data) - 0x66;
9143           const guint8 *hevc_data = stsd_data + 0x66;
9144
9145           /* find hevc */
9146           while (len >= 0x8) {
9147             gint size;
9148
9149             if (QT_UINT32 (hevc_data) <= len)
9150               size = QT_UINT32 (hevc_data) - 0x8;
9151             else
9152               size = len - 0x8;
9153
9154             if (size < 1)
9155               /* No real data, so break out */
9156               break;
9157
9158             switch (QT_FOURCC (hevc_data + 0x4)) {
9159               case FOURCC_hvcC:
9160               {
9161                 /* parse, if found */
9162                 GstBuffer *buf;
9163
9164                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9165
9166                 /* First 4 bytes are the length of the atom, the next 4 bytes
9167                  * are the fourcc, the next 1 byte is the version, and the
9168                  * subsequent bytes are sequence parameter set like data. */
9169                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9170                     (stream->caps, hevc_data + 8 + 1, size - 1);
9171
9172                 buf = gst_buffer_new_and_alloc (size);
9173                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9174                 gst_caps_set_simple (stream->caps,
9175                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9176                 gst_buffer_unref (buf);
9177                 break;
9178               }
9179               default:
9180                 break;
9181             }
9182             len -= size + 8;
9183             hevc_data += size + 8;
9184           }
9185           break;
9186         }
9187         case FOURCC_mp4v:
9188         case FOURCC_MP4V:
9189         case FOURCC_fmp4:
9190         case FOURCC_FMP4:
9191         {
9192           GNode *glbl;
9193
9194           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9195               GST_FOURCC_ARGS (fourcc));
9196
9197           /* codec data might be in glbl extension atom */
9198           glbl = mp4v ?
9199               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9200           if (glbl) {
9201             guint8 *data;
9202             GstBuffer *buf;
9203             gint len;
9204
9205             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9206             data = glbl->data;
9207             len = QT_UINT32 (data);
9208             if (len > 0x8) {
9209               len -= 0x8;
9210               buf = gst_buffer_new_and_alloc (len);
9211               gst_buffer_fill (buf, 0, data + 8, len);
9212               gst_caps_set_simple (stream->caps,
9213                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9214               gst_buffer_unref (buf);
9215             }
9216           }
9217           break;
9218         }
9219         case FOURCC_mjp2:
9220         {
9221           /* see annex I of the jpeg2000 spec */
9222           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9223           const guint8 *data;
9224           const gchar *colorspace = NULL;
9225           gint ncomp = 0;
9226           guint32 ncomp_map = 0;
9227           gint32 *comp_map = NULL;
9228           guint32 nchan_def = 0;
9229           gint32 *chan_def = NULL;
9230
9231           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9232           /* some required atoms */
9233           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9234           if (!mjp2)
9235             break;
9236           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9237           if (!jp2h)
9238             break;
9239
9240           /* number of components; redundant with info in codestream, but useful
9241              to a muxer */
9242           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9243           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9244             break;
9245           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9246
9247           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9248           if (!colr)
9249             break;
9250           GST_DEBUG_OBJECT (qtdemux, "found colr");
9251           /* extract colour space info */
9252           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9253             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9254               case 16:
9255                 colorspace = "sRGB";
9256                 break;
9257               case 17:
9258                 colorspace = "GRAY";
9259                 break;
9260               case 18:
9261                 colorspace = "sYUV";
9262                 break;
9263               default:
9264                 colorspace = NULL;
9265                 break;
9266             }
9267           }
9268           if (!colorspace)
9269             /* colr is required, and only values 16, 17, and 18 are specified,
9270                so error if we have no colorspace */
9271             break;
9272
9273           /* extract component mapping */
9274           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9275           if (cmap) {
9276             guint32 cmap_len = 0;
9277             int i;
9278             cmap_len = QT_UINT32 (cmap->data);
9279             if (cmap_len >= 8) {
9280               /* normal box, subtract off header */
9281               cmap_len -= 8;
9282               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9283               if (cmap_len % 4 == 0) {
9284                 ncomp_map = (cmap_len / 4);
9285                 comp_map = g_new0 (gint32, ncomp_map);
9286                 for (i = 0; i < ncomp_map; i++) {
9287                   guint16 cmp;
9288                   guint8 mtyp, pcol;
9289                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9290                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9291                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9292                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9293                 }
9294               }
9295             }
9296           }
9297           /* extract channel definitions */
9298           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9299           if (cdef) {
9300             guint32 cdef_len = 0;
9301             int i;
9302             cdef_len = QT_UINT32 (cdef->data);
9303             if (cdef_len >= 10) {
9304               /* normal box, subtract off header and len */
9305               cdef_len -= 10;
9306               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9307               if (cdef_len % 6 == 0) {
9308                 nchan_def = (cdef_len / 6);
9309                 chan_def = g_new0 (gint32, nchan_def);
9310                 for (i = 0; i < nchan_def; i++)
9311                   chan_def[i] = -1;
9312                 for (i = 0; i < nchan_def; i++) {
9313                   guint16 cn, typ, asoc;
9314                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9315                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9316                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9317                   if (cn < nchan_def) {
9318                     switch (typ) {
9319                       case 0:
9320                         chan_def[cn] = asoc;
9321                         break;
9322                       case 1:
9323                         chan_def[cn] = 0;       /* alpha */
9324                         break;
9325                       default:
9326                         chan_def[cn] = -typ;
9327                     }
9328                   }
9329                 }
9330               }
9331             }
9332           }
9333
9334           gst_caps_set_simple (stream->caps,
9335               "num-components", G_TYPE_INT, ncomp, NULL);
9336           gst_caps_set_simple (stream->caps,
9337               "colorspace", G_TYPE_STRING, colorspace, NULL);
9338
9339           if (comp_map) {
9340             GValue arr = { 0, };
9341             GValue elt = { 0, };
9342             int i;
9343             g_value_init (&arr, GST_TYPE_ARRAY);
9344             g_value_init (&elt, G_TYPE_INT);
9345             for (i = 0; i < ncomp_map; i++) {
9346               g_value_set_int (&elt, comp_map[i]);
9347               gst_value_array_append_value (&arr, &elt);
9348             }
9349             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9350                 "component-map", &arr);
9351             g_value_unset (&elt);
9352             g_value_unset (&arr);
9353             g_free (comp_map);
9354           }
9355
9356           if (chan_def) {
9357             GValue arr = { 0, };
9358             GValue elt = { 0, };
9359             int i;
9360             g_value_init (&arr, GST_TYPE_ARRAY);
9361             g_value_init (&elt, G_TYPE_INT);
9362             for (i = 0; i < nchan_def; i++) {
9363               g_value_set_int (&elt, chan_def[i]);
9364               gst_value_array_append_value (&arr, &elt);
9365             }
9366             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9367                 "channel-definitions", &arr);
9368             g_value_unset (&elt);
9369             g_value_unset (&arr);
9370             g_free (chan_def);
9371           }
9372
9373           /* some optional atoms */
9374           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9375           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9376
9377           /* indicate possible fields in caps */
9378           if (field) {
9379             data = (guint8 *) field->data + 8;
9380             if (*data != 1)
9381               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9382                   (gint) * data, NULL);
9383           }
9384           /* add codec_data if provided */
9385           if (prefix) {
9386             GstBuffer *buf;
9387             gint len;
9388
9389             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9390             data = prefix->data;
9391             len = QT_UINT32 (data);
9392             if (len > 0x8) {
9393               len -= 0x8;
9394               buf = gst_buffer_new_and_alloc (len);
9395               gst_buffer_fill (buf, 0, data + 8, len);
9396               gst_caps_set_simple (stream->caps,
9397                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9398               gst_buffer_unref (buf);
9399             }
9400           }
9401           break;
9402         }
9403         case FOURCC_SVQ3:
9404         case FOURCC_VP31:
9405         {
9406           GstBuffer *buf;
9407           GstBuffer *seqh = NULL;
9408           guint8 *gamma_data = NULL;
9409           gint len = QT_UINT32 (stsd_data);
9410
9411           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9412           if (gamma_data) {
9413             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9414                 QT_FP32 (gamma_data), NULL);
9415           }
9416           if (seqh) {
9417             /* sorry for the bad name, but we don't know what this is, other
9418              * than its own fourcc */
9419             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9420                 NULL);
9421           }
9422
9423           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9424           buf = gst_buffer_new_and_alloc (len);
9425           gst_buffer_fill (buf, 0, stsd_data, len);
9426           gst_caps_set_simple (stream->caps,
9427               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9428           gst_buffer_unref (buf);
9429           break;
9430         }
9431         case FOURCC_rle_:
9432         case FOURCC_WRLE:
9433         {
9434           gst_caps_set_simple (stream->caps,
9435               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9436           break;
9437         }
9438         case FOURCC_XiTh:
9439         {
9440           GNode *xith, *xdxt;
9441
9442           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9443           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9444           if (!xith)
9445             break;
9446
9447           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9448           if (!xdxt)
9449             break;
9450
9451           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9452           /* collect the headers and store them in a stream list so that we can
9453            * send them out first */
9454           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9455           break;
9456         }
9457         case FOURCC_ovc1:
9458         {
9459           GNode *ovc1;
9460           guint8 *ovc1_data;
9461           guint ovc1_len;
9462           GstBuffer *buf;
9463
9464           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9465           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9466           if (!ovc1)
9467             break;
9468           ovc1_data = ovc1->data;
9469           ovc1_len = QT_UINT32 (ovc1_data);
9470           if (ovc1_len <= 198) {
9471             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9472             break;
9473           }
9474           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9475           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9476           gst_caps_set_simple (stream->caps,
9477               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9478           gst_buffer_unref (buf);
9479           break;
9480         }
9481         case FOURCC_vc_1:
9482         {
9483           gint len = QT_UINT32 (stsd_data) - 0x66;
9484           const guint8 *vc1_data = stsd_data + 0x66;
9485
9486           /* find dvc1 */
9487           while (len >= 8) {
9488             gint size;
9489
9490             if (QT_UINT32 (vc1_data) <= len)
9491               size = QT_UINT32 (vc1_data) - 8;
9492             else
9493               size = len - 8;
9494
9495             if (size < 1)
9496               /* No real data, so break out */
9497               break;
9498
9499             switch (QT_FOURCC (vc1_data + 0x4)) {
9500               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
9501               {
9502                 GstBuffer *buf;
9503
9504                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
9505                 buf = gst_buffer_new_and_alloc (size);
9506                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
9507                 gst_caps_set_simple (stream->caps,
9508                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9509                 gst_buffer_unref (buf);
9510                 break;
9511               }
9512               default:
9513                 break;
9514             }
9515             len -= size + 8;
9516             vc1_data += size + 8;
9517           }
9518           break;
9519         }
9520         default:
9521           break;
9522       }
9523     }
9524
9525     GST_INFO_OBJECT (qtdemux,
9526         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
9527         GST_FOURCC_ARGS (fourcc), stream->caps);
9528
9529   } else if (stream->subtype == FOURCC_soun) {
9530     int version, samplesize;
9531     guint16 compression_id;
9532     gboolean amrwb = FALSE;
9533
9534     offset = 32;
9535     /* sample description entry (16) + sound sample description v0 (20) */
9536     if (len < 36)
9537       goto corrupt_file;
9538
9539     version = QT_UINT32 (stsd_data + offset);
9540     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
9541     samplesize = QT_UINT16 (stsd_data + offset + 10);
9542     compression_id = QT_UINT16 (stsd_data + offset + 12);
9543     stream->rate = QT_FP32 (stsd_data + offset + 16);
9544
9545     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
9546     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
9547         QT_UINT32 (stsd_data + offset + 4));
9548     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
9549     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
9550     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
9551     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
9552         QT_UINT16 (stsd_data + offset + 14));
9553     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
9554
9555     if (compression_id == 0xfffe)
9556       stream->sampled = TRUE;
9557
9558     /* first assume uncompressed audio */
9559     stream->bytes_per_sample = samplesize / 8;
9560     stream->samples_per_frame = stream->n_channels;
9561     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
9562     stream->samples_per_packet = stream->samples_per_frame;
9563     stream->bytes_per_packet = stream->bytes_per_sample;
9564
9565     offset = 52;
9566     switch (fourcc) {
9567         /* Yes, these have to be hard-coded */
9568       case FOURCC_MAC6:
9569       {
9570         stream->samples_per_packet = 6;
9571         stream->bytes_per_packet = 1;
9572         stream->bytes_per_frame = 1 * stream->n_channels;
9573         stream->bytes_per_sample = 1;
9574         stream->samples_per_frame = 6 * stream->n_channels;
9575         break;
9576       }
9577       case FOURCC_MAC3:
9578       {
9579         stream->samples_per_packet = 3;
9580         stream->bytes_per_packet = 1;
9581         stream->bytes_per_frame = 1 * stream->n_channels;
9582         stream->bytes_per_sample = 1;
9583         stream->samples_per_frame = 3 * stream->n_channels;
9584         break;
9585       }
9586       case FOURCC_ima4:
9587       {
9588         stream->samples_per_packet = 64;
9589         stream->bytes_per_packet = 34;
9590         stream->bytes_per_frame = 34 * stream->n_channels;
9591         stream->bytes_per_sample = 2;
9592         stream->samples_per_frame = 64 * stream->n_channels;
9593         break;
9594       }
9595       case FOURCC_ulaw:
9596       case FOURCC_alaw:
9597       {
9598         stream->samples_per_packet = 1;
9599         stream->bytes_per_packet = 1;
9600         stream->bytes_per_frame = 1 * stream->n_channels;
9601         stream->bytes_per_sample = 1;
9602         stream->samples_per_frame = 1 * stream->n_channels;
9603         break;
9604       }
9605       case FOURCC_agsm:
9606       {
9607         stream->samples_per_packet = 160;
9608         stream->bytes_per_packet = 33;
9609         stream->bytes_per_frame = 33 * stream->n_channels;
9610         stream->bytes_per_sample = 2;
9611         stream->samples_per_frame = 160 * stream->n_channels;
9612         break;
9613       }
9614       default:
9615         break;
9616     }
9617
9618     if (version == 0x00010000) {
9619       /* sample description entry (16) + sound sample description v1 (20+16) */
9620       if (len < 52)
9621         goto corrupt_file;
9622
9623       switch (fourcc) {
9624         case FOURCC_twos:
9625         case FOURCC_sowt:
9626         case FOURCC_raw_:
9627           break;
9628         default:
9629         {
9630           /* only parse extra decoding config for non-pcm audio */
9631           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
9632           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
9633           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
9634           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
9635
9636           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
9637               stream->samples_per_packet);
9638           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
9639               stream->bytes_per_packet);
9640           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
9641               stream->bytes_per_frame);
9642           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
9643               stream->bytes_per_sample);
9644
9645           if (!stream->sampled && stream->bytes_per_packet) {
9646             stream->samples_per_frame = (stream->bytes_per_frame /
9647                 stream->bytes_per_packet) * stream->samples_per_packet;
9648             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
9649                 stream->samples_per_frame);
9650           }
9651           break;
9652         }
9653       }
9654     } else if (version == 0x00020000) {
9655       union
9656       {
9657         gdouble fp;
9658         guint64 val;
9659       } qtfp;
9660
9661       /* sample description entry (16) + sound sample description v2 (56) */
9662       if (len < 72)
9663         goto corrupt_file;
9664
9665       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
9666       stream->rate = qtfp.fp;
9667       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
9668
9669       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
9670       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
9671       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
9672       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
9673           QT_UINT32 (stsd_data + offset + 20));
9674       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
9675           QT_UINT32 (stsd_data + offset + 24));
9676       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
9677           QT_UINT32 (stsd_data + offset + 28));
9678       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
9679           QT_UINT32 (stsd_data + offset + 32));
9680     } else if (version != 0x00000) {
9681       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
9682     }
9683
9684     if (stream->caps)
9685       gst_caps_unref (stream->caps);
9686
9687     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
9688         stsd_data + 32, len - 16, &codec);
9689
9690     switch (fourcc) {
9691       case FOURCC_in24:
9692       {
9693         GNode *enda;
9694         GNode *in24;
9695
9696         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
9697
9698         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
9699         if (!enda) {
9700           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
9701           if (wave)
9702             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
9703         }
9704         if (enda) {
9705           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
9706           gst_caps_set_simple (stream->caps,
9707               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
9708         }
9709         break;
9710       }
9711       case FOURCC_owma:
9712       {
9713         GNode *owma;
9714         const guint8 *owma_data;
9715         const gchar *codec_name = NULL;
9716         guint owma_len;
9717         GstBuffer *buf;
9718         gint version = 1;
9719         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9720         /* FIXME this should also be gst_riff_strf_auds,
9721          * but the latter one is actually missing bits-per-sample :( */
9722         typedef struct
9723         {
9724           gint16 wFormatTag;
9725           gint16 nChannels;
9726           gint32 nSamplesPerSec;
9727           gint32 nAvgBytesPerSec;
9728           gint16 nBlockAlign;
9729           gint16 wBitsPerSample;
9730           gint16 cbSize;
9731         } WAVEFORMATEX;
9732         WAVEFORMATEX *wfex;
9733
9734         GST_DEBUG_OBJECT (qtdemux, "parse owma");
9735         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
9736         if (!owma)
9737           break;
9738         owma_data = owma->data;
9739         owma_len = QT_UINT32 (owma_data);
9740         if (owma_len <= 54) {
9741           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
9742           break;
9743         }
9744         wfex = (WAVEFORMATEX *) (owma_data + 36);
9745         buf = gst_buffer_new_and_alloc (owma_len - 54);
9746         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
9747         if (wfex->wFormatTag == 0x0161) {
9748           codec_name = "Windows Media Audio";
9749           version = 2;
9750         } else if (wfex->wFormatTag == 0x0162) {
9751           codec_name = "Windows Media Audio 9 Pro";
9752           version = 3;
9753         } else if (wfex->wFormatTag == 0x0163) {
9754           codec_name = "Windows Media Audio 9 Lossless";
9755           /* is that correct? gstffmpegcodecmap.c is missing it, but
9756            * fluendo codec seems to support it */
9757           version = 4;
9758         }
9759
9760         gst_caps_set_simple (stream->caps,
9761             "codec_data", GST_TYPE_BUFFER, buf,
9762             "wmaversion", G_TYPE_INT, version,
9763             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
9764             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
9765             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9766             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9767             NULL);
9768         gst_buffer_unref (buf);
9769
9770         if (codec_name) {
9771           g_free (codec);
9772           codec = g_strdup (codec_name);
9773         }
9774         break;
9775       }
9776       case FOURCC_wma_:
9777       {
9778         gint len = QT_UINT32 (stsd_data) - offset;
9779         const guint8 *wfex_data = stsd_data + offset;
9780         const gchar *codec_name = NULL;
9781         gint version = 1;
9782         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9783         /* FIXME this should also be gst_riff_strf_auds,
9784          * but the latter one is actually missing bits-per-sample :( */
9785         typedef struct
9786         {
9787           gint16 wFormatTag;
9788           gint16 nChannels;
9789           gint32 nSamplesPerSec;
9790           gint32 nAvgBytesPerSec;
9791           gint16 nBlockAlign;
9792           gint16 wBitsPerSample;
9793           gint16 cbSize;
9794         } WAVEFORMATEX;
9795         WAVEFORMATEX wfex;
9796
9797         /* FIXME: unify with similar wavformatex parsing code above */
9798         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
9799
9800         /* find wfex */
9801         while (len >= 8) {
9802           gint size;
9803
9804           if (QT_UINT32 (wfex_data) <= len)
9805             size = QT_UINT32 (wfex_data) - 8;
9806           else
9807             size = len - 8;
9808
9809           if (size < 1)
9810             /* No real data, so break out */
9811             break;
9812
9813           switch (QT_FOURCC (wfex_data + 4)) {
9814             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
9815             {
9816               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
9817
9818               if (size < 8 + 18)
9819                 break;
9820
9821               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
9822               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
9823               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
9824               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
9825               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
9826               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
9827               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
9828
9829               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
9830               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
9831                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
9832                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
9833                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
9834                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
9835
9836               if (wfex.wFormatTag == 0x0161) {
9837                 codec_name = "Windows Media Audio";
9838                 version = 2;
9839               } else if (wfex.wFormatTag == 0x0162) {
9840                 codec_name = "Windows Media Audio 9 Pro";
9841                 version = 3;
9842               } else if (wfex.wFormatTag == 0x0163) {
9843                 codec_name = "Windows Media Audio 9 Lossless";
9844                 /* is that correct? gstffmpegcodecmap.c is missing it, but
9845                  * fluendo codec seems to support it */
9846                 version = 4;
9847               }
9848
9849               gst_caps_set_simple (stream->caps,
9850                   "wmaversion", G_TYPE_INT, version,
9851                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
9852                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
9853                   "width", G_TYPE_INT, wfex.wBitsPerSample,
9854                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
9855
9856               if (size > wfex.cbSize) {
9857                 GstBuffer *buf;
9858
9859                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
9860                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
9861                     size - wfex.cbSize);
9862                 gst_caps_set_simple (stream->caps,
9863                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9864                 gst_buffer_unref (buf);
9865               } else {
9866                 GST_WARNING_OBJECT (qtdemux, "no codec data");
9867               }
9868
9869               if (codec_name) {
9870                 g_free (codec);
9871                 codec = g_strdup (codec_name);
9872               }
9873               break;
9874             }
9875             default:
9876               break;
9877           }
9878           len -= size + 8;
9879           wfex_data += size + 8;
9880         }
9881         break;
9882       }
9883       case FOURCC_opus:
9884       {
9885         GNode *opus;
9886         const guint8 *opus_data;
9887         guint8 *channel_mapping = NULL;
9888         guint32 rate;
9889         guint8 channels;
9890         guint8 channel_mapping_family;
9891         guint8 stream_count;
9892         guint8 coupled_count;
9893         guint8 i;
9894
9895         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
9896         opus_data = opus->data;
9897
9898         channels = GST_READ_UINT8 (opus_data + 45);
9899         rate = GST_READ_UINT32_LE (opus_data + 48);
9900         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
9901         stream_count = GST_READ_UINT8 (opus_data + 55);
9902         coupled_count = GST_READ_UINT8 (opus_data + 56);
9903
9904         if (channels > 0) {
9905           channel_mapping = g_malloc (channels * sizeof (guint8));
9906           for (i = 0; i < channels; i++)
9907             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
9908         }
9909
9910         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
9911             channel_mapping_family, stream_count, coupled_count,
9912             channel_mapping);
9913         break;
9914       }
9915       default:
9916         break;
9917     }
9918
9919     if (codec) {
9920       GstStructure *s;
9921       gint bitrate = 0;
9922
9923       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9924           GST_TAG_AUDIO_CODEC, codec, NULL);
9925       g_free (codec);
9926       codec = NULL;
9927
9928       /* some bitrate info may have ended up in caps */
9929       s = gst_caps_get_structure (stream->caps, 0);
9930       gst_structure_get_int (s, "bitrate", &bitrate);
9931       if (bitrate > 0)
9932         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9933             GST_TAG_BITRATE, bitrate, NULL);
9934     }
9935
9936     if (stream->protected && fourcc == FOURCC_mp4a)
9937       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
9938     else
9939       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
9940
9941     wave = NULL;
9942     esds = NULL;
9943     if (mp4a) {
9944       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
9945       if (wave)
9946         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
9947       if (!esds)
9948         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
9949     }
9950
9951
9952     /* If the fourcc's bottom 16 bits gives 'sm', then the top
9953        16 bits is a byte-swapped wave-style codec identifier,
9954        and we can find a WAVE header internally to a 'wave' atom here.
9955        This can more clearly be thought of as 'ms' as the top 16 bits, and a
9956        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
9957        is big-endian).
9958      */
9959     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
9960       if (len < offset + 20) {
9961         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
9962       } else {
9963         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
9964         const guint8 *data = stsd_data + offset + 16;
9965         GNode *wavenode;
9966         GNode *waveheadernode;
9967
9968         wavenode = g_node_new ((guint8 *) data);
9969         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
9970           const guint8 *waveheader;
9971           guint32 headerlen;
9972
9973           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
9974           if (waveheadernode) {
9975             waveheader = (const guint8 *) waveheadernode->data;
9976             headerlen = QT_UINT32 (waveheader);
9977
9978             if (headerlen > 8) {
9979               gst_riff_strf_auds *header = NULL;
9980               GstBuffer *headerbuf;
9981               GstBuffer *extra;
9982
9983               waveheader += 8;
9984               headerlen -= 8;
9985
9986               headerbuf = gst_buffer_new_and_alloc (headerlen);
9987               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
9988
9989               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
9990                       headerbuf, &header, &extra)) {
9991                 gst_caps_unref (stream->caps);
9992                 /* FIXME: Need to do something with the channel reorder map */
9993                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
9994                     header, extra, NULL, NULL, NULL);
9995
9996                 if (extra)
9997                   gst_buffer_unref (extra);
9998                 g_free (header);
9999               }
10000             }
10001           } else
10002             GST_DEBUG ("Didn't find waveheadernode for this codec");
10003         }
10004         g_node_destroy (wavenode);
10005       }
10006     } else if (esds) {
10007       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10008     } else {
10009       switch (fourcc) {
10010 #if 0
10011           /* FIXME: what is in the chunk? */
10012         case FOURCC_QDMC:
10013         {
10014           gint len = QT_UINT32 (stsd_data);
10015
10016           /* seems to be always = 116 = 0x74 */
10017           break;
10018         }
10019 #endif
10020         case FOURCC_QDM2:
10021         {
10022           gint len = QT_UINT32 (stsd_data);
10023
10024           if (len > 0x4C) {
10025             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10026
10027             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10028             gst_caps_set_simple (stream->caps,
10029                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10030             gst_buffer_unref (buf);
10031           }
10032           gst_caps_set_simple (stream->caps,
10033               "samplesize", G_TYPE_INT, samplesize, NULL);
10034           break;
10035         }
10036         case FOURCC_alac:
10037         {
10038           GNode *alac, *wave = NULL;
10039
10040           /* apparently, m4a has this atom appended directly in the stsd entry,
10041            * while mov has it in a wave atom */
10042           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10043           if (alac) {
10044             /* alac now refers to stsd entry atom */
10045             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10046             if (wave)
10047               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10048             else
10049               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10050           }
10051           if (alac) {
10052             const guint8 *alac_data = alac->data;
10053             gint len = QT_UINT32 (alac->data);
10054             GstBuffer *buf;
10055
10056             if (len < 36) {
10057               GST_DEBUG_OBJECT (qtdemux,
10058                   "discarding alac atom with unexpected len %d", len);
10059             } else {
10060               /* codec-data contains alac atom size and prefix,
10061                * ffmpeg likes it that way, not quite gst-ish though ...*/
10062               buf = gst_buffer_new_and_alloc (len);
10063               gst_buffer_fill (buf, 0, alac->data, len);
10064               gst_caps_set_simple (stream->caps,
10065                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10066               gst_buffer_unref (buf);
10067
10068               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10069               stream->n_channels = QT_UINT8 (alac_data + 21);
10070               stream->rate = QT_UINT32 (alac_data + 32);
10071             }
10072           }
10073           gst_caps_set_simple (stream->caps,
10074               "samplesize", G_TYPE_INT, samplesize, NULL);
10075           break;
10076         }
10077         case FOURCC_sawb:
10078           /* Fallthrough! */
10079           amrwb = TRUE;
10080         case FOURCC_samr:
10081         {
10082           gint len = QT_UINT32 (stsd_data);
10083
10084           if (len > 0x34) {
10085             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10086             guint bitrate;
10087
10088             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10089
10090             /* If we have enough data, let's try to get the 'damr' atom. See
10091              * the 3GPP container spec (26.244) for more details. */
10092             if ((len - 0x34) > 8 &&
10093                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10094               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10095                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10096             }
10097
10098             gst_caps_set_simple (stream->caps,
10099                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10100             gst_buffer_unref (buf);
10101           }
10102           break;
10103         }
10104         case FOURCC_mp4a:
10105         {
10106           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10107           gint len = QT_UINT32 (stsd_data);
10108
10109           if (len >= 50) {
10110             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10111
10112             if (sound_version == 1) {
10113               guint16 channels = QT_UINT16 (stsd_data + 40);
10114               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10115               guint8 codec_data[2];
10116               GstBuffer *buf;
10117               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10118
10119               gint sample_rate_index =
10120                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10121
10122               /* build AAC codec data */
10123               codec_data[0] = profile << 3;
10124               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10125               codec_data[1] = (sample_rate_index & 0x01) << 7;
10126               codec_data[1] |= (channels & 0xF) << 3;
10127
10128               buf = gst_buffer_new_and_alloc (2);
10129               gst_buffer_fill (buf, 0, codec_data, 2);
10130               gst_caps_set_simple (stream->caps,
10131                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10132               gst_buffer_unref (buf);
10133             }
10134           }
10135           break;
10136         }
10137         default:
10138           GST_INFO_OBJECT (qtdemux,
10139               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10140           break;
10141       }
10142     }
10143     GST_INFO_OBJECT (qtdemux,
10144         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10145         GST_FOURCC_ARGS (fourcc), stream->caps);
10146
10147   } else if (stream->subtype == FOURCC_strm) {
10148     if (fourcc == FOURCC_rtsp) {
10149       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10150     } else {
10151       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10152           GST_FOURCC_ARGS (fourcc));
10153       goto unknown_stream;
10154     }
10155     stream->sampled = TRUE;
10156   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10157       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10158
10159     stream->sampled = TRUE;
10160     stream->sparse = TRUE;
10161
10162     stream->caps =
10163         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10164     if (codec) {
10165       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10166           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10167       g_free (codec);
10168       codec = NULL;
10169     }
10170
10171     /* hunt for sort-of codec data */
10172     switch (fourcc) {
10173       case FOURCC_mp4s:
10174       {
10175         GNode *mp4s = NULL;
10176         GNode *esds = NULL;
10177
10178         /* look for palette in a stsd->mp4s->esds sub-atom */
10179         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10180         if (mp4s)
10181           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10182         if (esds == NULL) {
10183           /* Invalid STSD */
10184           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10185           break;
10186         }
10187
10188         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10189         break;
10190       }
10191       default:
10192         GST_INFO_OBJECT (qtdemux,
10193             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10194         break;
10195     }
10196     GST_INFO_OBJECT (qtdemux,
10197         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10198         GST_FOURCC_ARGS (fourcc), stream->caps);
10199   } else {
10200     /* everything in 1 sample */
10201     stream->sampled = TRUE;
10202
10203     stream->caps =
10204         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10205
10206     if (stream->caps == NULL)
10207       goto unknown_stream;
10208
10209     if (codec) {
10210       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10211           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10212       g_free (codec);
10213       codec = NULL;
10214     }
10215   }
10216
10217   /* promote to sampled format */
10218   if (stream->fourcc == FOURCC_samr) {
10219     /* force mono 8000 Hz for AMR */
10220     stream->sampled = TRUE;
10221     stream->n_channels = 1;
10222     stream->rate = 8000;
10223   } else if (stream->fourcc == FOURCC_sawb) {
10224     /* force mono 16000 Hz for AMR-WB */
10225     stream->sampled = TRUE;
10226     stream->n_channels = 1;
10227     stream->rate = 16000;
10228   } else if (stream->fourcc == FOURCC_mp4a) {
10229     stream->sampled = TRUE;
10230   }
10231
10232   /* collect sample information */
10233   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10234     goto samples_failed;
10235
10236   if (qtdemux->fragmented) {
10237     guint64 offset;
10238
10239     /* need all moov samples as basis; probably not many if any at all */
10240     /* prevent moof parsing taking of at this time */
10241     offset = qtdemux->moof_offset;
10242     qtdemux->moof_offset = 0;
10243     if (stream->n_samples &&
10244         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10245       qtdemux->moof_offset = offset;
10246       goto samples_failed;
10247     }
10248     qtdemux->moof_offset = 0;
10249     /* movie duration more reliable in this case (e.g. mehd) */
10250     if (qtdemux->segment.duration &&
10251         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10252       stream->duration =
10253           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10254   }
10255
10256   /* configure segments */
10257   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10258     goto segments_failed;
10259
10260   /* add some language tag, if useful */
10261   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10262       strcmp (stream->lang_id, "und")) {
10263     const gchar *lang_code;
10264
10265     /* convert ISO 639-2 code to ISO 639-1 */
10266     lang_code = gst_tag_get_language_code (stream->lang_id);
10267     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10268         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10269   }
10270
10271   /* Check for UDTA tags */
10272   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10273     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10274   }
10275
10276   /* now we are ready to add the stream */
10277   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10278     goto too_many_streams;
10279
10280   if (!qtdemux->got_moov) {
10281     qtdemux->streams[qtdemux->n_streams] = stream;
10282     qtdemux->n_streams++;
10283     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10284   }
10285
10286   return TRUE;
10287
10288 /* ERRORS */
10289 skip_track:
10290   {
10291     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10292     if (new_stream)
10293       gst_qtdemux_stream_free (qtdemux, stream);
10294     return TRUE;
10295   }
10296 corrupt_file:
10297   {
10298     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10299         (_("This file is corrupt and cannot be played.")), (NULL));
10300     if (new_stream)
10301       gst_qtdemux_stream_free (qtdemux, stream);
10302     return FALSE;
10303   }
10304 error_encrypted:
10305   {
10306     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10307     if (new_stream)
10308       gst_qtdemux_stream_free (qtdemux, stream);
10309     return FALSE;
10310   }
10311 samples_failed:
10312 segments_failed:
10313   {
10314     /* we posted an error already */
10315     /* free stbl sub-atoms */
10316     gst_qtdemux_stbl_free (stream);
10317     if (new_stream)
10318       gst_qtdemux_stream_free (qtdemux, stream);
10319     return FALSE;
10320   }
10321 existing_stream:
10322   {
10323     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10324         track_id);
10325     if (new_stream)
10326       gst_qtdemux_stream_free (qtdemux, stream);
10327     return TRUE;
10328   }
10329 unknown_stream:
10330   {
10331     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10332         GST_FOURCC_ARGS (stream->subtype));
10333     if (new_stream)
10334       gst_qtdemux_stream_free (qtdemux, stream);
10335     return TRUE;
10336   }
10337 too_many_streams:
10338   {
10339     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10340         (_("This file contains too many streams. Only playing first %d"),
10341             GST_QTDEMUX_MAX_STREAMS), (NULL));
10342     return TRUE;
10343   }
10344 }
10345
10346 /* If we can estimate the overall bitrate, and don't have information about the
10347  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10348  * the overall bitrate minus the sum of the bitrates of all other streams. This
10349  * should be useful for the common case where we have one audio and one video
10350  * stream and can estimate the bitrate of one, but not the other. */
10351 static void
10352 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10353 {
10354   QtDemuxStream *stream = NULL;
10355   gint64 size, sys_bitrate, sum_bitrate = 0;
10356   GstClockTime duration;
10357   gint i;
10358   guint bitrate;
10359
10360   if (qtdemux->fragmented)
10361     return;
10362
10363   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10364
10365   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10366       || size <= 0) {
10367     GST_DEBUG_OBJECT (qtdemux,
10368         "Size in bytes of the stream not known - bailing");
10369     return;
10370   }
10371
10372   /* Subtract the header size */
10373   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10374       size, qtdemux->header_size);
10375
10376   if (size < qtdemux->header_size)
10377     return;
10378
10379   size = size - qtdemux->header_size;
10380
10381   if (!gst_qtdemux_get_duration (qtdemux, &duration) ||
10382       duration == GST_CLOCK_TIME_NONE) {
10383     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10384     return;
10385   }
10386
10387   for (i = 0; i < qtdemux->n_streams; i++) {
10388     switch (qtdemux->streams[i]->subtype) {
10389       case FOURCC_soun:
10390       case FOURCC_vide:
10391         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10392             qtdemux->streams[i]->caps);
10393         /* retrieve bitrate, prefer avg then max */
10394         bitrate = 0;
10395         if (qtdemux->streams[i]->pending_tags) {
10396           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10397               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10398           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10399           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10400               GST_TAG_NOMINAL_BITRATE, &bitrate);
10401           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10402           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10403               GST_TAG_BITRATE, &bitrate);
10404           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10405         }
10406         if (bitrate)
10407           sum_bitrate += bitrate;
10408         else {
10409           if (stream) {
10410             GST_DEBUG_OBJECT (qtdemux,
10411                 ">1 stream with unknown bitrate - bailing");
10412             return;
10413           } else
10414             stream = qtdemux->streams[i];
10415         }
10416
10417       default:
10418         /* For other subtypes, we assume no significant impact on bitrate */
10419         break;
10420     }
10421   }
10422
10423   if (!stream) {
10424     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10425     return;
10426   }
10427
10428   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10429
10430   if (sys_bitrate < sum_bitrate) {
10431     /* This can happen, since sum_bitrate might be derived from maximum
10432      * bitrates and not average bitrates */
10433     GST_DEBUG_OBJECT (qtdemux,
10434         "System bitrate less than sum bitrate - bailing");
10435     return;
10436   }
10437
10438   bitrate = sys_bitrate - sum_bitrate;
10439   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10440       ", Stream bitrate = %u", sys_bitrate, bitrate);
10441
10442   if (!stream->pending_tags)
10443     stream->pending_tags = gst_tag_list_new_empty ();
10444
10445   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10446       GST_TAG_BITRATE, bitrate, NULL);
10447 }
10448
10449 static GstFlowReturn
10450 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10451 {
10452   gint i;
10453   GstFlowReturn ret = GST_FLOW_OK;
10454
10455   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10456
10457   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10458     QtDemuxStream *stream = qtdemux->streams[i];
10459     guint32 sample_num = 0;
10460
10461     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10462         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10463
10464     if (qtdemux->fragmented) {
10465       /* need all moov samples first */
10466       GST_OBJECT_LOCK (qtdemux);
10467       while (stream->n_samples == 0)
10468         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10469           break;
10470       GST_OBJECT_UNLOCK (qtdemux);
10471     } else {
10472       /* discard any stray moof */
10473       qtdemux->moof_offset = 0;
10474     }
10475
10476     /* prepare braking */
10477     if (ret != GST_FLOW_ERROR)
10478       ret = GST_FLOW_OK;
10479
10480     /* in pull mode, we should have parsed some sample info by now;
10481      * and quite some code will not handle no samples.
10482      * in push mode, we'll just have to deal with it */
10483     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10484       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10485       gst_qtdemux_remove_stream (qtdemux, i);
10486       i--;
10487       continue;
10488     }
10489
10490     /* parse the initial sample for use in setting the frame rate cap */
10491     while (sample_num == 0 && sample_num < stream->n_samples) {
10492       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10493         break;
10494       ++sample_num;
10495     }
10496     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
10497       stream->first_duration = stream->samples[0].duration;
10498       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
10499           stream->track_id, stream->first_duration);
10500     }
10501   }
10502
10503   return ret;
10504 }
10505
10506 static GstFlowReturn
10507 qtdemux_expose_streams (GstQTDemux * qtdemux)
10508 {
10509   gint i;
10510   GstFlowReturn ret = GST_FLOW_OK;
10511   GSList *oldpads = NULL;
10512   GSList *iter;
10513
10514   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
10515
10516   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10517     QtDemuxStream *stream = qtdemux->streams[i];
10518     GstPad *oldpad = stream->pad;
10519     GstTagList *list;
10520
10521     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10522         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10523
10524     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
10525         stream->track_id == qtdemux->chapters_track_id) {
10526       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
10527          so that it doesn't look like a subtitle track */
10528       gst_qtdemux_remove_stream (qtdemux, i);
10529       i--;
10530       continue;
10531     }
10532
10533     /* now we have all info and can expose */
10534     list = stream->pending_tags;
10535     stream->pending_tags = NULL;
10536     if (oldpad)
10537       oldpads = g_slist_prepend (oldpads, oldpad);
10538     gst_qtdemux_add_stream (qtdemux, stream, list);
10539   }
10540
10541   gst_qtdemux_guess_bitrate (qtdemux);
10542
10543   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
10544
10545   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
10546     GstPad *oldpad = iter->data;
10547
10548     gst_pad_push_event (oldpad, gst_event_new_eos ());
10549     gst_pad_set_active (oldpad, FALSE);
10550     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
10551     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
10552     gst_object_unref (oldpad);
10553   }
10554
10555   /* check if we should post a redirect in case there is a single trak
10556    * and it is a redirecting trak */
10557   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
10558     GstMessage *m;
10559
10560     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
10561         "an external content");
10562     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
10563         gst_structure_new ("redirect",
10564             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
10565             NULL));
10566     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
10567     qtdemux->posted_redirect = TRUE;
10568   }
10569
10570   for (i = 0; i < qtdemux->n_streams; i++) {
10571     QtDemuxStream *stream = qtdemux->streams[i];
10572
10573     qtdemux_do_allocation (qtdemux, stream);
10574   }
10575
10576   qtdemux->exposed = TRUE;
10577   return ret;
10578 }
10579
10580 /* check if major or compatible brand is 3GP */
10581 static inline gboolean
10582 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
10583 {
10584   if (major) {
10585     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10586         FOURCC_3g__);
10587   } else if (qtdemux->comp_brands != NULL) {
10588     GstMapInfo map;
10589     guint8 *data;
10590     gsize size;
10591     gboolean res = FALSE;
10592
10593     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
10594     data = map.data;
10595     size = map.size;
10596     while (size >= 4) {
10597       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10598           FOURCC_3g__);
10599       data += 4;
10600       size -= 4;
10601     }
10602     gst_buffer_unmap (qtdemux->comp_brands, &map);
10603     return res;
10604   } else {
10605     return FALSE;
10606   }
10607 }
10608
10609 /* check if tag is a spec'ed 3GP tag keyword storing a string */
10610 static inline gboolean
10611 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
10612 {
10613   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
10614       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
10615       || fourcc == FOURCC_albm;
10616 }
10617
10618 static void
10619 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
10620     const char *tag, const char *dummy, GNode * node)
10621 {
10622   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10623   int offset;
10624   char *name;
10625   gchar *data;
10626   gdouble longitude, latitude, altitude;
10627   gint len;
10628
10629   len = QT_UINT32 (node->data);
10630   if (len <= 14)
10631     goto short_read;
10632
10633   data = node->data;
10634   offset = 14;
10635
10636   /* TODO: language code skipped */
10637
10638   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
10639
10640   if (!name) {
10641     /* do not alarm in trivial case, but bail out otherwise */
10642     if (*(data + offset) != 0) {
10643       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
10644           "giving up", tag);
10645     }
10646   } else {
10647     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10648         GST_TAG_GEO_LOCATION_NAME, name, NULL);
10649     offset += strlen (name);
10650     g_free (name);
10651   }
10652
10653   if (len < offset + 2 + 4 + 4 + 4)
10654     goto short_read;
10655
10656   /* +1 +1 = skip null-terminator and location role byte */
10657   offset += 1 + 1;
10658   /* table in spec says unsigned, semantics say negative has meaning ... */
10659   longitude = QT_SFP32 (data + offset);
10660
10661   offset += 4;
10662   latitude = QT_SFP32 (data + offset);
10663
10664   offset += 4;
10665   altitude = QT_SFP32 (data + offset);
10666
10667   /* one invalid means all are invalid */
10668   if (longitude >= -180.0 && longitude <= 180.0 &&
10669       latitude >= -90.0 && latitude <= 90.0) {
10670     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10671         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
10672         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
10673         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
10674   }
10675
10676   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
10677
10678   return;
10679
10680   /* ERRORS */
10681 short_read:
10682   {
10683     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
10684     return;
10685   }
10686 }
10687
10688
10689 static void
10690 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
10691     const char *tag, const char *dummy, GNode * node)
10692 {
10693   guint16 y;
10694   GDate *date;
10695   gint len;
10696
10697   len = QT_UINT32 (node->data);
10698   if (len < 14)
10699     return;
10700
10701   y = QT_UINT16 ((guint8 *) node->data + 12);
10702   if (y == 0) {
10703     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
10704     return;
10705   }
10706   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
10707
10708   date = g_date_new_dmy (1, 1, y);
10709   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
10710   g_date_free (date);
10711 }
10712
10713 static void
10714 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
10715     const char *tag, const char *dummy, GNode * node)
10716 {
10717   int offset;
10718   char *tag_str = NULL;
10719   guint8 *entity;
10720   guint16 table;
10721   gint len;
10722
10723   len = QT_UINT32 (node->data);
10724   if (len <= 20)
10725     goto short_read;
10726
10727   offset = 12;
10728   entity = (guint8 *) node->data + offset;
10729   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
10730     GST_DEBUG_OBJECT (qtdemux,
10731         "classification info: %c%c%c%c invalid classification entity",
10732         entity[0], entity[1], entity[2], entity[3]);
10733     return;
10734   }
10735
10736   offset += 4;
10737   table = QT_UINT16 ((guint8 *) node->data + offset);
10738
10739   /* Language code skipped */
10740
10741   offset += 4;
10742
10743   /* Tag format: "XXXX://Y[YYYY]/classification info string"
10744    * XXXX: classification entity, fixed length 4 chars.
10745    * Y[YYYY]: classification table, max 5 chars.
10746    */
10747   tag_str = g_strdup_printf ("----://%u/%s",
10748       table, (char *) node->data + offset);
10749
10750   /* memcpy To be sure we're preserving byte order */
10751   memcpy (tag_str, entity, 4);
10752   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
10753
10754   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
10755
10756   g_free (tag_str);
10757
10758   return;
10759
10760   /* ERRORS */
10761 short_read:
10762   {
10763     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
10764     return;
10765   }
10766 }
10767
10768 static gboolean
10769 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
10770     const char *tag, const char *dummy, GNode * node)
10771 {
10772   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10773   GNode *data;
10774   char *s;
10775   int len;
10776   guint32 type;
10777   int offset;
10778   gboolean ret = TRUE;
10779   const gchar *charset = NULL;
10780
10781   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10782   if (data) {
10783     len = QT_UINT32 (data->data);
10784     type = QT_UINT32 ((guint8 *) data->data + 8);
10785     if (type == 0x00000001 && len > 16) {
10786       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
10787           env_vars);
10788       if (s) {
10789         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10790         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10791         g_free (s);
10792       } else {
10793         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10794       }
10795     }
10796   } else {
10797     len = QT_UINT32 (node->data);
10798     type = QT_UINT32 ((guint8 *) node->data + 4);
10799     if ((type >> 24) == 0xa9) {
10800       gint str_len;
10801       gint lang_code;
10802
10803       /* Type starts with the (C) symbol, so the next data is a list
10804        * of (string size(16), language code(16), string) */
10805
10806       str_len = QT_UINT16 ((guint8 *) node->data + 8);
10807       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
10808
10809       /* the string + fourcc + size + 2 16bit fields,
10810        * means that there are more tags in this atom */
10811       if (len > str_len + 8 + 4) {
10812         /* TODO how to represent the same tag in different languages? */
10813         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
10814             "text alternatives, reading only first one");
10815       }
10816
10817       offset = 12;
10818       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
10819       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
10820
10821       if (lang_code < 0x800) {  /* MAC encoded string */
10822         charset = "mac";
10823       }
10824     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
10825             QT_FOURCC ((guint8 *) node->data + 4))) {
10826       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
10827
10828       /* we go for 3GP style encoding if major brands claims so,
10829        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
10830       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
10831           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
10832               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
10833         offset = 14;
10834         /* 16-bit Language code is ignored here as well */
10835         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
10836       } else {
10837         goto normal;
10838       }
10839     } else {
10840     normal:
10841       offset = 8;
10842       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
10843       ret = FALSE;              /* may have to fallback */
10844     }
10845     if (charset) {
10846       GError *err = NULL;
10847
10848       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
10849           charset, NULL, NULL, &err);
10850       if (err) {
10851         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
10852             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
10853             err->message);
10854         g_error_free (err);
10855       }
10856     } else {
10857       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10858           len - offset, env_vars);
10859     }
10860     if (s) {
10861       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10862       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10863       g_free (s);
10864       ret = TRUE;
10865     } else {
10866       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10867     }
10868   }
10869   return ret;
10870 }
10871
10872 static void
10873 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
10874     const char *tag, const char *dummy, GNode * node)
10875 {
10876   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
10877 }
10878
10879 static void
10880 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
10881     const char *tag, const char *dummy, GNode * node)
10882 {
10883   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10884   guint8 *data;
10885   char *s, *t, *k = NULL;
10886   int len;
10887   int offset;
10888   int count;
10889
10890   /* first try normal string tag if major brand not 3GP */
10891   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
10892     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
10893       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
10894        * let's try it 3gpp way after minor safety check */
10895       data = node->data;
10896       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
10897         return;
10898     } else
10899       return;
10900   }
10901
10902   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
10903
10904   data = node->data;
10905
10906   len = QT_UINT32 (data);
10907   if (len < 15)
10908     goto short_read;
10909
10910   count = QT_UINT8 (data + 14);
10911   offset = 15;
10912   for (; count; count--) {
10913     gint slen;
10914
10915     if (offset + 1 > len)
10916       goto short_read;
10917     slen = QT_UINT8 (data + offset);
10918     offset += 1;
10919     if (offset + slen > len)
10920       goto short_read;
10921     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10922         slen, env_vars);
10923     if (s) {
10924       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
10925       if (k) {
10926         t = g_strjoin (",", k, s, NULL);
10927         g_free (s);
10928         g_free (k);
10929         k = t;
10930       } else {
10931         k = s;
10932       }
10933     } else {
10934       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
10935     }
10936     offset += slen;
10937   }
10938
10939 done:
10940   if (k) {
10941     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
10942     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
10943   }
10944   g_free (k);
10945
10946   return;
10947
10948   /* ERRORS */
10949 short_read:
10950   {
10951     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
10952     goto done;
10953   }
10954 }
10955
10956 static void
10957 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
10958     const char *tag1, const char *tag2, GNode * node)
10959 {
10960   GNode *data;
10961   int len;
10962   int type;
10963   int n1, n2;
10964
10965   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10966   if (data) {
10967     len = QT_UINT32 (data->data);
10968     type = QT_UINT32 ((guint8 *) data->data + 8);
10969     if (type == 0x00000000 && len >= 22) {
10970       n1 = QT_UINT16 ((guint8 *) data->data + 18);
10971       n2 = QT_UINT16 ((guint8 *) data->data + 20);
10972       if (n1 > 0) {
10973         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
10974         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
10975       }
10976       if (n2 > 0) {
10977         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
10978         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
10979       }
10980     }
10981   }
10982 }
10983
10984 static void
10985 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
10986     const char *tag1, const char *dummy, GNode * node)
10987 {
10988   GNode *data;
10989   int len;
10990   int type;
10991   int n1;
10992
10993   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10994   if (data) {
10995     len = QT_UINT32 (data->data);
10996     type = QT_UINT32 ((guint8 *) data->data + 8);
10997     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
10998     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
10999     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11000       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11001       if (n1) {
11002         /* do not add bpm=0 */
11003         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11004         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11005             NULL);
11006       }
11007     }
11008   }
11009 }
11010
11011 static void
11012 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11013     const char *tag1, const char *dummy, GNode * node)
11014 {
11015   GNode *data;
11016   int len;
11017   int type;
11018   guint32 num;
11019
11020   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11021   if (data) {
11022     len = QT_UINT32 (data->data);
11023     type = QT_UINT32 ((guint8 *) data->data + 8);
11024     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11025     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11026     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11027       num = QT_UINT32 ((guint8 *) data->data + 16);
11028       if (num) {
11029         /* do not add num=0 */
11030         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11031         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11032       }
11033     }
11034   }
11035 }
11036
11037 static void
11038 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11039     const char *tag1, const char *dummy, GNode * node)
11040 {
11041   GNode *data;
11042   int len;
11043   int type;
11044   GstSample *sample;
11045
11046   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11047   if (data) {
11048     len = QT_UINT32 (data->data);
11049     type = QT_UINT32 ((guint8 *) data->data + 8);
11050     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11051     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11052       if ((sample =
11053               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11054                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11055         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11056         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11057         gst_sample_unref (sample);
11058       }
11059     }
11060   }
11061 }
11062
11063 static void
11064 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11065     const char *tag, const char *dummy, GNode * node)
11066 {
11067   GNode *data;
11068   char *s;
11069   int len;
11070   int type;
11071
11072   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11073   if (data) {
11074     len = QT_UINT32 (data->data);
11075     type = QT_UINT32 ((guint8 *) data->data + 8);
11076     if (type == 0x00000001 && len > 16) {
11077       guint y, m = 1, d = 1;
11078       gint ret;
11079
11080       s = g_strndup ((char *) data->data + 16, len - 16);
11081       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11082       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11083       if (ret >= 1 && y > 1500 && y < 3000) {
11084         GDate *date;
11085
11086         date = g_date_new_dmy (d, m, y);
11087         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11088         g_date_free (date);
11089       } else {
11090         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11091       }
11092       g_free (s);
11093     }
11094   }
11095 }
11096
11097 static void
11098 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11099     const char *tag, const char *dummy, GNode * node)
11100 {
11101   GNode *data;
11102
11103   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11104
11105   /* re-route to normal string tag if major brand says so
11106    * or no data atom and compatible brand suggests so */
11107   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11108       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11109     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11110     return;
11111   }
11112
11113   if (data) {
11114     guint len, type, n;
11115
11116     len = QT_UINT32 (data->data);
11117     type = QT_UINT32 ((guint8 *) data->data + 8);
11118     if (type == 0x00000000 && len >= 18) {
11119       n = QT_UINT16 ((guint8 *) data->data + 16);
11120       if (n > 0) {
11121         const gchar *genre;
11122
11123         genre = gst_tag_id3_genre_get (n - 1);
11124         if (genre != NULL) {
11125           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11126           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11127         }
11128       }
11129     }
11130   }
11131 }
11132
11133 static void
11134 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11135     const gchar * tag, guint8 * data, guint32 datasize)
11136 {
11137   gdouble value;
11138   gchar *datacopy;
11139
11140   /* make a copy to have \0 at the end */
11141   datacopy = g_strndup ((gchar *) data, datasize);
11142
11143   /* convert the str to double */
11144   if (sscanf (datacopy, "%lf", &value) == 1) {
11145     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11146     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11147   } else {
11148     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11149         datacopy);
11150   }
11151   g_free (datacopy);
11152 }
11153
11154
11155 static void
11156 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11157     const char *tag, const char *tag_bis, GNode * node)
11158 {
11159   GNode *mean;
11160   GNode *name;
11161   GNode *data;
11162   guint32 meansize;
11163   guint32 namesize;
11164   guint32 datatype;
11165   guint32 datasize;
11166   const gchar *meanstr;
11167   const gchar *namestr;
11168
11169   /* checking the whole ---- atom size for consistency */
11170   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11171     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11172     return;
11173   }
11174
11175   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11176   if (!mean) {
11177     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11178     return;
11179   }
11180
11181   meansize = QT_UINT32 (mean->data);
11182   if (meansize <= 12) {
11183     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11184     return;
11185   }
11186   meanstr = ((gchar *) mean->data) + 12;
11187   meansize -= 12;
11188
11189   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11190   if (!name) {
11191     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11192     return;
11193   }
11194
11195   namesize = QT_UINT32 (name->data);
11196   if (namesize <= 12) {
11197     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11198     return;
11199   }
11200   namestr = ((gchar *) name->data) + 12;
11201   namesize -= 12;
11202
11203   /*
11204    * Data atom is:
11205    * uint32 - size
11206    * uint32 - name
11207    * uint8  - version
11208    * uint24 - data type
11209    * uint32 - all 0
11210    * rest   - the data
11211    */
11212   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11213   if (!data) {
11214     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11215     return;
11216   }
11217   datasize = QT_UINT32 (data->data);
11218   if (datasize <= 16) {
11219     GST_WARNING_OBJECT (demux, "Data atom too small");
11220     return;
11221   }
11222   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11223
11224   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11225       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11226     static const struct
11227     {
11228       const gchar name[28];
11229       const gchar tag[28];
11230     } tags[] = {
11231       {
11232       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11233       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11234       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11235       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11236       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11237       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11238       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11239       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11240     };
11241     int i;
11242
11243     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11244       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11245         switch (gst_tag_get_type (tags[i].tag)) {
11246           case G_TYPE_DOUBLE:
11247             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11248                 ((guint8 *) data->data) + 16, datasize - 16);
11249             break;
11250           case G_TYPE_STRING:
11251             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11252             break;
11253           default:
11254             /* not reached */
11255             break;
11256         }
11257         break;
11258       }
11259     }
11260     if (i == G_N_ELEMENTS (tags))
11261       goto unknown_tag;
11262   } else {
11263     goto unknown_tag;
11264   }
11265
11266   return;
11267
11268 /* errors */
11269 unknown_tag:
11270 #ifndef GST_DISABLE_GST_DEBUG
11271   {
11272     gchar *namestr_dbg;
11273     gchar *meanstr_dbg;
11274
11275     meanstr_dbg = g_strndup (meanstr, meansize);
11276     namestr_dbg = g_strndup (namestr, namesize);
11277
11278     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11279         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11280
11281     g_free (namestr_dbg);
11282     g_free (meanstr_dbg);
11283   }
11284 #endif
11285   return;
11286 }
11287
11288 static void
11289 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11290     const char *tag_bis, GNode * node)
11291 {
11292   guint8 *data;
11293   GstBuffer *buf;
11294   guint len;
11295   GstTagList *id32_taglist = NULL;
11296
11297   GST_LOG_OBJECT (demux, "parsing ID32");
11298
11299   data = node->data;
11300   len = GST_READ_UINT32_BE (data);
11301
11302   /* need at least full box and language tag */
11303   if (len < 12 + 2)
11304     return;
11305
11306   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11307   gst_buffer_fill (buf, 0, data + 14, len - 14);
11308
11309   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11310   if (id32_taglist) {
11311     GST_LOG_OBJECT (demux, "parsing ok");
11312     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11313     gst_tag_list_unref (id32_taglist);
11314   } else {
11315     GST_LOG_OBJECT (demux, "parsing failed");
11316   }
11317
11318   gst_buffer_unref (buf);
11319 }
11320
11321 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11322     const char *tag, const char *tag_bis, GNode * node);
11323
11324 /* unmapped tags
11325 FOURCC_pcst -> if media is a podcast -> bool
11326 FOURCC_cpil -> if media is part of a compilation -> bool
11327 FOURCC_pgap -> if media is part of a gapless context -> bool
11328 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11329 */
11330
11331 static const struct
11332 {
11333   guint32 fourcc;
11334   const gchar *gst_tag;
11335   const gchar *gst_tag_bis;
11336   const GstQTDemuxAddTagFunc func;
11337 } add_funcs[] = {
11338   {
11339   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11340   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11341   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11342   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11343   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11344   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11345   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11346   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11347   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11348   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11349   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11350   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11351   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11352   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11353   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11354   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11355   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11356   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11357   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11358   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11359   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11360   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11361   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11362         qtdemux_tag_add_num}, {
11363   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11364         qtdemux_tag_add_num}, {
11365   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11366   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11367   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11368   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11369   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11370   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11371   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11372   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11373   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11374   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11375   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11376   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11377   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11378   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11379   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11380   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11381   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11382   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11383         qtdemux_tag_add_classification}, {
11384   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11385   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11386   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11387
11388     /* This is a special case, some tags are stored in this
11389      * 'reverse dns naming', according to:
11390      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11391      * bug #614471
11392      */
11393   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11394     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11395   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11396 };
11397
11398 struct _GstQtDemuxTagList
11399 {
11400   GstQTDemux *demux;
11401   GstTagList *taglist;
11402 };
11403 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11404
11405 static void
11406 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11407 {
11408   gint len;
11409   guint8 *data;
11410   GstBuffer *buf;
11411   gchar *media_type;
11412   const gchar *style;
11413   GstSample *sample;
11414   GstStructure *s;
11415   guint i;
11416   guint8 ndata[4];
11417   GstQTDemux *demux = qtdemuxtaglist->demux;
11418   GstTagList *taglist = qtdemuxtaglist->taglist;
11419
11420   data = node->data;
11421   len = QT_UINT32 (data);
11422   buf = gst_buffer_new_and_alloc (len);
11423   gst_buffer_fill (buf, 0, data, len);
11424
11425   /* heuristic to determine style of tag */
11426   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11427       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11428     style = "itunes";
11429   else if (demux->major_brand == FOURCC_qt__)
11430     style = "quicktime";
11431   /* fall back to assuming iso/3gp tag style */
11432   else
11433     style = "iso";
11434
11435   /* santize the name for the caps. */
11436   for (i = 0; i < 4; i++) {
11437     guint8 d = data[4 + i];
11438     if (g_ascii_isalnum (d))
11439       ndata[i] = g_ascii_tolower (d);
11440     else
11441       ndata[i] = '_';
11442   }
11443
11444   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11445       ndata[0], ndata[1], ndata[2], ndata[3]);
11446   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11447
11448   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11449   sample = gst_sample_new (buf, NULL, NULL, s);
11450   gst_buffer_unref (buf);
11451   g_free (media_type);
11452
11453   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11454       len, s);
11455
11456   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11457       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11458
11459   gst_sample_unref (sample);
11460 }
11461
11462 static void
11463 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11464 {
11465   GNode *meta;
11466   GNode *ilst;
11467   GNode *xmp_;
11468   GNode *node;
11469   gint i;
11470   GstQtDemuxTagList demuxtaglist;
11471
11472   demuxtaglist.demux = qtdemux;
11473   demuxtaglist.taglist = taglist;
11474
11475   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11476   if (meta != NULL) {
11477     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11478     if (ilst == NULL) {
11479       GST_LOG_OBJECT (qtdemux, "no ilst");
11480       return;
11481     }
11482   } else {
11483     ilst = udta;
11484     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11485   }
11486
11487   i = 0;
11488   while (i < G_N_ELEMENTS (add_funcs)) {
11489     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
11490     if (node) {
11491       gint len;
11492
11493       len = QT_UINT32 (node->data);
11494       if (len < 12) {
11495         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
11496             GST_FOURCC_ARGS (add_funcs[i].fourcc));
11497       } else {
11498         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
11499             add_funcs[i].gst_tag_bis, node);
11500       }
11501       g_node_destroy (node);
11502     } else {
11503       i++;
11504     }
11505   }
11506
11507   /* parsed nodes have been removed, pass along remainder as blob */
11508   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
11509       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
11510
11511   /* parse up XMP_ node if existing */
11512   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
11513   if (xmp_ != NULL) {
11514     GstBuffer *buf;
11515     GstTagList *xmptaglist;
11516
11517     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
11518         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
11519     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
11520     gst_buffer_unref (buf);
11521
11522     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
11523   } else {
11524     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
11525   }
11526 }
11527
11528 typedef struct
11529 {
11530   GstStructure *structure;      /* helper for sort function */
11531   gchar *location;
11532   guint min_req_bitrate;
11533   guint min_req_qt_version;
11534 } GstQtReference;
11535
11536 static gint
11537 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
11538 {
11539   GstQtReference *ref_a = (GstQtReference *) a;
11540   GstQtReference *ref_b = (GstQtReference *) b;
11541
11542   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
11543     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
11544
11545   /* known bitrates go before unknown; higher bitrates go first */
11546   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
11547 }
11548
11549 /* sort the redirects and post a message for the application.
11550  */
11551 static void
11552 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
11553 {
11554   GstQtReference *best;
11555   GstStructure *s;
11556   GstMessage *msg;
11557   GValue list_val = { 0, };
11558   GList *l;
11559
11560   g_assert (references != NULL);
11561
11562   references = g_list_sort (references, qtdemux_redirects_sort_func);
11563
11564   best = (GstQtReference *) references->data;
11565
11566   g_value_init (&list_val, GST_TYPE_LIST);
11567
11568   for (l = references; l != NULL; l = l->next) {
11569     GstQtReference *ref = (GstQtReference *) l->data;
11570     GValue struct_val = { 0, };
11571
11572     ref->structure = gst_structure_new ("redirect",
11573         "new-location", G_TYPE_STRING, ref->location, NULL);
11574
11575     if (ref->min_req_bitrate > 0) {
11576       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
11577           ref->min_req_bitrate, NULL);
11578     }
11579
11580     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
11581     g_value_set_boxed (&struct_val, ref->structure);
11582     gst_value_list_append_value (&list_val, &struct_val);
11583     g_value_unset (&struct_val);
11584     /* don't free anything here yet, since we need best->structure below */
11585   }
11586
11587   g_assert (best != NULL);
11588   s = gst_structure_copy (best->structure);
11589
11590   if (g_list_length (references) > 1) {
11591     gst_structure_set_value (s, "locations", &list_val);
11592   }
11593
11594   g_value_unset (&list_val);
11595
11596   for (l = references; l != NULL; l = l->next) {
11597     GstQtReference *ref = (GstQtReference *) l->data;
11598
11599     gst_structure_free (ref->structure);
11600     g_free (ref->location);
11601     g_free (ref);
11602   }
11603   g_list_free (references);
11604
11605   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
11606   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
11607   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
11608   qtdemux->posted_redirect = TRUE;
11609 }
11610
11611 /* look for redirect nodes, collect all redirect information and
11612  * process it.
11613  */
11614 static gboolean
11615 qtdemux_parse_redirects (GstQTDemux * qtdemux)
11616 {
11617   GNode *rmra, *rmda, *rdrf;
11618
11619   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
11620   if (rmra) {
11621     GList *redirects = NULL;
11622
11623     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
11624     while (rmda) {
11625       GstQtReference ref = { NULL, NULL, 0, 0 };
11626       GNode *rmdr, *rmvc;
11627
11628       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
11629         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
11630         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
11631             ref.min_req_bitrate);
11632       }
11633
11634       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
11635         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
11636         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
11637
11638 #ifndef GST_DISABLE_GST_DEBUG
11639         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
11640 #endif
11641         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
11642
11643         GST_LOG_OBJECT (qtdemux,
11644             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
11645             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
11646             bitmask, check_type);
11647         if (package == FOURCC_qtim && check_type == 0) {
11648           ref.min_req_qt_version = version;
11649         }
11650       }
11651
11652       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
11653       if (rdrf) {
11654         guint32 ref_type;
11655         guint8 *ref_data;
11656         guint ref_len;
11657
11658         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
11659         if (ref_len > 20) {
11660           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
11661           ref_data = (guint8 *) rdrf->data + 20;
11662           if (ref_type == FOURCC_alis) {
11663             guint record_len, record_version, fn_len;
11664
11665             if (ref_len > 70) {
11666               /* MacOSX alias record, google for alias-layout.txt */
11667               record_len = QT_UINT16 (ref_data + 4);
11668               record_version = QT_UINT16 (ref_data + 4 + 2);
11669               fn_len = QT_UINT8 (ref_data + 50);
11670               if (record_len > 50 && record_version == 2 && fn_len > 0) {
11671                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
11672               }
11673             } else {
11674               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
11675                   ref_len);
11676             }
11677           } else if (ref_type == FOURCC_url_) {
11678             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
11679           } else {
11680             GST_DEBUG_OBJECT (qtdemux,
11681                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
11682                 GST_FOURCC_ARGS (ref_type));
11683           }
11684           if (ref.location != NULL) {
11685             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
11686             redirects =
11687                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
11688           } else {
11689             GST_WARNING_OBJECT (qtdemux,
11690                 "Failed to extract redirect location from rdrf atom");
11691           }
11692         } else {
11693           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
11694         }
11695       }
11696
11697       /* look for others */
11698       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
11699     }
11700
11701     if (redirects != NULL) {
11702       qtdemux_process_redirects (qtdemux, redirects);
11703     }
11704   }
11705   return TRUE;
11706 }
11707
11708 static GstTagList *
11709 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
11710 {
11711   const gchar *fmt;
11712
11713   if (tags == NULL) {
11714     tags = gst_tag_list_new_empty ();
11715     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
11716   }
11717
11718   if (qtdemux->major_brand == FOURCC_mjp2)
11719     fmt = "Motion JPEG 2000";
11720   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
11721     fmt = "3GP";
11722   else if (qtdemux->major_brand == FOURCC_qt__)
11723     fmt = "Quicktime";
11724   else if (qtdemux->fragmented)
11725     fmt = "ISO fMP4";
11726   else
11727     fmt = "ISO MP4/M4A";
11728
11729   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
11730       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
11731
11732   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
11733       fmt, NULL);
11734
11735   return tags;
11736 }
11737
11738 /* we have read th complete moov node now.
11739  * This function parses all of the relevant info, creates the traks and
11740  * prepares all data structures for playback
11741  */
11742 static gboolean
11743 qtdemux_parse_tree (GstQTDemux * qtdemux)
11744 {
11745   GNode *mvhd;
11746   GNode *trak;
11747   GNode *udta;
11748   GNode *mvex;
11749   GstClockTime duration;
11750   GNode *pssh;
11751   guint64 creation_time;
11752   GstDateTime *datetime = NULL;
11753   gint version;
11754
11755   /* make sure we have a usable taglist */
11756   if (!qtdemux->tag_list) {
11757     qtdemux->tag_list = gst_tag_list_new_empty ();
11758     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11759   } else {
11760     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11761   }
11762
11763   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
11764   if (mvhd == NULL) {
11765     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
11766     return qtdemux_parse_redirects (qtdemux);
11767   }
11768
11769   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
11770   if (version == 1) {
11771     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
11772     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
11773     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
11774   } else if (version == 0) {
11775     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
11776     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
11777     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
11778   } else {
11779     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
11780     return FALSE;
11781   }
11782
11783   /* Moving qt creation time (secs since 1904) to unix time */
11784   if (creation_time != 0) {
11785     /* Try to use epoch first as it should be faster and more commonly found */
11786     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
11787       GTimeVal now;
11788
11789       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
11790       /* some data cleansing sanity */
11791       g_get_current_time (&now);
11792       if (now.tv_sec + 24 * 3600 < creation_time) {
11793         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
11794       } else {
11795         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
11796       }
11797     } else {
11798       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
11799       GDateTime *dt, *dt_local;
11800
11801       dt = g_date_time_add_seconds (base_dt, creation_time);
11802       dt_local = g_date_time_to_local (dt);
11803       datetime = gst_date_time_new_from_g_date_time (dt_local);
11804
11805       g_date_time_unref (base_dt);
11806       g_date_time_unref (dt);
11807     }
11808   }
11809   if (datetime) {
11810     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
11811     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
11812         datetime, NULL);
11813     gst_date_time_unref (datetime);
11814   }
11815
11816   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
11817   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
11818
11819   /* check for fragmented file and get some (default) data */
11820   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
11821   if (mvex) {
11822     GNode *mehd;
11823     GstByteReader mehd_data;
11824
11825     /* let track parsing or anyone know weird stuff might happen ... */
11826     qtdemux->fragmented = TRUE;
11827
11828     /* compensate for total duration */
11829     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
11830     if (mehd)
11831       qtdemux_parse_mehd (qtdemux, &mehd_data);
11832   }
11833
11834   /* set duration in the segment info */
11835   gst_qtdemux_get_duration (qtdemux, &duration);
11836   if (duration) {
11837     qtdemux->segment.duration = duration;
11838     /* also do not exceed duration; stop is set that way post seek anyway,
11839      * and segment activation falls back to duration,
11840      * whereas loop only checks stop, so let's align this here as well */
11841     qtdemux->segment.stop = duration;
11842   }
11843
11844   /* parse all traks */
11845   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
11846   while (trak) {
11847     qtdemux_parse_trak (qtdemux, trak);
11848     /* iterate all siblings */
11849     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
11850   }
11851
11852   if (!qtdemux->tag_list) {
11853     GST_DEBUG_OBJECT (qtdemux, "new tag list");
11854     qtdemux->tag_list = gst_tag_list_new_empty ();
11855     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11856   } else {
11857     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11858   }
11859
11860   /* find tags */
11861   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
11862   if (udta) {
11863     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11864   } else {
11865     GST_LOG_OBJECT (qtdemux, "No udta node found.");
11866   }
11867
11868   /* maybe also some tags in meta box */
11869   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
11870   if (udta) {
11871     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
11872     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11873   } else {
11874     GST_LOG_OBJECT (qtdemux, "No meta node found.");
11875   }
11876
11877   /* parse any protection system info */
11878   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
11879   while (pssh) {
11880     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
11881     qtdemux_parse_pssh (qtdemux, pssh);
11882     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
11883   }
11884
11885   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
11886
11887   return TRUE;
11888 }
11889
11890 /* taken from ffmpeg */
11891 static int
11892 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
11893 {
11894   int count = 4;
11895   int len = 0;
11896
11897   while (count--) {
11898     int c;
11899
11900     if (ptr >= end)
11901       return -1;
11902
11903     c = *ptr++;
11904     len = (len << 7) | (c & 0x7f);
11905     if (!(c & 0x80))
11906       break;
11907   }
11908   *end_out = ptr;
11909   return len;
11910 }
11911
11912 /* this can change the codec originally present in @list */
11913 static void
11914 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
11915     GNode * esds, GstTagList * list)
11916 {
11917   int len = QT_UINT32 (esds->data);
11918   guint8 *ptr = esds->data;
11919   guint8 *end = ptr + len;
11920   int tag;
11921   guint8 *data_ptr = NULL;
11922   int data_len = 0;
11923   guint8 object_type_id = 0;
11924   const char *codec_name = NULL;
11925   GstCaps *caps = NULL;
11926
11927   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
11928   ptr += 8;
11929   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
11930   ptr += 4;
11931   while (ptr + 1 < end) {
11932     tag = QT_UINT8 (ptr);
11933     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
11934     ptr++;
11935     len = read_descr_size (ptr, end, &ptr);
11936     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
11937
11938     /* Check the stated amount of data is available for reading */
11939     if (len < 0 || ptr + len > end)
11940       break;
11941
11942     switch (tag) {
11943       case ES_DESCRIPTOR_TAG:
11944         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
11945         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
11946         ptr += 3;
11947         break;
11948       case DECODER_CONFIG_DESC_TAG:{
11949         guint max_bitrate, avg_bitrate;
11950
11951         object_type_id = QT_UINT8 (ptr);
11952         max_bitrate = QT_UINT32 (ptr + 5);
11953         avg_bitrate = QT_UINT32 (ptr + 9);
11954         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
11955         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
11956         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
11957         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
11958         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
11959         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11960           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
11961               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
11962         }
11963         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11964           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
11965               avg_bitrate, NULL);
11966         }
11967         ptr += 13;
11968         break;
11969       }
11970       case DECODER_SPECIFIC_INFO_TAG:
11971         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
11972         if (object_type_id == 0xe0 && len == 0x40) {
11973           guint8 *data;
11974           GstStructure *s;
11975           guint32 clut[16];
11976           gint i;
11977
11978           GST_DEBUG_OBJECT (qtdemux,
11979               "Have VOBSUB palette. Creating palette event");
11980           /* move to decConfigDescr data and read palette */
11981           data = ptr;
11982           for (i = 0; i < 16; i++) {
11983             clut[i] = QT_UINT32 (data);
11984             data += 4;
11985           }
11986
11987           s = gst_structure_new ("application/x-gst-dvd", "event",
11988               G_TYPE_STRING, "dvd-spu-clut-change",
11989               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
11990               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
11991               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
11992               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
11993               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
11994               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
11995               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
11996               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
11997               NULL);
11998
11999           /* store event and trigger custom processing */
12000           stream->pending_event =
12001               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12002         } else {
12003           /* Generic codec_data handler puts it on the caps */
12004           data_ptr = ptr;
12005           data_len = len;
12006         }
12007
12008         ptr += len;
12009         break;
12010       case SL_CONFIG_DESC_TAG:
12011         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12012         ptr += 1;
12013         break;
12014       default:
12015         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12016             tag);
12017         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12018         ptr += len;
12019         break;
12020     }
12021   }
12022
12023   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12024    * in use, and should also be used to override some other parameters for some
12025    * codecs. */
12026   switch (object_type_id) {
12027     case 0x20:                 /* MPEG-4 */
12028       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12029        * profile_and_level_indication */
12030       if (data_ptr != NULL && data_len >= 5 &&
12031           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12032         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12033             data_ptr + 4, data_len - 4);
12034       }
12035       break;                    /* Nothing special needed here */
12036     case 0x21:                 /* H.264 */
12037       codec_name = "H.264 / AVC";
12038       caps = gst_caps_new_simple ("video/x-h264",
12039           "stream-format", G_TYPE_STRING, "avc",
12040           "alignment", G_TYPE_STRING, "au", NULL);
12041       break;
12042     case 0x40:                 /* AAC (any) */
12043     case 0x66:                 /* AAC Main */
12044     case 0x67:                 /* AAC LC */
12045     case 0x68:                 /* AAC SSR */
12046       /* Override channels and rate based on the codec_data, as it's often
12047        * wrong. */
12048       /* Only do so for basic setup without HE-AAC extension */
12049       if (data_ptr && data_len == 2) {
12050         guint channels, rateindex, rate;
12051
12052         /* FIXME: add gst_codec_utils_aac_get_{channels|sample_rate}()? */
12053         channels = (data_ptr[1] & 0x7f) >> 3;
12054         if (channels > 0 && channels < 7) {
12055           stream->n_channels = channels;
12056         } else if (channels == 7) {
12057           stream->n_channels = 8;
12058         }
12059
12060         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
12061         rate = gst_codec_utils_aac_get_sample_rate_from_index (rateindex);
12062         if (rate > 0)
12063           stream->rate = rate;
12064       }
12065
12066       /* Set level and profile if possible */
12067       if (data_ptr != NULL && data_len >= 2) {
12068         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12069             data_ptr, data_len);
12070       }
12071       break;
12072     case 0x60:                 /* MPEG-2, various profiles */
12073     case 0x61:
12074     case 0x62:
12075     case 0x63:
12076     case 0x64:
12077     case 0x65:
12078       codec_name = "MPEG-2 video";
12079       caps = gst_caps_new_simple ("video/mpeg",
12080           "mpegversion", G_TYPE_INT, 2,
12081           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12082       break;
12083     case 0x69:                 /* MPEG-2 BC audio */
12084     case 0x6B:                 /* MPEG-1 audio */
12085       caps = gst_caps_new_simple ("audio/mpeg",
12086           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12087       codec_name = "MPEG-1 audio";
12088       break;
12089     case 0x6A:                 /* MPEG-1 */
12090       codec_name = "MPEG-1 video";
12091       caps = gst_caps_new_simple ("video/mpeg",
12092           "mpegversion", G_TYPE_INT, 1,
12093           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12094       break;
12095     case 0x6C:                 /* MJPEG */
12096       caps =
12097           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12098           NULL);
12099       codec_name = "Motion-JPEG";
12100       break;
12101     case 0x6D:                 /* PNG */
12102       caps =
12103           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12104           NULL);
12105       codec_name = "PNG still images";
12106       break;
12107     case 0x6E:                 /* JPEG2000 */
12108       codec_name = "JPEG-2000";
12109       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12110       break;
12111     case 0xA4:                 /* Dirac */
12112       codec_name = "Dirac";
12113       caps = gst_caps_new_empty_simple ("video/x-dirac");
12114       break;
12115     case 0xA5:                 /* AC3 */
12116       codec_name = "AC-3 audio";
12117       caps = gst_caps_new_simple ("audio/x-ac3",
12118           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12119       break;
12120     case 0xA9:                 /* AC3 */
12121       codec_name = "DTS audio";
12122       caps = gst_caps_new_simple ("audio/x-dts",
12123           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12124       break;
12125     case 0xE1:                 /* QCELP */
12126       /* QCELP, the codec_data is a riff tag (little endian) with
12127        * 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). */
12128       caps = gst_caps_new_empty_simple ("audio/qcelp");
12129       codec_name = "QCELP";
12130       break;
12131     default:
12132       break;
12133   }
12134
12135   /* If we have a replacement caps, then change our caps for this stream */
12136   if (caps) {
12137     gst_caps_unref (stream->caps);
12138     stream->caps = caps;
12139   }
12140
12141   if (codec_name && list)
12142     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12143         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12144
12145   /* Add the codec_data attribute to caps, if we have it */
12146   if (data_ptr) {
12147     GstBuffer *buffer;
12148
12149     buffer = gst_buffer_new_and_alloc (data_len);
12150     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12151
12152     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12153     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12154
12155     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12156         buffer, NULL);
12157     gst_buffer_unref (buffer);
12158   }
12159
12160 }
12161
12162 #define _codec(name) \
12163   do { \
12164     if (codec_name) { \
12165       *codec_name = g_strdup (name); \
12166     } \
12167   } while (0)
12168
12169 static GstCaps *
12170 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12171     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12172 {
12173   GstCaps *caps = NULL;
12174   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12175
12176   switch (fourcc) {
12177     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12178       _codec ("PNG still images");
12179       caps = gst_caps_new_empty_simple ("image/png");
12180       break;
12181     case FOURCC_jpeg:
12182       _codec ("JPEG still images");
12183       caps =
12184           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12185           NULL);
12186       break;
12187     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12188     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12189     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12190     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12191       _codec ("Motion-JPEG");
12192       caps =
12193           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12194           NULL);
12195       break;
12196     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12197       _codec ("Motion-JPEG format B");
12198       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12199       break;
12200     case FOURCC_mjp2:
12201       _codec ("JPEG-2000");
12202       /* override to what it should be according to spec, avoid palette_data */
12203       stream->bits_per_sample = 24;
12204       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12205       break;
12206     case FOURCC_SVQ3:
12207       _codec ("Sorensen video v.3");
12208       caps = gst_caps_new_simple ("video/x-svq",
12209           "svqversion", G_TYPE_INT, 3, NULL);
12210       break;
12211     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12212     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12213       _codec ("Sorensen video v.1");
12214       caps = gst_caps_new_simple ("video/x-svq",
12215           "svqversion", G_TYPE_INT, 1, NULL);
12216       break;
12217     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12218       caps = gst_caps_new_empty_simple ("video/x-raw");
12219       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12220       _codec ("Windows Raw RGB");
12221       break;
12222     case FOURCC_raw_:
12223     {
12224       guint16 bps;
12225
12226       bps = QT_UINT16 (stsd_data + 98);
12227       switch (bps) {
12228         case 15:
12229           format = GST_VIDEO_FORMAT_RGB15;
12230           break;
12231         case 16:
12232           format = GST_VIDEO_FORMAT_RGB16;
12233           break;
12234         case 24:
12235           format = GST_VIDEO_FORMAT_RGB;
12236           break;
12237         case 32:
12238           format = GST_VIDEO_FORMAT_ARGB;
12239           break;
12240         default:
12241           /* unknown */
12242           break;
12243       }
12244       break;
12245     }
12246     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12247       format = GST_VIDEO_FORMAT_I420;
12248       break;
12249     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12250     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12251       format = GST_VIDEO_FORMAT_I420;
12252       break;
12253     case FOURCC_2vuy:
12254     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12255       format = GST_VIDEO_FORMAT_UYVY;
12256       break;
12257     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12258       format = GST_VIDEO_FORMAT_v308;
12259       break;
12260     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12261       format = GST_VIDEO_FORMAT_v216;
12262       break;
12263     case FOURCC_v210:
12264       format = GST_VIDEO_FORMAT_v210;
12265       break;
12266     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12267       format = GST_VIDEO_FORMAT_r210;
12268       break;
12269       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12270          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12271          format = GST_VIDEO_FORMAT_v410;
12272          break;
12273        */
12274       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12275        * but different order than AYUV
12276        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12277        format = GST_VIDEO_FORMAT_v408;
12278        break;
12279        */
12280     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12281     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12282       _codec ("MPEG-1 video");
12283       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12284           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12285       break;
12286     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12287     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12288     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12289     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12290     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12291     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12292     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12293     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12294     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12295     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12296     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12297     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12298     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12299     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12300     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12301     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12302     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12303     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12304     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12305     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12306     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12307     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12308     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12309     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12310     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12311     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12312     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12313     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12314     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12315     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12316     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12317     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12318     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12319     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12320     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12321     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12322     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12323     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12324     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12325     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12326     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12327     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12328     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12329     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12330     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12331     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12332       _codec ("MPEG-2 video");
12333       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12334           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12335       break;
12336     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12337       _codec ("GIF still images");
12338       caps = gst_caps_new_empty_simple ("image/gif");
12339       break;
12340     case FOURCC_h263:
12341     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12342     case FOURCC_s263:
12343     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12344       _codec ("H.263");
12345       /* ffmpeg uses the height/width props, don't know why */
12346       caps = gst_caps_new_simple ("video/x-h263",
12347           "variant", G_TYPE_STRING, "itu", NULL);
12348       break;
12349     case FOURCC_mp4v:
12350     case FOURCC_MP4V:
12351       _codec ("MPEG-4 video");
12352       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12353           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12354       break;
12355     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12356     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12357       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12358       caps = gst_caps_new_simple ("video/x-msmpeg",
12359           "msmpegversion", G_TYPE_INT, 43, NULL);
12360       break;
12361     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12362       _codec ("DivX 3");
12363       caps = gst_caps_new_simple ("video/x-divx",
12364           "divxversion", G_TYPE_INT, 3, NULL);
12365       break;
12366     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12367     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12368       _codec ("DivX 4");
12369       caps = gst_caps_new_simple ("video/x-divx",
12370           "divxversion", G_TYPE_INT, 4, NULL);
12371       break;
12372     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12373       _codec ("DivX 5");
12374       caps = gst_caps_new_simple ("video/x-divx",
12375           "divxversion", G_TYPE_INT, 5, NULL);
12376       break;
12377
12378     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
12379       _codec ("FFV1");
12380       caps = gst_caps_new_simple ("video/x-ffv",
12381           "ffvversion", G_TYPE_INT, 1, NULL);
12382       break;
12383
12384     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12385     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12386     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12387     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12388     case FOURCC_FMP4:
12389     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12390       caps = gst_caps_new_simple ("video/mpeg",
12391           "mpegversion", G_TYPE_INT, 4, NULL);
12392       _codec ("MPEG-4");
12393       break;
12394
12395     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12396       _codec ("Cinepak");
12397       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12398       break;
12399     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12400       _codec ("Apple QuickDraw");
12401       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12402       break;
12403     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12404       _codec ("Apple video");
12405       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12406       break;
12407     case FOURCC_H264:
12408     case FOURCC_avc1:
12409       _codec ("H.264 / AVC");
12410       caps = gst_caps_new_simple ("video/x-h264",
12411           "stream-format", G_TYPE_STRING, "avc",
12412           "alignment", G_TYPE_STRING, "au", NULL);
12413       break;
12414     case FOURCC_avc3:
12415       _codec ("H.264 / AVC");
12416       caps = gst_caps_new_simple ("video/x-h264",
12417           "stream-format", G_TYPE_STRING, "avc3",
12418           "alignment", G_TYPE_STRING, "au", NULL);
12419       break;
12420     case FOURCC_H265:
12421     case FOURCC_hvc1:
12422       _codec ("H.265 / HEVC");
12423       caps = gst_caps_new_simple ("video/x-h265",
12424           "stream-format", G_TYPE_STRING, "hvc1",
12425           "alignment", G_TYPE_STRING, "au", NULL);
12426       break;
12427     case FOURCC_hev1:
12428       _codec ("H.265 / HEVC");
12429       caps = gst_caps_new_simple ("video/x-h265",
12430           "stream-format", G_TYPE_STRING, "hev1",
12431           "alignment", G_TYPE_STRING, "au", NULL);
12432       break;
12433     case FOURCC_rle_:
12434       _codec ("Run-length encoding");
12435       caps = gst_caps_new_simple ("video/x-rle",
12436           "layout", G_TYPE_STRING, "quicktime", NULL);
12437       break;
12438     case FOURCC_WRLE:
12439       _codec ("Run-length encoding");
12440       caps = gst_caps_new_simple ("video/x-rle",
12441           "layout", G_TYPE_STRING, "microsoft", NULL);
12442       break;
12443     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12444     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12445       _codec ("Indeo Video 3");
12446       caps = gst_caps_new_simple ("video/x-indeo",
12447           "indeoversion", G_TYPE_INT, 3, NULL);
12448       break;
12449     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12450     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12451       _codec ("Intel Video 4");
12452       caps = gst_caps_new_simple ("video/x-indeo",
12453           "indeoversion", G_TYPE_INT, 4, NULL);
12454       break;
12455     case FOURCC_dvcp:
12456     case FOURCC_dvc_:
12457     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12458     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12459     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12460     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12461     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12462     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12463       _codec ("DV Video");
12464       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12465           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12466       break;
12467     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
12468     case FOURCC_dv5p:          /* DVCPRO50 PAL */
12469       _codec ("DVCPro50 Video");
12470       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12471           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12472       break;
12473     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12474     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12475       _codec ("DVCProHD Video");
12476       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12477           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12478       break;
12479     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12480       _codec ("Apple Graphics (SMC)");
12481       caps = gst_caps_new_empty_simple ("video/x-smc");
12482       break;
12483     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12484       _codec ("VP3");
12485       caps = gst_caps_new_empty_simple ("video/x-vp3");
12486       break;
12487     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12488       _codec ("VP6 Flash");
12489       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12490       break;
12491     case FOURCC_XiTh:
12492       _codec ("Theora");
12493       caps = gst_caps_new_empty_simple ("video/x-theora");
12494       /* theora uses one byte of padding in the data stream because it does not
12495        * allow 0 sized packets while theora does */
12496       stream->padding = 1;
12497       break;
12498     case FOURCC_drac:
12499       _codec ("Dirac");
12500       caps = gst_caps_new_empty_simple ("video/x-dirac");
12501       break;
12502     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
12503       _codec ("TIFF still images");
12504       caps = gst_caps_new_empty_simple ("image/tiff");
12505       break;
12506     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
12507       _codec ("Apple Intermediate Codec");
12508       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
12509       break;
12510     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
12511       _codec ("AVID DNxHD");
12512       caps = gst_caps_from_string ("video/x-dnxhd");
12513       break;
12514     case FOURCC_VP80:
12515       _codec ("On2 VP8");
12516       caps = gst_caps_from_string ("video/x-vp8");
12517       break;
12518     case FOURCC_apcs:
12519       _codec ("Apple ProRes LT");
12520       caps =
12521           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
12522           NULL);
12523       break;
12524     case FOURCC_apch:
12525       _codec ("Apple ProRes HQ");
12526       caps =
12527           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
12528           NULL);
12529       break;
12530     case FOURCC_apcn:
12531       _codec ("Apple ProRes");
12532       caps =
12533           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12534           "standard", NULL);
12535       break;
12536     case FOURCC_apco:
12537       _codec ("Apple ProRes Proxy");
12538       caps =
12539           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12540           "proxy", NULL);
12541       break;
12542     case FOURCC_ap4h:
12543       _codec ("Apple ProRes 4444");
12544       caps =
12545           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12546           "4444", NULL);
12547       break;
12548     case FOURCC_vc_1:
12549     case FOURCC_ovc1:
12550       _codec ("VC-1");
12551       caps = gst_caps_new_simple ("video/x-wmv",
12552           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
12553       break;
12554     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
12555     default:
12556     {
12557       char *s, fourstr[5];
12558
12559       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12560       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
12561       caps = gst_caps_new_empty_simple (s);
12562       g_free (s);
12563       break;
12564     }
12565   }
12566
12567   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
12568     GstVideoInfo info;
12569
12570     gst_video_info_init (&info);
12571     gst_video_info_set_format (&info, format, stream->width, stream->height);
12572
12573     caps = gst_video_info_to_caps (&info);
12574     *codec_name = gst_pb_utils_get_codec_description (caps);
12575
12576     /* enable clipping for raw video streams */
12577     stream->need_clip = TRUE;
12578   }
12579
12580   return caps;
12581 }
12582
12583 static GstCaps *
12584 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12585     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
12586 {
12587   GstCaps *caps;
12588   const GstStructure *s;
12589   const gchar *name;
12590   gint endian = 0;
12591   GstAudioFormat format = 0;
12592   gint depth;
12593
12594   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12595
12596   depth = stream->bytes_per_packet * 8;
12597
12598   switch (fourcc) {
12599     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
12600     case FOURCC_raw_:
12601       /* 8-bit audio is unsigned */
12602       if (depth == 8)
12603         format = GST_AUDIO_FORMAT_U8;
12604       /* otherwise it's signed and big-endian just like 'twos' */
12605     case FOURCC_twos:
12606       endian = G_BIG_ENDIAN;
12607       /* fall-through */
12608     case FOURCC_sowt:
12609     {
12610       gchar *str;
12611
12612       if (!endian)
12613         endian = G_LITTLE_ENDIAN;
12614
12615       if (!format)
12616         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
12617
12618       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
12619       _codec (str);
12620       g_free (str);
12621
12622       caps = gst_caps_new_simple ("audio/x-raw",
12623           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12624           "layout", G_TYPE_STRING, "interleaved", NULL);
12625       break;
12626     }
12627     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
12628       _codec ("Raw 64-bit floating-point audio");
12629       caps = gst_caps_new_simple ("audio/x-raw",
12630           "format", G_TYPE_STRING, "F64BE",
12631           "layout", G_TYPE_STRING, "interleaved", NULL);
12632       break;
12633     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
12634       _codec ("Raw 32-bit floating-point audio");
12635       caps = gst_caps_new_simple ("audio/x-raw",
12636           "format", G_TYPE_STRING, "F32BE",
12637           "layout", G_TYPE_STRING, "interleaved", NULL);
12638       break;
12639     case FOURCC_in24:
12640       _codec ("Raw 24-bit PCM audio");
12641       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
12642        * endian later */
12643       caps = gst_caps_new_simple ("audio/x-raw",
12644           "format", G_TYPE_STRING, "S24BE",
12645           "layout", G_TYPE_STRING, "interleaved", NULL);
12646       break;
12647     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
12648       _codec ("Raw 32-bit PCM audio");
12649       caps = gst_caps_new_simple ("audio/x-raw",
12650           "format", G_TYPE_STRING, "S32BE",
12651           "layout", G_TYPE_STRING, "interleaved", NULL);
12652       break;
12653     case FOURCC_ulaw:
12654       _codec ("Mu-law audio");
12655       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
12656       break;
12657     case FOURCC_alaw:
12658       _codec ("A-law audio");
12659       caps = gst_caps_new_empty_simple ("audio/x-alaw");
12660       break;
12661     case 0x0200736d:
12662     case 0x6d730002:
12663       _codec ("Microsoft ADPCM");
12664       /* Microsoft ADPCM-ACM code 2 */
12665       caps = gst_caps_new_simple ("audio/x-adpcm",
12666           "layout", G_TYPE_STRING, "microsoft", NULL);
12667       break;
12668     case 0x1100736d:
12669     case 0x6d730011:
12670       _codec ("DVI/IMA ADPCM");
12671       caps = gst_caps_new_simple ("audio/x-adpcm",
12672           "layout", G_TYPE_STRING, "dvi", NULL);
12673       break;
12674     case 0x1700736d:
12675     case 0x6d730017:
12676       _codec ("DVI/Intel IMA ADPCM");
12677       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
12678       caps = gst_caps_new_simple ("audio/x-adpcm",
12679           "layout", G_TYPE_STRING, "quicktime", NULL);
12680       break;
12681     case 0x5500736d:
12682     case 0x6d730055:
12683       /* MPEG layer 3, CBR only (pre QT4.1) */
12684     case FOURCC__mp3:
12685       _codec ("MPEG-1 layer 3");
12686       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
12687       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
12688           "mpegversion", G_TYPE_INT, 1, NULL);
12689       break;
12690     case 0x20736d:
12691     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
12692       _codec ("EAC-3 audio");
12693       caps = gst_caps_new_simple ("audio/x-eac3",
12694           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12695       stream->sampled = TRUE;
12696       break;
12697     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
12698     case FOURCC_ac_3:
12699       _codec ("AC-3 audio");
12700       caps = gst_caps_new_simple ("audio/x-ac3",
12701           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12702       stream->sampled = TRUE;
12703       break;
12704     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
12705     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
12706       _codec ("DTS audio");
12707       caps = gst_caps_new_simple ("audio/x-dts",
12708           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12709       stream->sampled = TRUE;
12710       break;
12711     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
12712     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
12713       _codec ("DTS-HD audio");
12714       caps = gst_caps_new_simple ("audio/x-dts",
12715           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12716       stream->sampled = TRUE;
12717       break;
12718     case FOURCC_MAC3:
12719       _codec ("MACE-3");
12720       caps = gst_caps_new_simple ("audio/x-mace",
12721           "maceversion", G_TYPE_INT, 3, NULL);
12722       break;
12723     case FOURCC_MAC6:
12724       _codec ("MACE-6");
12725       caps = gst_caps_new_simple ("audio/x-mace",
12726           "maceversion", G_TYPE_INT, 6, NULL);
12727       break;
12728     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
12729       /* ogg/vorbis */
12730       caps = gst_caps_new_empty_simple ("application/ogg");
12731       break;
12732     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
12733       _codec ("DV audio");
12734       caps = gst_caps_new_empty_simple ("audio/x-dv");
12735       break;
12736     case FOURCC_mp4a:
12737       _codec ("MPEG-4 AAC audio");
12738       caps = gst_caps_new_simple ("audio/mpeg",
12739           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
12740           "stream-format", G_TYPE_STRING, "raw", NULL);
12741       break;
12742     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
12743       _codec ("QDesign Music");
12744       caps = gst_caps_new_empty_simple ("audio/x-qdm");
12745       break;
12746     case FOURCC_QDM2:
12747       _codec ("QDesign Music v.2");
12748       /* FIXME: QDesign music version 2 (no constant) */
12749       if (FALSE && data) {
12750         caps = gst_caps_new_simple ("audio/x-qdm2",
12751             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
12752             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
12753             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
12754       } else {
12755         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
12756       }
12757       break;
12758     case FOURCC_agsm:
12759       _codec ("GSM audio");
12760       caps = gst_caps_new_empty_simple ("audio/x-gsm");
12761       break;
12762     case FOURCC_samr:
12763       _codec ("AMR audio");
12764       caps = gst_caps_new_empty_simple ("audio/AMR");
12765       break;
12766     case FOURCC_sawb:
12767       _codec ("AMR-WB audio");
12768       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
12769       break;
12770     case FOURCC_ima4:
12771       _codec ("Quicktime IMA ADPCM");
12772       caps = gst_caps_new_simple ("audio/x-adpcm",
12773           "layout", G_TYPE_STRING, "quicktime", NULL);
12774       break;
12775     case FOURCC_alac:
12776       _codec ("Apple lossless audio");
12777       caps = gst_caps_new_empty_simple ("audio/x-alac");
12778       break;
12779     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
12780       _codec ("QualComm PureVoice");
12781       caps = gst_caps_from_string ("audio/qcelp");
12782       break;
12783     case FOURCC_wma_:
12784     case FOURCC_owma:
12785       _codec ("WMA");
12786       caps = gst_caps_new_empty_simple ("audio/x-wma");
12787       break;
12788     case FOURCC_opus:
12789       _codec ("Opus");
12790       caps = gst_caps_new_empty_simple ("audio/x-opus");
12791       break;
12792     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
12793     {
12794       guint32 flags = 0;
12795       guint32 depth = 0;
12796       guint32 width = 0;
12797       GstAudioFormat format;
12798       enum
12799       {
12800         FLAG_IS_FLOAT = 0x1,
12801         FLAG_IS_BIG_ENDIAN = 0x2,
12802         FLAG_IS_SIGNED = 0x4,
12803         FLAG_IS_PACKED = 0x8,
12804         FLAG_IS_ALIGNED_HIGH = 0x10,
12805         FLAG_IS_NON_INTERLEAVED = 0x20
12806       };
12807       _codec ("Raw LPCM audio");
12808
12809       if (data && len >= 56) {
12810         depth = QT_UINT32 (data + 40);
12811         flags = QT_UINT32 (data + 44);
12812         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
12813       }
12814       if ((flags & FLAG_IS_FLOAT) == 0) {
12815         if (depth == 0)
12816           depth = 16;
12817         if (width == 0)
12818           width = 16;
12819         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
12820             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
12821             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
12822         caps = gst_caps_new_simple ("audio/x-raw",
12823             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12824             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12825             "non-interleaved" : "interleaved", NULL);
12826       } else {
12827         if (width == 0)
12828           width = 32;
12829         if (width == 64) {
12830           if (flags & FLAG_IS_BIG_ENDIAN)
12831             format = GST_AUDIO_FORMAT_F64BE;
12832           else
12833             format = GST_AUDIO_FORMAT_F64LE;
12834         } else {
12835           if (flags & FLAG_IS_BIG_ENDIAN)
12836             format = GST_AUDIO_FORMAT_F32BE;
12837           else
12838             format = GST_AUDIO_FORMAT_F32LE;
12839         }
12840         caps = gst_caps_new_simple ("audio/x-raw",
12841             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12842             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12843             "non-interleaved" : "interleaved", NULL);
12844       }
12845       break;
12846     }
12847     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
12848       /* ? */
12849     default:
12850     {
12851       char *s, fourstr[5];
12852
12853       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12854       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
12855       caps = gst_caps_new_empty_simple (s);
12856       g_free (s);
12857       break;
12858     }
12859   }
12860
12861   if (caps) {
12862     GstCaps *templ_caps =
12863         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
12864     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
12865     gst_caps_unref (caps);
12866     gst_caps_unref (templ_caps);
12867     caps = intersection;
12868   }
12869
12870   /* enable clipping for raw audio streams */
12871   s = gst_caps_get_structure (caps, 0);
12872   name = gst_structure_get_name (s);
12873   if (g_str_has_prefix (name, "audio/x-raw")) {
12874     stream->need_clip = TRUE;
12875     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
12876     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
12877   }
12878   return caps;
12879 }
12880
12881 static GstCaps *
12882 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12883     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12884 {
12885   GstCaps *caps;
12886
12887   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12888
12889   switch (fourcc) {
12890     case FOURCC_mp4s:
12891       _codec ("DVD subtitle");
12892       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
12893       stream->need_process = TRUE;
12894       break;
12895     case FOURCC_text:
12896       _codec ("Quicktime timed text");
12897       goto text;
12898     case FOURCC_tx3g:
12899       _codec ("3GPP timed text");
12900     text:
12901       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
12902           "utf8", NULL);
12903       /* actual text piece needs to be extracted */
12904       stream->need_process = TRUE;
12905       break;
12906     case FOURCC_stpp:
12907       _codec ("XML subtitles");
12908       caps = gst_caps_new_empty_simple ("application/ttml+xml");
12909       break;
12910     default:
12911     {
12912       char *s, fourstr[5];
12913
12914       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12915       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
12916       caps = gst_caps_new_empty_simple (s);
12917       g_free (s);
12918       break;
12919     }
12920   }
12921   return caps;
12922 }
12923
12924 static GstCaps *
12925 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12926     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12927 {
12928   GstCaps *caps;
12929
12930   switch (fourcc) {
12931     case FOURCC_m1v:
12932       _codec ("MPEG 1 video");
12933       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12934           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12935       break;
12936     default:
12937       caps = NULL;
12938       break;
12939   }
12940   return caps;
12941 }
12942
12943 static void
12944 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
12945     const gchar * system_id)
12946 {
12947   gint i;
12948
12949   if (!qtdemux->protection_system_ids)
12950     qtdemux->protection_system_ids =
12951         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
12952   /* Check whether we already have an entry for this system ID. */
12953   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
12954     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
12955     if (g_ascii_strcasecmp (system_id, id) == 0) {
12956       return;
12957     }
12958   }
12959   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
12960   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
12961           -1));
12962 }