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