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