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