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