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