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