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