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