qtdemux: Fix leak of palette_data in error cases
[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       g_free (palette_data);
7495       goto unknown_stream;
7496     }
7497
7498     if (codec) {
7499       list = gst_tag_list_new_empty ();
7500       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
7501           GST_TAG_VIDEO_CODEC, codec, NULL);
7502       g_free (codec);
7503       codec = NULL;
7504     }
7505
7506
7507     if (palette_data) {
7508       GstStructure *s;
7509
7510       if (stream->rgb8_palette)
7511         gst_memory_unref (stream->rgb8_palette);
7512       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
7513           palette_data, palette_size, 0, palette_size, palette_data, g_free);
7514
7515       s = gst_caps_get_structure (stream->caps, 0);
7516
7517       /* non-raw video has a palette_data property. raw video has the palette as
7518        * an extra plane that we append to the output buffers before we push
7519        * them*/
7520       if (!gst_structure_has_name (s, "video/x-raw")) {
7521         GstBuffer *palette;
7522
7523         palette = gst_buffer_new ();
7524         gst_buffer_append_memory (palette, stream->rgb8_palette);
7525         stream->rgb8_palette = NULL;
7526
7527         gst_caps_set_simple (stream->caps, "palette_data",
7528             GST_TYPE_BUFFER, palette, NULL);
7529         gst_buffer_unref (palette);
7530       }
7531     } else if (palette_count != 0) {
7532       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
7533           (NULL), ("Unsupported palette depth %d", depth));
7534     }
7535
7536     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
7537         QT_UINT16 (stsd_data + offset + 48));
7538
7539     esds = NULL;
7540     pasp = NULL;
7541     /* pick 'the' stsd child */
7542     mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
7543     if (mp4v) {
7544       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
7545       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
7546     }
7547
7548     if (pasp) {
7549       const guint8 *pasp_data = (const guint8 *) pasp->data;
7550
7551       stream->par_w = QT_UINT32 (pasp_data + 8);
7552       stream->par_h = QT_UINT32 (pasp_data + 12);
7553     } else {
7554       stream->par_w = 0;
7555       stream->par_h = 0;
7556     }
7557
7558     if (esds) {
7559       gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
7560     } else {
7561       switch (fourcc) {
7562         case FOURCC_H264:
7563         case FOURCC_avc1:
7564         case FOURCC_avc3:
7565         {
7566           gint len = QT_UINT32 (stsd_data) - 0x66;
7567           const guint8 *avc_data = stsd_data + 0x66;
7568
7569           /* find avcC */
7570           while (len >= 0x8) {
7571             gint size;
7572
7573             if (QT_UINT32 (avc_data) <= len)
7574               size = QT_UINT32 (avc_data) - 0x8;
7575             else
7576               size = len - 0x8;
7577
7578             if (size < 1)
7579               /* No real data, so break out */
7580               break;
7581
7582             switch (QT_FOURCC (avc_data + 0x4)) {
7583               case FOURCC_avcC:
7584               {
7585                 /* parse, if found */
7586                 GstBuffer *buf;
7587
7588                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
7589
7590                 /* First 4 bytes are the length of the atom, the next 4 bytes
7591                  * are the fourcc, the next 1 byte is the version, and the
7592                  * subsequent bytes are profile_tier_level structure like data. */
7593                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
7594                     avc_data + 8 + 1, size - 1);
7595                 buf = gst_buffer_new_and_alloc (size);
7596                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
7597                 gst_caps_set_simple (stream->caps,
7598                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
7599                 gst_buffer_unref (buf);
7600
7601                 break;
7602               }
7603               case FOURCC_strf:
7604               {
7605                 GstBuffer *buf;
7606
7607                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
7608
7609                 /* First 4 bytes are the length of the atom, the next 4 bytes
7610                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
7611                  * next 1 byte is the version, and the
7612                  * subsequent bytes are sequence parameter set like data. */
7613
7614                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
7615                 if (size > 1) {
7616                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
7617                       avc_data + 8 + 40 + 1, size - 1);
7618
7619                   buf = gst_buffer_new_and_alloc (size);
7620                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
7621                   gst_caps_set_simple (stream->caps,
7622                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
7623                   gst_buffer_unref (buf);
7624                 }
7625                 break;
7626               }
7627               case FOURCC_btrt:
7628               {
7629                 guint avg_bitrate, max_bitrate;
7630
7631                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
7632                 if (size < 12)
7633                   break;
7634
7635                 max_bitrate = QT_UINT32 (avc_data + 0xc);
7636                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
7637
7638                 if (!max_bitrate && !avg_bitrate)
7639                   break;
7640
7641                 /* Some muxers seem to swap the average and maximum bitrates
7642                  * (I'm looking at you, YouTube), so we swap for sanity. */
7643                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
7644                   guint temp = avg_bitrate;
7645
7646                   avg_bitrate = max_bitrate;
7647                   max_bitrate = temp;
7648                 }
7649
7650                 if (!list)
7651                   list = gst_tag_list_new_empty ();
7652
7653                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
7654                   gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
7655                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
7656                 }
7657                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
7658                   gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
7659                       GST_TAG_BITRATE, avg_bitrate, NULL);
7660                 }
7661
7662                 break;
7663               }
7664
7665               default:
7666                 break;
7667             }
7668
7669             len -= size + 8;
7670             avc_data += size + 8;
7671           }
7672
7673           break;
7674         }
7675         case FOURCC_H265:
7676         case FOURCC_hvc1:
7677         case FOURCC_hev1:
7678         {
7679           gint len = QT_UINT32 (stsd_data) - 0x66;
7680           const guint8 *hevc_data = stsd_data + 0x66;
7681
7682           /* find hevc */
7683           while (len >= 0x8) {
7684             gint size;
7685
7686             if (QT_UINT32 (hevc_data) <= len)
7687               size = QT_UINT32 (hevc_data) - 0x8;
7688             else
7689               size = len - 0x8;
7690
7691             if (size < 1)
7692               /* No real data, so break out */
7693               break;
7694
7695             switch (QT_FOURCC (hevc_data + 0x4)) {
7696               case FOURCC_hvcC:
7697               {
7698                 /* parse, if found */
7699                 GstBuffer *buf;
7700
7701                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
7702
7703                 /* First 4 bytes are the length of the atom, the next 4 bytes
7704                  * are the fourcc, the next 1 byte is the version, and the
7705                  * subsequent bytes are sequence parameter set like data. */
7706                 gst_codec_utils_h265_caps_set_level_tier_and_profile
7707                     (stream->caps, hevc_data + 8 + 1, size - 1);
7708
7709                 buf = gst_buffer_new_and_alloc (size);
7710                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
7711                 gst_caps_set_simple (stream->caps,
7712                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
7713                 gst_buffer_unref (buf);
7714                 break;
7715               }
7716               default:
7717                 break;
7718             }
7719             len -= size + 8;
7720             hevc_data += size + 8;
7721           }
7722           break;
7723         }
7724         case FOURCC_mp4v:
7725         case FOURCC_MP4V:
7726         case FOURCC_fmp4:
7727         case FOURCC_FMP4:
7728         {
7729           GNode *glbl;
7730
7731           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
7732               GST_FOURCC_ARGS (fourcc));
7733
7734           /* codec data might be in glbl extension atom */
7735           glbl = mp4v ?
7736               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
7737           if (glbl) {
7738             guint8 *data;
7739             GstBuffer *buf;
7740             gint len;
7741
7742             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
7743             data = glbl->data;
7744             len = QT_UINT32 (data);
7745             if (len > 0x8) {
7746               len -= 0x8;
7747               buf = gst_buffer_new_and_alloc (len);
7748               gst_buffer_fill (buf, 0, data + 8, len);
7749               gst_caps_set_simple (stream->caps,
7750                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
7751               gst_buffer_unref (buf);
7752             }
7753           }
7754           break;
7755         }
7756         case FOURCC_mjp2:
7757         {
7758           /* see annex I of the jpeg2000 spec */
7759           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
7760           const guint8 *data;
7761           const gchar *colorspace = NULL;
7762           gint ncomp = 0;
7763           guint32 ncomp_map = 0;
7764           gint32 *comp_map = NULL;
7765           guint32 nchan_def = 0;
7766           gint32 *chan_def = NULL;
7767
7768           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
7769           /* some required atoms */
7770           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
7771           if (!mjp2)
7772             break;
7773           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
7774           if (!jp2h)
7775             break;
7776
7777           /* number of components; redundant with info in codestream, but useful
7778              to a muxer */
7779           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
7780           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
7781             break;
7782           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
7783
7784           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
7785           if (!colr)
7786             break;
7787           GST_DEBUG_OBJECT (qtdemux, "found colr");
7788           /* extract colour space info */
7789           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
7790             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
7791               case 16:
7792                 colorspace = "sRGB";
7793                 break;
7794               case 17:
7795                 colorspace = "GRAY";
7796                 break;
7797               case 18:
7798                 colorspace = "sYUV";
7799                 break;
7800               default:
7801                 colorspace = NULL;
7802                 break;
7803             }
7804           }
7805           if (!colorspace)
7806             /* colr is required, and only values 16, 17, and 18 are specified,
7807                so error if we have no colorspace */
7808             break;
7809
7810           /* extract component mapping */
7811           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
7812           if (cmap) {
7813             guint32 cmap_len = 0;
7814             int i;
7815             cmap_len = QT_UINT32 (cmap->data);
7816             if (cmap_len >= 8) {
7817               /* normal box, subtract off header */
7818               cmap_len -= 8;
7819               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
7820               if (cmap_len % 4 == 0) {
7821                 ncomp_map = (cmap_len / 4);
7822                 comp_map = g_new0 (gint32, ncomp_map);
7823                 for (i = 0; i < ncomp_map; i++) {
7824                   guint16 cmp;
7825                   guint8 mtyp, pcol;
7826                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
7827                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
7828                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
7829                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
7830                 }
7831               }
7832             }
7833           }
7834           /* extract channel definitions */
7835           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
7836           if (cdef) {
7837             guint32 cdef_len = 0;
7838             int i;
7839             cdef_len = QT_UINT32 (cdef->data);
7840             if (cdef_len >= 10) {
7841               /* normal box, subtract off header and len */
7842               cdef_len -= 10;
7843               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
7844               if (cdef_len % 6 == 0) {
7845                 nchan_def = (cdef_len / 6);
7846                 chan_def = g_new0 (gint32, nchan_def);
7847                 for (i = 0; i < nchan_def; i++)
7848                   chan_def[i] = -1;
7849                 for (i = 0; i < nchan_def; i++) {
7850                   guint16 cn, typ, asoc;
7851                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
7852                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
7853                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
7854                   if (cn < nchan_def) {
7855                     switch (typ) {
7856                       case 0:
7857                         chan_def[cn] = asoc;
7858                         break;
7859                       case 1:
7860                         chan_def[cn] = 0;       /* alpha */
7861                         break;
7862                       default:
7863                         chan_def[cn] = -typ;
7864                     }
7865                   }
7866                 }
7867               }
7868             }
7869           }
7870
7871           gst_caps_set_simple (stream->caps,
7872               "num-components", G_TYPE_INT, ncomp, NULL);
7873           gst_caps_set_simple (stream->caps,
7874               "colorspace", G_TYPE_STRING, colorspace, NULL);
7875
7876           if (comp_map) {
7877             GValue arr = { 0, };
7878             GValue elt = { 0, };
7879             int i;
7880             g_value_init (&arr, GST_TYPE_ARRAY);
7881             g_value_init (&elt, G_TYPE_INT);
7882             for (i = 0; i < ncomp_map; i++) {
7883               g_value_set_int (&elt, comp_map[i]);
7884               gst_value_array_append_value (&arr, &elt);
7885             }
7886             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
7887                 "component-map", &arr);
7888             g_value_unset (&elt);
7889             g_value_unset (&arr);
7890             g_free (comp_map);
7891           }
7892
7893           if (chan_def) {
7894             GValue arr = { 0, };
7895             GValue elt = { 0, };
7896             int i;
7897             g_value_init (&arr, GST_TYPE_ARRAY);
7898             g_value_init (&elt, G_TYPE_INT);
7899             for (i = 0; i < nchan_def; i++) {
7900               g_value_set_int (&elt, chan_def[i]);
7901               gst_value_array_append_value (&arr, &elt);
7902             }
7903             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
7904                 "channel-definitions", &arr);
7905             g_value_unset (&elt);
7906             g_value_unset (&arr);
7907             g_free (chan_def);
7908           }
7909
7910           /* some optional atoms */
7911           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
7912           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
7913
7914           /* indicate possible fields in caps */
7915           if (field) {
7916             data = (guint8 *) field->data + 8;
7917             if (*data != 1)
7918               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
7919                   (gint) * data, NULL);
7920           }
7921           /* add codec_data if provided */
7922           if (prefix) {
7923             GstBuffer *buf;
7924             gint len;
7925
7926             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
7927             data = prefix->data;
7928             len = QT_UINT32 (data);
7929             if (len > 0x8) {
7930               len -= 0x8;
7931               buf = gst_buffer_new_and_alloc (len);
7932               gst_buffer_fill (buf, 0, data + 8, len);
7933               gst_caps_set_simple (stream->caps,
7934                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
7935               gst_buffer_unref (buf);
7936             }
7937           }
7938           break;
7939         }
7940         case FOURCC_SVQ3:
7941         case FOURCC_VP31:
7942         {
7943           GstBuffer *buf;
7944           GstBuffer *seqh = NULL;
7945           guint8 *gamma_data = NULL;
7946           gint len = QT_UINT32 (stsd_data);
7947
7948           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
7949           if (gamma_data) {
7950             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
7951                 QT_FP32 (gamma_data), NULL);
7952           }
7953           if (seqh) {
7954             /* sorry for the bad name, but we don't know what this is, other
7955              * than its own fourcc */
7956             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
7957                 NULL);
7958           }
7959
7960           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
7961           buf = gst_buffer_new_and_alloc (len);
7962           gst_buffer_fill (buf, 0, stsd_data, len);
7963           gst_caps_set_simple (stream->caps,
7964               "codec_data", GST_TYPE_BUFFER, buf, NULL);
7965           gst_buffer_unref (buf);
7966           break;
7967         }
7968         case FOURCC_rle_:
7969         case FOURCC_WRLE:
7970         {
7971           gst_caps_set_simple (stream->caps,
7972               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
7973           break;
7974         }
7975         case FOURCC_XiTh:
7976         {
7977           GNode *xith, *xdxt;
7978
7979           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
7980           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
7981           if (!xith)
7982             break;
7983
7984           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
7985           if (!xdxt)
7986             break;
7987
7988           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
7989           /* collect the headers and store them in a stream list so that we can
7990            * send them out first */
7991           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
7992           break;
7993         }
7994         case FOURCC_ovc1:
7995         {
7996           GNode *ovc1;
7997           guint8 *ovc1_data;
7998           guint ovc1_len;
7999           GstBuffer *buf;
8000
8001           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
8002           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
8003           if (!ovc1)
8004             break;
8005           ovc1_data = ovc1->data;
8006           ovc1_len = QT_UINT32 (ovc1_data);
8007           if (ovc1_len <= 198) {
8008             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
8009             break;
8010           }
8011           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
8012           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
8013           gst_caps_set_simple (stream->caps,
8014               "codec_data", GST_TYPE_BUFFER, buf, NULL);
8015           gst_buffer_unref (buf);
8016           break;
8017         }
8018         default:
8019           break;
8020       }
8021     }
8022
8023     GST_INFO_OBJECT (qtdemux,
8024         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
8025         GST_FOURCC_ARGS (fourcc), stream->caps);
8026
8027   } else if (stream->subtype == FOURCC_soun) {
8028     int version, samplesize;
8029     guint16 compression_id;
8030     gboolean amrwb = FALSE;
8031
8032     offset = 32;
8033     /* sample description entry (16) + sound sample description v0 (20) */
8034     if (len < 36)
8035       goto corrupt_file;
8036
8037     version = QT_UINT32 (stsd_data + offset);
8038     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
8039     samplesize = QT_UINT16 (stsd_data + offset + 10);
8040     compression_id = QT_UINT16 (stsd_data + offset + 12);
8041     stream->rate = QT_FP32 (stsd_data + offset + 16);
8042
8043     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
8044     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
8045         QT_UINT32 (stsd_data + offset + 4));
8046     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
8047     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
8048     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
8049     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
8050         QT_UINT16 (stsd_data + offset + 14));
8051     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
8052
8053     if (compression_id == 0xfffe)
8054       stream->sampled = TRUE;
8055
8056     /* first assume uncompressed audio */
8057     stream->bytes_per_sample = samplesize / 8;
8058     stream->samples_per_frame = stream->n_channels;
8059     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
8060     stream->samples_per_packet = stream->samples_per_frame;
8061     stream->bytes_per_packet = stream->bytes_per_sample;
8062
8063     offset = 52;
8064     switch (fourcc) {
8065         /* Yes, these have to be hard-coded */
8066       case FOURCC_MAC6:
8067       {
8068         stream->samples_per_packet = 6;
8069         stream->bytes_per_packet = 1;
8070         stream->bytes_per_frame = 1 * stream->n_channels;
8071         stream->bytes_per_sample = 1;
8072         stream->samples_per_frame = 6 * stream->n_channels;
8073         break;
8074       }
8075       case FOURCC_MAC3:
8076       {
8077         stream->samples_per_packet = 3;
8078         stream->bytes_per_packet = 1;
8079         stream->bytes_per_frame = 1 * stream->n_channels;
8080         stream->bytes_per_sample = 1;
8081         stream->samples_per_frame = 3 * stream->n_channels;
8082         break;
8083       }
8084       case FOURCC_ima4:
8085       {
8086         stream->samples_per_packet = 64;
8087         stream->bytes_per_packet = 34;
8088         stream->bytes_per_frame = 34 * stream->n_channels;
8089         stream->bytes_per_sample = 2;
8090         stream->samples_per_frame = 64 * stream->n_channels;
8091         break;
8092       }
8093       case FOURCC_ulaw:
8094       case FOURCC_alaw:
8095       {
8096         stream->samples_per_packet = 1;
8097         stream->bytes_per_packet = 1;
8098         stream->bytes_per_frame = 1 * stream->n_channels;
8099         stream->bytes_per_sample = 1;
8100         stream->samples_per_frame = 1 * stream->n_channels;
8101         break;
8102       }
8103       case FOURCC_agsm:
8104       {
8105         stream->samples_per_packet = 160;
8106         stream->bytes_per_packet = 33;
8107         stream->bytes_per_frame = 33 * stream->n_channels;
8108         stream->bytes_per_sample = 2;
8109         stream->samples_per_frame = 160 * stream->n_channels;
8110         break;
8111       }
8112       default:
8113         break;
8114     }
8115
8116     if (version == 0x00010000) {
8117       /* sample description entry (16) + sound sample description v1 (20+16) */
8118       if (len < 52)
8119         goto corrupt_file;
8120
8121       switch (fourcc) {
8122         case FOURCC_twos:
8123         case FOURCC_sowt:
8124         case FOURCC_raw_:
8125           break;
8126         default:
8127         {
8128           /* only parse extra decoding config for non-pcm audio */
8129           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
8130           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
8131           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
8132           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
8133
8134           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
8135               stream->samples_per_packet);
8136           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
8137               stream->bytes_per_packet);
8138           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
8139               stream->bytes_per_frame);
8140           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
8141               stream->bytes_per_sample);
8142
8143           if (!stream->sampled && stream->bytes_per_packet) {
8144             stream->samples_per_frame = (stream->bytes_per_frame /
8145                 stream->bytes_per_packet) * stream->samples_per_packet;
8146             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
8147                 stream->samples_per_frame);
8148           }
8149           break;
8150         }
8151       }
8152     } else if (version == 0x00020000) {
8153       union
8154       {
8155         gdouble fp;
8156         guint64 val;
8157       } qtfp;
8158
8159       /* sample description entry (16) + sound sample description v2 (56) */
8160       if (len < 72)
8161         goto corrupt_file;
8162
8163       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
8164       stream->rate = qtfp.fp;
8165       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
8166
8167       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
8168       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
8169       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
8170       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
8171           QT_UINT32 (stsd_data + offset + 20));
8172       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
8173           QT_UINT32 (stsd_data + offset + 24));
8174       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
8175           QT_UINT32 (stsd_data + offset + 28));
8176       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
8177           QT_UINT32 (stsd_data + offset + 32));
8178     } else {
8179       GST_WARNING_OBJECT (qtdemux, "unknown version %08x", version);
8180     }
8181
8182     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
8183         stsd_data + 32, len - 16, &codec);
8184
8185     switch (fourcc) {
8186       case FOURCC_in24:
8187       {
8188         GNode *enda;
8189         GNode *in24;
8190
8191         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
8192
8193         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
8194         if (!enda) {
8195           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
8196           if (wave)
8197             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
8198         }
8199         if (enda) {
8200           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
8201           gst_caps_set_simple (stream->caps,
8202               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
8203         }
8204         break;
8205       }
8206       case FOURCC_owma:
8207       {
8208         GNode *owma;
8209         const guint8 *owma_data;
8210         const gchar *codec_name = NULL;
8211         guint owma_len;
8212         GstBuffer *buf;
8213         gint version = 1;
8214         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
8215         /* FIXME this should also be gst_riff_strf_auds,
8216          * but the latter one is actually missing bits-per-sample :( */
8217         typedef struct
8218         {
8219           gint16 wFormatTag;
8220           gint16 nChannels;
8221           gint32 nSamplesPerSec;
8222           gint32 nAvgBytesPerSec;
8223           gint16 nBlockAlign;
8224           gint16 wBitsPerSample;
8225           gint16 cbSize;
8226         } WAVEFORMATEX;
8227         WAVEFORMATEX *wfex;
8228
8229         GST_DEBUG_OBJECT (qtdemux, "parse owma");
8230         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
8231         if (!owma)
8232           break;
8233         owma_data = owma->data;
8234         owma_len = QT_UINT32 (owma_data);
8235         if (owma_len <= 54) {
8236           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
8237           break;
8238         }
8239         wfex = (WAVEFORMATEX *) (owma_data + 36);
8240         buf = gst_buffer_new_and_alloc (owma_len - 54);
8241         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
8242         if (wfex->wFormatTag == 0x0161) {
8243           codec_name = "Windows Media Audio";
8244           version = 2;
8245         } else if (wfex->wFormatTag == 0x0162) {
8246           codec_name = "Windows Media Audio 9 Pro";
8247           version = 3;
8248         } else if (wfex->wFormatTag == 0x0163) {
8249           codec_name = "Windows Media Audio 9 Lossless";
8250           /* is that correct? gstffmpegcodecmap.c is missing it, but
8251            * fluendo codec seems to support it */
8252           version = 4;
8253         }
8254
8255         gst_caps_set_simple (stream->caps,
8256             "codec_data", GST_TYPE_BUFFER, buf,
8257             "wmaversion", G_TYPE_INT, version,
8258             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
8259             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
8260             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
8261             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
8262             NULL);
8263         gst_buffer_unref (buf);
8264
8265         if (codec_name) {
8266           g_free (codec);
8267           codec = g_strdup (codec_name);
8268         }
8269         break;
8270       }
8271       default:
8272         break;
8273     }
8274
8275     if (codec) {
8276       GstStructure *s;
8277       gint bitrate = 0;
8278
8279       list = gst_tag_list_new_empty ();
8280       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
8281           GST_TAG_AUDIO_CODEC, codec, NULL);
8282       g_free (codec);
8283       codec = NULL;
8284
8285       /* some bitrate info may have ended up in caps */
8286       s = gst_caps_get_structure (stream->caps, 0);
8287       gst_structure_get_int (s, "bitrate", &bitrate);
8288       if (bitrate > 0)
8289         gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
8290             bitrate, NULL);
8291     }
8292
8293     mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
8294     wave = NULL;
8295     esds = NULL;
8296     if (mp4a) {
8297       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
8298       if (wave)
8299         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
8300       if (!esds)
8301         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
8302     }
8303
8304
8305     /* If the fourcc's bottom 16 bits gives 'sm', then the top
8306        16 bits is a byte-swapped wave-style codec identifier,
8307        and we can find a WAVE header internally to a 'wave' atom here.
8308        This can more clearly be thought of as 'ms' as the top 16 bits, and a
8309        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
8310        is big-endian).
8311      */
8312     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
8313       if (len < offset + 20) {
8314         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
8315       } else {
8316         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
8317         const guint8 *data = stsd_data + offset + 16;
8318         GNode *wavenode;
8319         GNode *waveheadernode;
8320
8321         wavenode = g_node_new ((guint8 *) data);
8322         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
8323           const guint8 *waveheader;
8324           guint32 headerlen;
8325
8326           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
8327           if (waveheadernode) {
8328             waveheader = (const guint8 *) waveheadernode->data;
8329             headerlen = QT_UINT32 (waveheader);
8330
8331             if (headerlen > 8) {
8332               gst_riff_strf_auds *header = NULL;
8333               GstBuffer *headerbuf;
8334               GstBuffer *extra;
8335
8336               waveheader += 8;
8337               headerlen -= 8;
8338
8339               headerbuf = gst_buffer_new_and_alloc (headerlen);
8340               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
8341
8342               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
8343                       headerbuf, &header, &extra)) {
8344                 gst_caps_unref (stream->caps);
8345                 /* FIXME: Need to do something with the channel reorder map */
8346                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
8347                     header, extra, NULL, NULL, NULL);
8348
8349                 if (extra)
8350                   gst_buffer_unref (extra);
8351                 g_free (header);
8352               }
8353             }
8354           } else
8355             GST_DEBUG ("Didn't find waveheadernode for this codec");
8356         }
8357         g_node_destroy (wavenode);
8358       }
8359     } else if (esds) {
8360       gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
8361     } else {
8362       switch (fourcc) {
8363 #if 0
8364           /* FIXME: what is in the chunk? */
8365         case FOURCC_QDMC:
8366         {
8367           gint len = QT_UINT32 (stsd_data);
8368
8369           /* seems to be always = 116 = 0x74 */
8370           break;
8371         }
8372 #endif
8373         case FOURCC_QDM2:
8374         {
8375           gint len = QT_UINT32 (stsd_data);
8376
8377           if (len > 0x4C) {
8378             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
8379
8380             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
8381             gst_caps_set_simple (stream->caps,
8382                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
8383             gst_buffer_unref (buf);
8384           }
8385           gst_caps_set_simple (stream->caps,
8386               "samplesize", G_TYPE_INT, samplesize, NULL);
8387           break;
8388         }
8389         case FOURCC_alac:
8390         {
8391           GNode *alac, *wave = NULL;
8392
8393           /* apparently, m4a has this atom appended directly in the stsd entry,
8394            * while mov has it in a wave atom */
8395           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
8396           if (alac) {
8397             /* alac now refers to stsd entry atom */
8398             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
8399             if (wave)
8400               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
8401             else
8402               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
8403           }
8404           if (alac) {
8405             const guint8 *alac_data = alac->data;
8406             gint len = QT_UINT32 (alac->data);
8407             GstBuffer *buf;
8408
8409             if (len < 36) {
8410               GST_DEBUG_OBJECT (qtdemux,
8411                   "discarding alac atom with unexpected len %d", len);
8412             } else {
8413               /* codec-data contains alac atom size and prefix,
8414                * ffmpeg likes it that way, not quite gst-ish though ...*/
8415               buf = gst_buffer_new_and_alloc (len);
8416               gst_buffer_fill (buf, 0, alac->data, len);
8417               gst_caps_set_simple (stream->caps,
8418                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
8419               gst_buffer_unref (buf);
8420
8421               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
8422               stream->n_channels = QT_UINT8 (alac_data + 21);
8423               stream->rate = QT_UINT32 (alac_data + 32);
8424             }
8425           }
8426           gst_caps_set_simple (stream->caps,
8427               "samplesize", G_TYPE_INT, samplesize, NULL);
8428           break;
8429         }
8430         case FOURCC_sawb:
8431           /* Fallthrough! */
8432           amrwb = TRUE;
8433         case FOURCC_samr:
8434         {
8435           gint len = QT_UINT32 (stsd_data);
8436
8437           if (len > 0x34) {
8438             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
8439             guint bitrate;
8440
8441             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
8442
8443             /* If we have enough data, let's try to get the 'damr' atom. See
8444              * the 3GPP container spec (26.244) for more details. */
8445             if ((len - 0x34) > 8 &&
8446                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
8447               if (!list)
8448                 list = gst_tag_list_new_empty ();
8449               gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
8450                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
8451             }
8452
8453             gst_caps_set_simple (stream->caps,
8454                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
8455             gst_buffer_unref (buf);
8456           }
8457           break;
8458         }
8459         default:
8460           GST_INFO_OBJECT (qtdemux,
8461               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
8462           break;
8463       }
8464     }
8465     GST_INFO_OBJECT (qtdemux,
8466         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
8467         GST_FOURCC_ARGS (fourcc), stream->caps);
8468
8469   } else if (stream->subtype == FOURCC_strm) {
8470     if (fourcc == FOURCC_rtsp) {
8471       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
8472     } else {
8473       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
8474           GST_FOURCC_ARGS (fourcc));
8475       goto unknown_stream;
8476     }
8477     stream->sampled = TRUE;
8478   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8479       || stream->subtype == FOURCC_sbtl) {
8480
8481     stream->sampled = TRUE;
8482     stream->sparse = TRUE;
8483
8484     offset = 16;
8485
8486     stream->caps =
8487         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
8488     if (codec) {
8489       list = gst_tag_list_new_empty ();
8490       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
8491           GST_TAG_SUBTITLE_CODEC, codec, NULL);
8492       g_free (codec);
8493       codec = NULL;
8494     }
8495
8496     /* hunt for sort-of codec data */
8497     switch (fourcc) {
8498       case FOURCC_mp4s:
8499       {
8500         GNode *mp4s = NULL;
8501         GNode *esds = NULL;
8502
8503         /* look for palette in a stsd->mp4s->esds sub-atom */
8504         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
8505         if (mp4s)
8506           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
8507         if (esds == NULL) {
8508           /* Invalid STSD */
8509           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
8510           break;
8511         }
8512
8513         gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
8514         break;
8515       }
8516       default:
8517         GST_INFO_OBJECT (qtdemux,
8518             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
8519         break;
8520     }
8521     GST_INFO_OBJECT (qtdemux,
8522         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
8523         GST_FOURCC_ARGS (fourcc), stream->caps);
8524   } else {
8525     /* everything in 1 sample */
8526     stream->sampled = TRUE;
8527
8528     stream->caps =
8529         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
8530
8531     if (stream->caps == NULL)
8532       goto unknown_stream;
8533
8534     if (codec) {
8535       list = gst_tag_list_new_empty ();
8536       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
8537           GST_TAG_SUBTITLE_CODEC, codec, NULL);
8538       g_free (codec);
8539       codec = NULL;
8540     }
8541   }
8542
8543   /* promote to sampled format */
8544   if (stream->fourcc == FOURCC_samr) {
8545     /* force mono 8000 Hz for AMR */
8546     stream->sampled = TRUE;
8547     stream->n_channels = 1;
8548     stream->rate = 8000;
8549   } else if (stream->fourcc == FOURCC_sawb) {
8550     /* force mono 16000 Hz for AMR-WB */
8551     stream->sampled = TRUE;
8552     stream->n_channels = 1;
8553     stream->rate = 16000;
8554   } else if (stream->fourcc == FOURCC_mp4a) {
8555     stream->sampled = TRUE;
8556   }
8557
8558   /* collect sample information */
8559   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
8560     goto samples_failed;
8561
8562   if (qtdemux->fragmented) {
8563     guint32 dummy;
8564     guint64 offset;
8565
8566     /* need all moov samples as basis; probably not many if any at all */
8567     /* prevent moof parsing taking of at this time */
8568     offset = qtdemux->moof_offset;
8569     qtdemux->moof_offset = 0;
8570     if (stream->n_samples &&
8571         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
8572       qtdemux->moof_offset = offset;
8573       goto samples_failed;
8574     }
8575     qtdemux->moof_offset = 0;
8576     /* movie duration more reliable in this case (e.g. mehd) */
8577     if (qtdemux->segment.duration &&
8578         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
8579       stream->duration = gst_util_uint64_scale (qtdemux->segment.duration,
8580           stream->timescale, GST_SECOND);
8581     /* need defaults for fragments */
8582     qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
8583   }
8584
8585   /* configure segments */
8586   if (!qtdemux_parse_segments (qtdemux, stream, trak))
8587     goto segments_failed;
8588
8589   /* add some language tag, if useful */
8590   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
8591       strcmp (stream->lang_id, "und")) {
8592     const gchar *lang_code;
8593
8594     if (!list)
8595       list = gst_tag_list_new_empty ();
8596
8597     /* convert ISO 639-2 code to ISO 639-1 */
8598     lang_code = gst_tag_get_language_code (stream->lang_id);
8599     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
8600         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
8601   }
8602
8603   /* now we are ready to add the stream */
8604   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
8605     goto too_many_streams;
8606
8607   if (!qtdemux->got_moov) {
8608     stream->pending_tags = list;
8609     qtdemux->streams[qtdemux->n_streams] = stream;
8610     qtdemux->n_streams++;
8611     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
8612   }
8613
8614   return TRUE;
8615
8616 /* ERRORS */
8617 skip_track:
8618   {
8619     GST_INFO_OBJECT (qtdemux, "skip disabled track");
8620     if (new_stream)
8621       g_free (stream);
8622     return TRUE;
8623   }
8624 corrupt_file:
8625   {
8626     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8627         (_("This file is corrupt and cannot be played.")), (NULL));
8628     if (new_stream)
8629       g_free (stream);
8630     return FALSE;
8631   }
8632 error_encrypted:
8633   {
8634     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
8635     if (new_stream)
8636       g_free (stream);
8637     return FALSE;
8638   }
8639 samples_failed:
8640 segments_failed:
8641   {
8642     /* we posted an error already */
8643     /* free stbl sub-atoms */
8644     gst_qtdemux_stbl_free (stream);
8645     if (new_stream)
8646       g_free (stream);
8647     return FALSE;
8648   }
8649 existing_stream:
8650   {
8651     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
8652         track_id);
8653     if (new_stream)
8654       g_free (stream);
8655     return TRUE;
8656   }
8657 unknown_stream:
8658   {
8659     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
8660         GST_FOURCC_ARGS (stream->subtype));
8661     if (new_stream)
8662       g_free (stream);
8663     return TRUE;
8664   }
8665 too_many_streams:
8666   {
8667     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
8668         (_("This file contains too many streams. Only playing first %d"),
8669             GST_QTDEMUX_MAX_STREAMS), (NULL));
8670     return TRUE;
8671   }
8672 }
8673
8674 /* If we can estimate the overall bitrate, and don't have information about the
8675  * stream bitrate for exactly one stream, this guesses the stream bitrate as
8676  * the overall bitrate minus the sum of the bitrates of all other streams. This
8677  * should be useful for the common case where we have one audio and one video
8678  * stream and can estimate the bitrate of one, but not the other. */
8679 static void
8680 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
8681 {
8682   QtDemuxStream *stream = NULL;
8683   gint64 size, duration, sys_bitrate, sum_bitrate = 0;
8684   gint i;
8685   guint bitrate;
8686
8687   if (qtdemux->fragmented)
8688     return;
8689
8690   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
8691
8692   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
8693       || size <= 0) {
8694     GST_DEBUG_OBJECT (qtdemux,
8695         "Size in bytes of the stream not known - bailing");
8696     return;
8697   }
8698
8699   /* Subtract the header size */
8700   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
8701       size, qtdemux->header_size);
8702
8703   if (size < qtdemux->header_size)
8704     return;
8705
8706   size = size - qtdemux->header_size;
8707
8708   if (!gst_qtdemux_get_duration (qtdemux, &duration) ||
8709       duration == GST_CLOCK_TIME_NONE) {
8710     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
8711     return;
8712   }
8713
8714   for (i = 0; i < qtdemux->n_streams; i++) {
8715     switch (qtdemux->streams[i]->subtype) {
8716       case FOURCC_soun:
8717       case FOURCC_vide:
8718         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
8719             qtdemux->streams[i]->caps);
8720         /* retrieve bitrate, prefer avg then max */
8721         bitrate = 0;
8722         if (qtdemux->streams[i]->pending_tags) {
8723           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
8724               GST_TAG_MAXIMUM_BITRATE, &bitrate);
8725           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
8726           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
8727               GST_TAG_NOMINAL_BITRATE, &bitrate);
8728           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
8729           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
8730               GST_TAG_BITRATE, &bitrate);
8731           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
8732         }
8733         if (bitrate)
8734           sum_bitrate += bitrate;
8735         else {
8736           if (stream) {
8737             GST_DEBUG_OBJECT (qtdemux,
8738                 ">1 stream with unknown bitrate - bailing");
8739             return;
8740           } else
8741             stream = qtdemux->streams[i];
8742         }
8743
8744       default:
8745         /* For other subtypes, we assume no significant impact on bitrate */
8746         break;
8747     }
8748   }
8749
8750   if (!stream) {
8751     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
8752     return;
8753   }
8754
8755   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
8756
8757   if (sys_bitrate < sum_bitrate) {
8758     /* This can happen, since sum_bitrate might be derived from maximum
8759      * bitrates and not average bitrates */
8760     GST_DEBUG_OBJECT (qtdemux,
8761         "System bitrate less than sum bitrate - bailing");
8762     return;
8763   }
8764
8765   bitrate = sys_bitrate - sum_bitrate;
8766   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
8767       ", Stream bitrate = %u", sys_bitrate, bitrate);
8768
8769   if (!stream->pending_tags)
8770     stream->pending_tags = gst_tag_list_new_empty ();
8771
8772   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
8773       GST_TAG_BITRATE, bitrate, NULL);
8774 }
8775
8776 static GstFlowReturn
8777 qtdemux_prepare_streams (GstQTDemux * qtdemux)
8778 {
8779   gint i;
8780   GstFlowReturn ret = GST_FLOW_OK;
8781
8782   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
8783
8784   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
8785     QtDemuxStream *stream = qtdemux->streams[i];
8786     guint32 sample_num = 0;
8787     guint samples = 20;
8788     GArray *durations;
8789
8790     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
8791         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
8792
8793     if (qtdemux->fragmented) {
8794       /* need all moov samples first */
8795       GST_OBJECT_LOCK (qtdemux);
8796       while (stream->n_samples == 0)
8797         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
8798           break;
8799       GST_OBJECT_UNLOCK (qtdemux);
8800     } else {
8801       /* discard any stray moof */
8802       qtdemux->moof_offset = 0;
8803     }
8804
8805     /* prepare braking */
8806     if (ret != GST_FLOW_ERROR)
8807       ret = GST_FLOW_OK;
8808
8809     /* in pull mode, we should have parsed some sample info by now;
8810      * and quite some code will not handle no samples.
8811      * in push mode, we'll just have to deal with it */
8812     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
8813       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
8814       gst_qtdemux_remove_stream (qtdemux, i);
8815       i--;
8816       continue;
8817     }
8818
8819     /* parse number of initial sample to set frame rate cap */
8820     while (sample_num < stream->n_samples && sample_num < samples) {
8821       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
8822         break;
8823       ++sample_num;
8824     }
8825     /* collect and sort durations */
8826     samples = MIN (stream->stbl_index + 1, samples);
8827     GST_DEBUG_OBJECT (qtdemux, "%d samples for framerate", samples);
8828     if (samples) {
8829       durations = g_array_sized_new (FALSE, FALSE, sizeof (guint32), samples);
8830       sample_num = 0;
8831       while (sample_num < samples) {
8832         g_array_append_val (durations, stream->samples[sample_num].duration);
8833         sample_num++;
8834       }
8835       g_array_sort (durations, less_than);
8836       stream->min_duration = g_array_index (durations, guint32, samples / 2);
8837       g_array_free (durations, TRUE);
8838     }
8839   }
8840
8841   return ret;
8842 }
8843
8844 static GstFlowReturn
8845 qtdemux_expose_streams (GstQTDemux * qtdemux)
8846 {
8847   gint i;
8848   GstFlowReturn ret = GST_FLOW_OK;
8849   GSList *oldpads = NULL;
8850   GSList *iter;
8851
8852   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
8853
8854   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
8855     QtDemuxStream *stream = qtdemux->streams[i];
8856     GstPad *oldpad = stream->pad;
8857     GstTagList *list;
8858
8859     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
8860         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
8861
8862     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
8863         stream->track_id == qtdemux->chapters_track_id) {
8864       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
8865          so that it doesn't look like a subtitle track */
8866       gst_qtdemux_remove_stream (qtdemux, i);
8867       i--;
8868       continue;
8869     }
8870
8871     /* now we have all info and can expose */
8872     list = stream->pending_tags;
8873     stream->pending_tags = NULL;
8874     if (oldpad)
8875       oldpads = g_slist_prepend (oldpads, oldpad);
8876     gst_qtdemux_add_stream (qtdemux, stream, list);
8877   }
8878
8879   gst_qtdemux_guess_bitrate (qtdemux);
8880
8881   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
8882
8883   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
8884     GstPad *oldpad = iter->data;
8885
8886     gst_pad_push_event (oldpad, gst_event_new_eos ());
8887     gst_pad_set_active (oldpad, FALSE);
8888     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
8889     gst_object_unref (oldpad);
8890   }
8891
8892   /* check if we should post a redirect in case there is a single trak
8893    * and it is a redirecting trak */
8894   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
8895     GstMessage *m;
8896
8897     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
8898         "an external content");
8899     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
8900         gst_structure_new ("redirect",
8901             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
8902             NULL));
8903     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
8904     qtdemux->posted_redirect = TRUE;
8905   }
8906
8907   for (i = 0; i < qtdemux->n_streams; i++) {
8908     QtDemuxStream *stream = qtdemux->streams[i];
8909
8910     qtdemux_do_allocation (qtdemux, stream);
8911   }
8912
8913   qtdemux->exposed = TRUE;
8914   return ret;
8915 }
8916
8917 /* check if major or compatible brand is 3GP */
8918 static inline gboolean
8919 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
8920 {
8921   if (major) {
8922     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
8923         GST_MAKE_FOURCC ('3', 'g', 0, 0));
8924   } else if (qtdemux->comp_brands != NULL) {
8925     GstMapInfo map;
8926     guint8 *data;
8927     gsize size;
8928     gboolean res = FALSE;
8929
8930     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
8931     data = map.data;
8932     size = map.size;
8933     while (size >= 4) {
8934       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
8935           GST_MAKE_FOURCC ('3', 'g', 0, 0));
8936       data += 4;
8937       size -= 4;
8938     }
8939     gst_buffer_unmap (qtdemux->comp_brands, &map);
8940     return res;
8941   } else {
8942     return FALSE;
8943   }
8944 }
8945
8946 /* check if tag is a spec'ed 3GP tag keyword storing a string */
8947 static inline gboolean
8948 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
8949 {
8950   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
8951       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
8952       || fourcc == FOURCC_albm;
8953 }
8954
8955 static void
8956 qtdemux_tag_add_location (GstQTDemux * qtdemux, const char *tag,
8957     const char *dummy, GNode * node)
8958 {
8959   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
8960   int offset;
8961   char *name;
8962   gchar *data;
8963   gdouble longitude, latitude, altitude;
8964   gint len;
8965
8966   len = QT_UINT32 (node->data);
8967   if (len <= 14)
8968     goto short_read;
8969
8970   data = node->data;
8971   offset = 14;
8972
8973   /* TODO: language code skipped */
8974
8975   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
8976
8977   if (!name) {
8978     /* do not alarm in trivial case, but bail out otherwise */
8979     if (*(data + offset) != 0) {
8980       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
8981           "giving up", tag);
8982     }
8983   } else {
8984     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
8985         GST_TAG_GEO_LOCATION_NAME, name, NULL);
8986     offset += strlen (name);
8987     g_free (name);
8988   }
8989
8990   if (len < offset + 2 + 4 + 4 + 4)
8991     goto short_read;
8992
8993   /* +1 +1 = skip null-terminator and location role byte */
8994   offset += 1 + 1;
8995   /* table in spec says unsigned, semantics say negative has meaning ... */
8996   longitude = QT_SFP32 (data + offset);
8997
8998   offset += 4;
8999   latitude = QT_SFP32 (data + offset);
9000
9001   offset += 4;
9002   altitude = QT_SFP32 (data + offset);
9003
9004   /* one invalid means all are invalid */
9005   if (longitude >= -180.0 && longitude <= 180.0 &&
9006       latitude >= -90.0 && latitude <= 90.0) {
9007     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
9008         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
9009         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
9010         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
9011   }
9012
9013   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
9014
9015   return;
9016
9017   /* ERRORS */
9018 short_read:
9019   {
9020     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
9021     return;
9022   }
9023 }
9024
9025
9026 static void
9027 qtdemux_tag_add_year (GstQTDemux * qtdemux, const char *tag, const char *dummy,
9028     GNode * node)
9029 {
9030   guint16 y;
9031   GDate *date;
9032   gint len;
9033
9034   len = QT_UINT32 (node->data);
9035   if (len < 14)
9036     return;
9037
9038   y = QT_UINT16 ((guint8 *) node->data + 12);
9039   if (y == 0) {
9040     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
9041     return;
9042   }
9043   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
9044
9045   date = g_date_new_dmy (1, 1, y);
9046   gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, date, NULL);
9047   g_date_free (date);
9048 }
9049
9050 static void
9051 qtdemux_tag_add_classification (GstQTDemux * qtdemux, const char *tag,
9052     const char *dummy, GNode * node)
9053 {
9054   int offset;
9055   char *tag_str = NULL;
9056   guint8 *entity;
9057   guint16 table;
9058   gint len;
9059
9060   len = QT_UINT32 (node->data);
9061   if (len <= 20)
9062     goto short_read;
9063
9064   offset = 12;
9065   entity = (guint8 *) node->data + offset;
9066   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
9067     GST_DEBUG_OBJECT (qtdemux,
9068         "classification info: %c%c%c%c invalid classification entity",
9069         entity[0], entity[1], entity[2], entity[3]);
9070     return;
9071   }
9072
9073   offset += 4;
9074   table = QT_UINT16 ((guint8 *) node->data + offset);
9075
9076   /* Language code skipped */
9077
9078   offset += 4;
9079
9080   /* Tag format: "XXXX://Y[YYYY]/classification info string"
9081    * XXXX: classification entity, fixed length 4 chars.
9082    * Y[YYYY]: classification table, max 5 chars.
9083    */
9084   tag_str = g_strdup_printf ("----://%u/%s",
9085       table, (char *) node->data + offset);
9086
9087   /* memcpy To be sure we're preserving byte order */
9088   memcpy (tag_str, entity, 4);
9089   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
9090
9091   gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_APPEND, tag,
9092       tag_str, NULL);
9093
9094   g_free (tag_str);
9095
9096   return;
9097
9098   /* ERRORS */
9099 short_read:
9100   {
9101     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
9102     return;
9103   }
9104 }
9105
9106 static gboolean
9107 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag,
9108     const char *dummy, GNode * node)
9109 {
9110   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
9111   GNode *data;
9112   char *s;
9113   int len;
9114   guint32 type;
9115   int offset;
9116   gboolean ret = TRUE;
9117   const gchar *charset = NULL;
9118
9119   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
9120   if (data) {
9121     len = QT_UINT32 (data->data);
9122     type = QT_UINT32 ((guint8 *) data->data + 8);
9123     if (type == 0x00000001 && len > 16) {
9124       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
9125           env_vars);
9126       if (s) {
9127         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
9128         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s,
9129             NULL);
9130         g_free (s);
9131       } else {
9132         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
9133       }
9134     }
9135   } else {
9136     len = QT_UINT32 (node->data);
9137     type = QT_UINT32 ((guint8 *) node->data + 4);
9138     if ((type >> 24) == 0xa9) {
9139       gint str_len;
9140       gint lang_code;
9141
9142       /* Type starts with the (C) symbol, so the next data is a list
9143        * of (string size(16), language code(16), string) */
9144
9145       str_len = QT_UINT16 ((guint8 *) node->data + 8);
9146       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
9147
9148       /* the string + fourcc + size + 2 16bit fields,
9149        * means that there are more tags in this atom */
9150       if (len > str_len + 8 + 4) {
9151         /* TODO how to represent the same tag in different languages? */
9152         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
9153             "text alternatives, reading only first one");
9154       }
9155
9156       offset = 12;
9157       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
9158       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
9159
9160       if (lang_code < 0x800) {  /* MAC encoded string */
9161         charset = "mac";
9162       }
9163     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
9164             QT_FOURCC ((guint8 *) node->data + 4))) {
9165       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
9166
9167       /* we go for 3GP style encoding if major brands claims so,
9168        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
9169       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
9170           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
9171               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
9172         offset = 14;
9173         /* 16-bit Language code is ignored here as well */
9174         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
9175       } else {
9176         goto normal;
9177       }
9178     } else {
9179     normal:
9180       offset = 8;
9181       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
9182       ret = FALSE;              /* may have to fallback */
9183     }
9184     if (charset) {
9185       GError *err = NULL;
9186
9187       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
9188           charset, NULL, NULL, &err);
9189       if (err) {
9190         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
9191             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
9192             err->message);
9193         g_error_free (err);
9194       }
9195     } else {
9196       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
9197           len - offset, env_vars);
9198     }
9199     if (s) {
9200       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
9201       gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s, NULL);
9202       g_free (s);
9203       ret = TRUE;
9204     } else {
9205       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
9206     }
9207   }
9208   return ret;
9209 }
9210
9211 static void
9212 qtdemux_tag_add_str (GstQTDemux * qtdemux, const char *tag,
9213     const char *dummy, GNode * node)
9214 {
9215   qtdemux_tag_add_str_full (qtdemux, tag, dummy, node);
9216 }
9217
9218 static void
9219 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, const char *tag,
9220     const char *dummy, GNode * node)
9221 {
9222   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
9223   guint8 *data;
9224   char *s, *t, *k = NULL;
9225   int len;
9226   int offset;
9227   int count;
9228
9229   /* first try normal string tag if major brand not 3GP */
9230   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
9231     if (!qtdemux_tag_add_str_full (qtdemux, tag, dummy, node)) {
9232       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
9233        * let's try it 3gpp way after minor safety check */
9234       data = node->data;
9235       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
9236         return;
9237     } else
9238       return;
9239   }
9240
9241   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
9242
9243   data = node->data;
9244
9245   len = QT_UINT32 (data);
9246   if (len < 15)
9247     goto short_read;
9248
9249   count = QT_UINT8 (data + 14);
9250   offset = 15;
9251   for (; count; count--) {
9252     gint slen;
9253
9254     if (offset + 1 > len)
9255       goto short_read;
9256     slen = QT_UINT8 (data + offset);
9257     offset += 1;
9258     if (offset + slen > len)
9259       goto short_read;
9260     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
9261         slen, env_vars);
9262     if (s) {
9263       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
9264       if (k) {
9265         t = g_strjoin (",", k, s, NULL);
9266         g_free (s);
9267         g_free (k);
9268         k = t;
9269       } else {
9270         k = s;
9271       }
9272     } else {
9273       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
9274     }
9275     offset += slen;
9276   }
9277
9278 done:
9279   if (k) {
9280     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
9281     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, k, NULL);
9282   }
9283   g_free (k);
9284
9285   return;
9286
9287   /* ERRORS */
9288 short_read:
9289   {
9290     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
9291     goto done;
9292   }
9293 }
9294
9295 static void
9296 qtdemux_tag_add_num (GstQTDemux * qtdemux, const char *tag1,
9297     const char *tag2, GNode * node)
9298 {
9299   GNode *data;
9300   int len;
9301   int type;
9302   int n1, n2;
9303
9304   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
9305   if (data) {
9306     len = QT_UINT32 (data->data);
9307     type = QT_UINT32 ((guint8 *) data->data + 8);
9308     if (type == 0x00000000 && len >= 22) {
9309       n1 = QT_UINT16 ((guint8 *) data->data + 18);
9310       n2 = QT_UINT16 ((guint8 *) data->data + 20);
9311       if (n1 > 0) {
9312         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
9313         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
9314             tag1, n1, NULL);
9315       }
9316       if (n2 > 0) {
9317         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
9318         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
9319             tag2, n2, NULL);
9320       }
9321     }
9322   }
9323 }
9324
9325 static void
9326 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
9327     GNode * node)
9328 {
9329   GNode *data;
9330   int len;
9331   int type;
9332   int n1;
9333
9334   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
9335   if (data) {
9336     len = QT_UINT32 (data->data);
9337     type = QT_UINT32 ((guint8 *) data->data + 8);
9338     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
9339     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
9340     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
9341       n1 = QT_UINT16 ((guint8 *) data->data + 16);
9342       if (n1) {
9343         /* do not add bpm=0 */
9344         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
9345         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
9346             tag1, (gdouble) n1, NULL);
9347       }
9348     }
9349   }
9350 }
9351
9352 static void
9353 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, const char *tag1,
9354     const char *dummy, GNode * node)
9355 {
9356   GNode *data;
9357   int len;
9358   int type;
9359   guint32 num;
9360
9361   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
9362   if (data) {
9363     len = QT_UINT32 (data->data);
9364     type = QT_UINT32 ((guint8 *) data->data + 8);
9365     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
9366     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
9367     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
9368       num = QT_UINT32 ((guint8 *) data->data + 16);
9369       if (num) {
9370         /* do not add num=0 */
9371         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
9372         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
9373             tag1, num, NULL);
9374       }
9375     }
9376   }
9377 }
9378
9379 static void
9380 qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
9381     GNode * node)
9382 {
9383   GNode *data;
9384   int len;
9385   int type;
9386   GstSample *sample;
9387
9388   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
9389   if (data) {
9390     len = QT_UINT32 (data->data);
9391     type = QT_UINT32 ((guint8 *) data->data + 8);
9392     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
9393     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
9394       if ((sample =
9395               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
9396                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
9397         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
9398         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
9399             tag1, sample, NULL);
9400         gst_sample_unref (sample);
9401       }
9402     }
9403   }
9404 }
9405
9406 static void
9407 qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy,
9408     GNode * node)
9409 {
9410   GNode *data;
9411   char *s;
9412   int len;
9413   int type;
9414
9415   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
9416   if (data) {
9417     len = QT_UINT32 (data->data);
9418     type = QT_UINT32 ((guint8 *) data->data + 8);
9419     if (type == 0x00000001 && len > 16) {
9420       guint y, m = 1, d = 1;
9421       gint ret;
9422
9423       s = g_strndup ((char *) data->data + 16, len - 16);
9424       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
9425       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
9426       if (ret >= 1 && y > 1500 && y < 3000) {
9427         GDate *date;
9428
9429         date = g_date_new_dmy (d, m, y);
9430         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag,
9431             date, NULL);
9432         g_date_free (date);
9433       } else {
9434         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
9435       }
9436       g_free (s);
9437     }
9438   }
9439 }
9440
9441 static void
9442 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy,
9443     GNode * node)
9444 {
9445   GNode *data;
9446
9447   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
9448
9449   /* re-route to normal string tag if major brand says so
9450    * or no data atom and compatible brand suggests so */
9451   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
9452       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
9453     qtdemux_tag_add_str (qtdemux, tag, dummy, node);
9454     return;
9455   }
9456
9457   if (data) {
9458     guint len, type, n;
9459
9460     len = QT_UINT32 (data->data);
9461     type = QT_UINT32 ((guint8 *) data->data + 8);
9462     if (type == 0x00000000 && len >= 18) {
9463       n = QT_UINT16 ((guint8 *) data->data + 16);
9464       if (n > 0) {
9465         const gchar *genre;
9466
9467         genre = gst_tag_id3_genre_get (n - 1);
9468         if (genre != NULL) {
9469           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
9470           gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
9471               tag, genre, NULL);
9472         }
9473       }
9474     }
9475   }
9476 }
9477
9478 static void
9479 qtdemux_add_double_tag_from_str (GstQTDemux * demux, const gchar * tag,
9480     guint8 * data, guint32 datasize)
9481 {
9482   gdouble value;
9483   gchar *datacopy;
9484
9485   /* make a copy to have \0 at the end */
9486   datacopy = g_strndup ((gchar *) data, datasize);
9487
9488   /* convert the str to double */
9489   if (sscanf (datacopy, "%lf", &value) == 1) {
9490     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
9491     gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_REPLACE, tag, value, NULL);
9492   } else {
9493     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
9494         datacopy);
9495   }
9496   g_free (datacopy);
9497 }
9498
9499
9500 static void
9501 qtdemux_tag_add_revdns (GstQTDemux * demux, const char *tag,
9502     const char *tag_bis, GNode * node)
9503 {
9504   GNode *mean;
9505   GNode *name;
9506   GNode *data;
9507   guint32 meansize;
9508   guint32 namesize;
9509   guint32 datatype;
9510   guint32 datasize;
9511   const gchar *meanstr;
9512   const gchar *namestr;
9513
9514   /* checking the whole ---- atom size for consistency */
9515   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
9516     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
9517     return;
9518   }
9519
9520   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
9521   if (!mean) {
9522     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
9523     return;
9524   }
9525
9526   meansize = QT_UINT32 (mean->data);
9527   if (meansize <= 12) {
9528     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
9529     return;
9530   }
9531   meanstr = ((gchar *) mean->data) + 12;
9532   meansize -= 12;
9533
9534   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
9535   if (!name) {
9536     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
9537     return;
9538   }
9539
9540   namesize = QT_UINT32 (name->data);
9541   if (namesize <= 12) {
9542     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
9543     return;
9544   }
9545   namestr = ((gchar *) name->data) + 12;
9546   namesize -= 12;
9547
9548   /*
9549    * Data atom is:
9550    * uint32 - size
9551    * uint32 - name
9552    * uint8  - version
9553    * uint24 - data type
9554    * uint32 - all 0
9555    * rest   - the data
9556    */
9557   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
9558   if (!data) {
9559     GST_WARNING_OBJECT (demux, "No data atom in this tag");
9560     return;
9561   }
9562   datasize = QT_UINT32 (data->data);
9563   if (datasize <= 16) {
9564     GST_WARNING_OBJECT (demux, "Data atom too small");
9565     return;
9566   }
9567   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
9568
9569   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
9570       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
9571     static const struct
9572     {
9573       const gchar name[28];
9574       const gchar tag[28];
9575     } tags[] = {
9576       {
9577       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
9578       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
9579       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
9580       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
9581       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
9582       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
9583       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
9584       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
9585     };
9586     int i;
9587
9588     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
9589       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
9590         switch (gst_tag_get_type (tags[i].tag)) {
9591           case G_TYPE_DOUBLE:
9592             qtdemux_add_double_tag_from_str (demux, tags[i].tag,
9593                 ((guint8 *) data->data) + 16, datasize - 16);
9594             break;
9595           case G_TYPE_STRING:
9596             qtdemux_tag_add_str (demux, tags[i].tag, NULL, node);
9597             break;
9598           default:
9599             /* not reached */
9600             break;
9601         }
9602         break;
9603       }
9604     }
9605     if (i == G_N_ELEMENTS (tags))
9606       goto unknown_tag;
9607   } else {
9608     goto unknown_tag;
9609   }
9610
9611   return;
9612
9613 /* errors */
9614 unknown_tag:
9615 #ifndef GST_DISABLE_GST_DEBUG
9616   {
9617     gchar *namestr_dbg;
9618     gchar *meanstr_dbg;
9619
9620     meanstr_dbg = g_strndup (meanstr, meansize);
9621     namestr_dbg = g_strndup (namestr, namesize);
9622
9623     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
9624         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
9625
9626     g_free (namestr_dbg);
9627     g_free (meanstr_dbg);
9628   }
9629 #endif
9630   return;
9631 }
9632
9633 static void
9634 qtdemux_tag_add_id32 (GstQTDemux * demux, const char *tag,
9635     const char *tag_bis, GNode * node)
9636 {
9637   guint8 *data;
9638   GstBuffer *buf;
9639   guint len;
9640   GstTagList *taglist = NULL;
9641
9642   GST_LOG_OBJECT (demux, "parsing ID32");
9643
9644   data = node->data;
9645   len = GST_READ_UINT32_BE (data);
9646
9647   /* need at least full box and language tag */
9648   if (len < 12 + 2)
9649     return;
9650
9651   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
9652   gst_buffer_fill (buf, 0, data + 14, len - 14);
9653
9654   taglist = gst_tag_list_from_id3v2_tag (buf);
9655   if (taglist) {
9656     GST_LOG_OBJECT (demux, "parsing ok");
9657     gst_tag_list_insert (demux->tag_list, taglist, GST_TAG_MERGE_KEEP);
9658   } else {
9659     GST_LOG_OBJECT (demux, "parsing failed");
9660   }
9661
9662   if (taglist)
9663     gst_tag_list_unref (taglist);
9664
9665   gst_buffer_unref (buf);
9666 }
9667
9668 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux,
9669     const char *tag, const char *tag_bis, GNode * node);
9670
9671 /* unmapped tags
9672 FOURCC_pcst -> if media is a podcast -> bool
9673 FOURCC_cpil -> if media is part of a compilation -> bool
9674 FOURCC_pgap -> if media is part of a gapless context -> bool
9675 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
9676 */
9677
9678 static const struct
9679 {
9680   guint32 fourcc;
9681   const gchar *gst_tag;
9682   const gchar *gst_tag_bis;
9683   const GstQTDemuxAddTagFunc func;
9684 } add_funcs[] = {
9685   {
9686   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
9687   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
9688   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
9689   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
9690   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
9691   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
9692   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
9693   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
9694   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
9695   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
9696   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
9697   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
9698   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
9699   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
9700   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
9701   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
9702   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
9703   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
9704   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
9705   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
9706   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
9707   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
9708   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
9709         qtdemux_tag_add_num}, {
9710   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
9711         qtdemux_tag_add_num}, {
9712   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
9713   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
9714   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
9715   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
9716   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
9717   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
9718   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
9719   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
9720   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
9721   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
9722   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
9723   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
9724   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
9725   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
9726   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
9727   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
9728   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
9729   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
9730         qtdemux_tag_add_classification}, {
9731
9732     /* This is a special case, some tags are stored in this
9733      * 'reverse dns naming', according to:
9734      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
9735      * bug #614471
9736      */
9737   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
9738     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
9739   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
9740 };
9741
9742 static void
9743 qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
9744 {
9745   gint len;
9746   guint8 *data;
9747   GstBuffer *buf;
9748   gchar *media_type;
9749   const gchar *style;
9750   GstSample *sample;
9751   GstStructure *s;
9752   guint i;
9753   guint8 ndata[4];
9754
9755   data = node->data;
9756   len = QT_UINT32 (data);
9757   buf = gst_buffer_new_and_alloc (len);
9758   gst_buffer_fill (buf, 0, data, len);
9759
9760   /* heuristic to determine style of tag */
9761   if (QT_FOURCC (data + 4) == FOURCC_____ ||
9762       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
9763     style = "itunes";
9764   else if (demux->major_brand == FOURCC_qt__)
9765     style = "quicktime";
9766   /* fall back to assuming iso/3gp tag style */
9767   else
9768     style = "iso";
9769
9770   /* santize the name for the caps. */
9771   for (i = 0; i < 4; i++) {
9772     guint8 d = data[4 + i];
9773     if (g_ascii_isalnum (d))
9774       ndata[i] = g_ascii_tolower (d);
9775     else
9776       ndata[i] = '_';
9777   }
9778
9779   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
9780       ndata[0], ndata[1], ndata[2], ndata[3]);
9781   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
9782
9783   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
9784   sample = gst_sample_new (buf, NULL, NULL, s);
9785   gst_buffer_unref (buf);
9786   g_free (media_type);
9787
9788   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
9789       len, s);
9790
9791   gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_APPEND,
9792       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
9793
9794   gst_sample_unref (sample);
9795 }
9796
9797 static void
9798 qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
9799 {
9800   GNode *meta;
9801   GNode *ilst;
9802   GNode *xmp_;
9803   GNode *node;
9804   gint i;
9805
9806   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
9807   if (meta != NULL) {
9808     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
9809     if (ilst == NULL) {
9810       GST_LOG_OBJECT (qtdemux, "no ilst");
9811       return;
9812     }
9813   } else {
9814     ilst = udta;
9815     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
9816   }
9817
9818   GST_DEBUG_OBJECT (qtdemux, "new tag list");
9819   if (!qtdemux->tag_list) {
9820     qtdemux->tag_list = gst_tag_list_new_empty ();
9821     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
9822   } else {
9823     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
9824   }
9825
9826   i = 0;
9827   while (i < G_N_ELEMENTS (add_funcs)) {
9828     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
9829     if (node) {
9830       gint len;
9831
9832       len = QT_UINT32 (node->data);
9833       if (len < 12) {
9834         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
9835             GST_FOURCC_ARGS (add_funcs[i].fourcc));
9836       } else {
9837         add_funcs[i].func (qtdemux, add_funcs[i].gst_tag,
9838             add_funcs[i].gst_tag_bis, node);
9839       }
9840       g_node_destroy (node);
9841     } else {
9842       i++;
9843     }
9844   }
9845
9846   /* parsed nodes have been removed, pass along remainder as blob */
9847   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
9848       (GNodeForeachFunc) qtdemux_tag_add_blob, qtdemux);
9849
9850   /* parse up XMP_ node if existing */
9851   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
9852   if (xmp_ != NULL) {
9853     GstBuffer *buf;
9854     GstTagList *taglist;
9855
9856     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
9857         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
9858     taglist = gst_tag_list_from_xmp_buffer (buf);
9859     gst_buffer_unref (buf);
9860
9861     qtdemux_handle_xmp_taglist (qtdemux, taglist);
9862   } else {
9863     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
9864   }
9865
9866 }
9867
9868 typedef struct
9869 {
9870   GstStructure *structure;      /* helper for sort function */
9871   gchar *location;
9872   guint min_req_bitrate;
9873   guint min_req_qt_version;
9874 } GstQtReference;
9875
9876 static gint
9877 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
9878 {
9879   GstQtReference *ref_a = (GstQtReference *) a;
9880   GstQtReference *ref_b = (GstQtReference *) b;
9881
9882   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
9883     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
9884
9885   /* known bitrates go before unknown; higher bitrates go first */
9886   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
9887 }
9888
9889 /* sort the redirects and post a message for the application.
9890  */
9891 static void
9892 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
9893 {
9894   GstQtReference *best;
9895   GstStructure *s;
9896   GstMessage *msg;
9897   GValue list_val = { 0, };
9898   GList *l;
9899
9900   g_assert (references != NULL);
9901
9902   references = g_list_sort (references, qtdemux_redirects_sort_func);
9903
9904   best = (GstQtReference *) references->data;
9905
9906   g_value_init (&list_val, GST_TYPE_LIST);
9907
9908   for (l = references; l != NULL; l = l->next) {
9909     GstQtReference *ref = (GstQtReference *) l->data;
9910     GValue struct_val = { 0, };
9911
9912     ref->structure = gst_structure_new ("redirect",
9913         "new-location", G_TYPE_STRING, ref->location, NULL);
9914
9915     if (ref->min_req_bitrate > 0) {
9916       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
9917           ref->min_req_bitrate, NULL);
9918     }
9919
9920     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
9921     g_value_set_boxed (&struct_val, ref->structure);
9922     gst_value_list_append_value (&list_val, &struct_val);
9923     g_value_unset (&struct_val);
9924     /* don't free anything here yet, since we need best->structure below */
9925   }
9926
9927   g_assert (best != NULL);
9928   s = gst_structure_copy (best->structure);
9929
9930   if (g_list_length (references) > 1) {
9931     gst_structure_set_value (s, "locations", &list_val);
9932   }
9933
9934   g_value_unset (&list_val);
9935
9936   for (l = references; l != NULL; l = l->next) {
9937     GstQtReference *ref = (GstQtReference *) l->data;
9938
9939     gst_structure_free (ref->structure);
9940     g_free (ref->location);
9941     g_free (ref);
9942   }
9943   g_list_free (references);
9944
9945   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
9946   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
9947   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
9948   qtdemux->posted_redirect = TRUE;
9949 }
9950
9951 /* look for redirect nodes, collect all redirect information and
9952  * process it.
9953  */
9954 static gboolean
9955 qtdemux_parse_redirects (GstQTDemux * qtdemux)
9956 {
9957   GNode *rmra, *rmda, *rdrf;
9958
9959   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
9960   if (rmra) {
9961     GList *redirects = NULL;
9962
9963     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
9964     while (rmda) {
9965       GstQtReference ref = { NULL, NULL, 0, 0 };
9966       GNode *rmdr, *rmvc;
9967
9968       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
9969         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
9970         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
9971             ref.min_req_bitrate);
9972       }
9973
9974       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
9975         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
9976         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
9977
9978 #ifndef GST_DISABLE_GST_DEBUG
9979         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
9980 #endif
9981         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
9982
9983         GST_LOG_OBJECT (qtdemux,
9984             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
9985             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
9986             bitmask, check_type);
9987         if (package == FOURCC_qtim && check_type == 0) {
9988           ref.min_req_qt_version = version;
9989         }
9990       }
9991
9992       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
9993       if (rdrf) {
9994         guint32 ref_type;
9995         guint8 *ref_data;
9996
9997         ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
9998         ref_data = (guint8 *) rdrf->data + 20;
9999         if (ref_type == FOURCC_alis) {
10000           guint record_len, record_version, fn_len;
10001
10002           /* MacOSX alias record, google for alias-layout.txt */
10003           record_len = QT_UINT16 (ref_data + 4);
10004           record_version = QT_UINT16 (ref_data + 4 + 2);
10005           fn_len = QT_UINT8 (ref_data + 50);
10006           if (record_len > 50 && record_version == 2 && fn_len > 0) {
10007             ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
10008           }
10009         } else if (ref_type == FOURCC_url_) {
10010           ref.location = g_strdup ((gchar *) ref_data);
10011         } else {
10012           GST_DEBUG_OBJECT (qtdemux,
10013               "unknown rdrf reference type %" GST_FOURCC_FORMAT,
10014               GST_FOURCC_ARGS (ref_type));
10015         }
10016         if (ref.location != NULL) {
10017           GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
10018           redirects = g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
10019         } else {
10020           GST_WARNING_OBJECT (qtdemux,
10021               "Failed to extract redirect location from rdrf atom");
10022         }
10023       }
10024
10025       /* look for others */
10026       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
10027     }
10028
10029     if (redirects != NULL) {
10030       qtdemux_process_redirects (qtdemux, redirects);
10031     }
10032   }
10033   return TRUE;
10034 }
10035
10036 static GstTagList *
10037 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
10038 {
10039   const gchar *fmt;
10040
10041   if (tags == NULL) {
10042     tags = gst_tag_list_new_empty ();
10043     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
10044   }
10045
10046   if (qtdemux->major_brand == FOURCC_mjp2)
10047     fmt = "Motion JPEG 2000";
10048   else if ((qtdemux->major_brand & 0xffff) == GST_MAKE_FOURCC ('3', 'g', 0, 0))
10049     fmt = "3GP";
10050   else if (qtdemux->major_brand == FOURCC_qt__)
10051     fmt = "Quicktime";
10052   else if (qtdemux->fragmented)
10053     fmt = "ISO fMP4";
10054   else
10055     fmt = "ISO MP4/M4A";
10056
10057   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
10058       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
10059
10060   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
10061       fmt, NULL);
10062
10063   return tags;
10064 }
10065
10066 /* we have read th complete moov node now.
10067  * This function parses all of the relevant info, creates the traks and
10068  * prepares all data structures for playback
10069  */
10070 static gboolean
10071 qtdemux_parse_tree (GstQTDemux * qtdemux)
10072 {
10073   GNode *mvhd;
10074   GNode *trak;
10075   GNode *udta;
10076   GNode *mvex;
10077   gint64 duration;
10078   guint64 creation_time;
10079   GstDateTime *datetime = NULL;
10080   gint version;
10081
10082   /* make sure we have a usable taglist */
10083   if (!qtdemux->tag_list) {
10084     qtdemux->tag_list = gst_tag_list_new_empty ();
10085     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
10086   } else {
10087     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
10088   }
10089
10090   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
10091   if (mvhd == NULL) {
10092     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
10093     return qtdemux_parse_redirects (qtdemux);
10094   }
10095
10096   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
10097   if (version == 1) {
10098     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
10099     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
10100     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
10101   } else if (version == 0) {
10102     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
10103     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
10104     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
10105   } else {
10106     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
10107     return FALSE;
10108   }
10109
10110   /* Moving qt creation time (secs since 1904) to unix time */
10111   if (creation_time != 0) {
10112     /* Try to use epoch first as it should be faster and more commonly found */
10113     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
10114       GTimeVal now;
10115
10116       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
10117       /* some data cleansing sanity */
10118       g_get_current_time (&now);
10119       if (now.tv_sec + 24 * 3600 < creation_time) {
10120         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
10121       } else {
10122         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
10123       }
10124     } else {
10125       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
10126       GDateTime *dt, *dt_local;
10127
10128       dt = g_date_time_add_seconds (base_dt, creation_time);
10129       dt_local = g_date_time_to_local (dt);
10130       datetime = gst_date_time_new_from_g_date_time (dt_local);
10131
10132       g_date_time_unref (base_dt);
10133       g_date_time_unref (dt);
10134     }
10135   }
10136   if (datetime) {
10137     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
10138     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
10139         datetime, NULL);
10140     gst_date_time_unref (datetime);
10141   }
10142
10143   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
10144   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
10145
10146   /* check for fragmented file and get some (default) data */
10147   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
10148   if (mvex) {
10149     GNode *mehd;
10150     GstByteReader mehd_data;
10151
10152     /* let track parsing or anyone know weird stuff might happen ... */
10153     qtdemux->fragmented = TRUE;
10154
10155     /* compensate for total duration */
10156     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
10157     if (mehd)
10158       qtdemux_parse_mehd (qtdemux, &mehd_data);
10159   }
10160
10161   /* parse all traks */
10162   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
10163   while (trak) {
10164     qtdemux_parse_trak (qtdemux, trak);
10165     /* iterate all siblings */
10166     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
10167   }
10168
10169   /* set duration in the segment info */
10170   gst_qtdemux_get_duration (qtdemux, &duration);
10171   if (duration) {
10172     qtdemux->segment.duration = duration;
10173     /* also do not exceed duration; stop is set that way post seek anyway,
10174      * and segment activation falls back to duration,
10175      * whereas loop only checks stop, so let's align this here as well */
10176     qtdemux->segment.stop = duration;
10177   }
10178
10179   /* find tags */
10180   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
10181   if (udta) {
10182     qtdemux_parse_udta (qtdemux, udta);
10183   } else {
10184     GST_LOG_OBJECT (qtdemux, "No udta node found.");
10185   }
10186
10187   /* maybe also some tags in meta box */
10188   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
10189   if (udta) {
10190     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
10191     qtdemux_parse_udta (qtdemux, udta);
10192   } else {
10193     GST_LOG_OBJECT (qtdemux, "No meta node found.");
10194   }
10195
10196   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
10197
10198   return TRUE;
10199 }
10200
10201 /* taken from ffmpeg */
10202 static int
10203 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
10204 {
10205   int count = 4;
10206   int len = 0;
10207
10208   while (count--) {
10209     int c;
10210
10211     if (ptr >= end)
10212       return -1;
10213
10214     c = *ptr++;
10215     len = (len << 7) | (c & 0x7f);
10216     if (!(c & 0x80))
10217       break;
10218   }
10219   *end_out = ptr;
10220   return len;
10221 }
10222
10223 /* this can change the codec originally present in @list */
10224 static void
10225 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
10226     GNode * esds, GstTagList * list)
10227 {
10228   int len = QT_UINT32 (esds->data);
10229   guint8 *ptr = esds->data;
10230   guint8 *end = ptr + len;
10231   int tag;
10232   guint8 *data_ptr = NULL;
10233   int data_len = 0;
10234   guint8 object_type_id = 0;
10235   const char *codec_name = NULL;
10236   GstCaps *caps = NULL;
10237
10238   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
10239   ptr += 8;
10240   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
10241   ptr += 4;
10242   while (ptr + 1 < end) {
10243     tag = QT_UINT8 (ptr);
10244     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
10245     ptr++;
10246     len = read_descr_size (ptr, end, &ptr);
10247     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
10248
10249     /* Check the stated amount of data is available for reading */
10250     if (len < 0 || ptr + len > end)
10251       break;
10252
10253     switch (tag) {
10254       case ES_DESCRIPTOR_TAG:
10255         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
10256         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
10257         ptr += 3;
10258         break;
10259       case DECODER_CONFIG_DESC_TAG:{
10260         guint max_bitrate, avg_bitrate;
10261
10262         object_type_id = QT_UINT8 (ptr);
10263         max_bitrate = QT_UINT32 (ptr + 5);
10264         avg_bitrate = QT_UINT32 (ptr + 9);
10265         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
10266         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
10267         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
10268         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
10269         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
10270         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10271           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
10272               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
10273         }
10274         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10275           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
10276               avg_bitrate, NULL);
10277         }
10278         ptr += 13;
10279         break;
10280       }
10281       case DECODER_SPECIFIC_INFO_TAG:
10282         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
10283         if (object_type_id == 0xe0 && len == 0x40) {
10284           guint8 *data;
10285           GstStructure *s;
10286           guint32 clut[16];
10287           gint i;
10288
10289           GST_DEBUG_OBJECT (qtdemux,
10290               "Have VOBSUB palette. Creating palette event");
10291           /* move to decConfigDescr data and read palette */
10292           data = ptr;
10293           for (i = 0; i < 16; i++) {
10294             clut[i] = QT_UINT32 (data);
10295             data += 4;
10296           }
10297
10298           s = gst_structure_new ("application/x-gst-dvd", "event",
10299               G_TYPE_STRING, "dvd-spu-clut-change",
10300               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
10301               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
10302               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
10303               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
10304               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
10305               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
10306               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
10307               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
10308               NULL);
10309
10310           /* store event and trigger custom processing */
10311           stream->pending_event =
10312               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
10313         } else {
10314           /* Generic codec_data handler puts it on the caps */
10315           data_ptr = ptr;
10316           data_len = len;
10317         }
10318
10319         ptr += len;
10320         break;
10321       case SL_CONFIG_DESC_TAG:
10322         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
10323         ptr += 1;
10324         break;
10325       default:
10326         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
10327             tag);
10328         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
10329         ptr += len;
10330         break;
10331     }
10332   }
10333
10334   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
10335    * in use, and should also be used to override some other parameters for some
10336    * codecs. */
10337   switch (object_type_id) {
10338     case 0x20:                 /* MPEG-4 */
10339       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
10340        * profile_and_level_indication */
10341       if (data_ptr != NULL && data_len >= 5 &&
10342           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
10343         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
10344             data_ptr + 4, data_len - 4);
10345       }
10346       break;                    /* Nothing special needed here */
10347     case 0x21:                 /* H.264 */
10348       codec_name = "H.264 / AVC";
10349       caps = gst_caps_new_simple ("video/x-h264",
10350           "stream-format", G_TYPE_STRING, "avc",
10351           "alignment", G_TYPE_STRING, "au", NULL);
10352       break;
10353     case 0x40:                 /* AAC (any) */
10354     case 0x66:                 /* AAC Main */
10355     case 0x67:                 /* AAC LC */
10356     case 0x68:                 /* AAC SSR */
10357       /* Override channels and rate based on the codec_data, as it's often
10358        * wrong. */
10359       /* Only do so for basic setup without HE-AAC extension */
10360       if (data_ptr && data_len == 2) {
10361         guint channels, rateindex, rate;
10362
10363         /* FIXME: add gst_codec_utils_aac_get_{channels|sample_rate}()? */
10364         channels = (data_ptr[1] & 0x7f) >> 3;
10365         if (channels > 0 && channels < 7) {
10366           stream->n_channels = channels;
10367         } else if (channels == 7) {
10368           stream->n_channels = 8;
10369         }
10370
10371         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
10372         rate = gst_codec_utils_aac_get_sample_rate_from_index (rateindex);
10373         if (rate > 0)
10374           stream->rate = rate;
10375       }
10376
10377       /* Set level and profile if possible */
10378       if (data_ptr != NULL && data_len >= 2) {
10379         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
10380             data_ptr, data_len);
10381       }
10382       break;
10383     case 0x60:                 /* MPEG-2, various profiles */
10384     case 0x61:
10385     case 0x62:
10386     case 0x63:
10387     case 0x64:
10388     case 0x65:
10389       codec_name = "MPEG-2 video";
10390       caps = gst_caps_new_simple ("video/mpeg",
10391           "mpegversion", G_TYPE_INT, 2,
10392           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
10393       break;
10394     case 0x69:                 /* MPEG-2 BC audio */
10395     case 0x6B:                 /* MPEG-1 audio */
10396       caps = gst_caps_new_simple ("audio/mpeg",
10397           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
10398       codec_name = "MPEG-1 audio";
10399       break;
10400     case 0x6A:                 /* MPEG-1 */
10401       codec_name = "MPEG-1 video";
10402       caps = gst_caps_new_simple ("video/mpeg",
10403           "mpegversion", G_TYPE_INT, 1,
10404           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
10405       break;
10406     case 0x6C:                 /* MJPEG */
10407       caps = gst_caps_new_empty_simple ("image/jpeg");
10408       codec_name = "Motion-JPEG";
10409       break;
10410     case 0x6D:                 /* PNG */
10411       caps = gst_caps_new_empty_simple ("image/png");
10412       codec_name = "PNG still images";
10413       break;
10414     case 0x6E:                 /* JPEG2000 */
10415       codec_name = "JPEG-2000";
10416       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
10417       break;
10418     case 0xA4:                 /* Dirac */
10419       codec_name = "Dirac";
10420       caps = gst_caps_new_empty_simple ("video/x-dirac");
10421       break;
10422     case 0xA5:                 /* AC3 */
10423       codec_name = "AC-3 audio";
10424       caps = gst_caps_new_simple ("audio/x-ac3",
10425           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
10426       break;
10427     case 0xE1:                 /* QCELP */
10428       /* QCELP, the codec_data is a riff tag (little endian) with
10429        * 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). */
10430       caps = gst_caps_new_empty_simple ("audio/qcelp");
10431       codec_name = "QCELP";
10432       break;
10433     default:
10434       break;
10435   }
10436
10437   /* If we have a replacement caps, then change our caps for this stream */
10438   if (caps) {
10439     gst_caps_unref (stream->caps);
10440     stream->caps = caps;
10441   }
10442
10443   if (codec_name && list)
10444     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
10445         GST_TAG_AUDIO_CODEC, codec_name, NULL);
10446
10447   /* Add the codec_data attribute to caps, if we have it */
10448   if (data_ptr) {
10449     GstBuffer *buffer;
10450
10451     buffer = gst_buffer_new_and_alloc (data_len);
10452     gst_buffer_fill (buffer, 0, data_ptr, data_len);
10453
10454     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
10455     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
10456
10457     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
10458         buffer, NULL);
10459     gst_buffer_unref (buffer);
10460   }
10461
10462 }
10463
10464 #define _codec(name) \
10465   do { \
10466     if (codec_name) { \
10467       *codec_name = g_strdup (name); \
10468     } \
10469   } while (0)
10470
10471 static GstCaps *
10472 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
10473     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
10474 {
10475   GstCaps *caps = NULL;
10476   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
10477
10478   switch (fourcc) {
10479     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
10480       _codec ("PNG still images");
10481       caps = gst_caps_new_empty_simple ("image/png");
10482       break;
10483     case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'):
10484       _codec ("JPEG still images");
10485       caps = gst_caps_new_empty_simple ("image/jpeg");
10486       break;
10487     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
10488     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
10489     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
10490     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
10491       _codec ("Motion-JPEG");
10492       caps = gst_caps_new_empty_simple ("image/jpeg");
10493       break;
10494     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
10495       _codec ("Motion-JPEG format B");
10496       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
10497       break;
10498     case GST_MAKE_FOURCC ('m', 'j', 'p', '2'):
10499       _codec ("JPEG-2000");
10500       /* override to what it should be according to spec, avoid palette_data */
10501       stream->bits_per_sample = 24;
10502       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
10503       break;
10504     case GST_MAKE_FOURCC ('S', 'V', 'Q', '3'):
10505       _codec ("Sorensen video v.3");
10506       caps = gst_caps_new_simple ("video/x-svq",
10507           "svqversion", G_TYPE_INT, 3, NULL);
10508       break;
10509     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
10510     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
10511       _codec ("Sorensen video v.1");
10512       caps = gst_caps_new_simple ("video/x-svq",
10513           "svqversion", G_TYPE_INT, 1, NULL);
10514       break;
10515     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
10516       caps = gst_caps_new_empty_simple ("video/x-raw");
10517       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
10518       _codec ("Windows Raw RGB");
10519       break;
10520     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
10521     {
10522       guint16 bps;
10523
10524       bps = QT_UINT16 (stsd_data + 98);
10525       switch (bps) {
10526         case 15:
10527           format = GST_VIDEO_FORMAT_RGB15;
10528           break;
10529         case 16:
10530           format = GST_VIDEO_FORMAT_RGB16;
10531           break;
10532         case 24:
10533           format = GST_VIDEO_FORMAT_RGB;
10534           break;
10535         case 32:
10536           format = GST_VIDEO_FORMAT_ARGB;
10537           break;
10538         default:
10539           /* unknown */
10540           break;
10541       }
10542       break;
10543     }
10544     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
10545       format = GST_VIDEO_FORMAT_I420;
10546       break;
10547     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
10548     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
10549       format = GST_VIDEO_FORMAT_I420;
10550       break;
10551     case GST_MAKE_FOURCC ('2', 'v', 'u', 'y'):
10552     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
10553     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
10554       format = GST_VIDEO_FORMAT_UYVY;
10555       break;
10556     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
10557       format = GST_VIDEO_FORMAT_r210;
10558       break;
10559     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
10560     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
10561       _codec ("MPEG-1 video");
10562       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
10563           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
10564       break;
10565     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
10566     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
10567     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
10568     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
10569     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
10570     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
10571     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
10572     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
10573     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
10574     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
10575     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
10576     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
10577     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
10578     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
10579     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
10580     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
10581     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
10582     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
10583     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
10584     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
10585     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
10586     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
10587     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
10588     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
10589     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
10590     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
10591     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
10592     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
10593     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
10594     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
10595     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
10596     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
10597     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
10598     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
10599     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
10600     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
10601     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
10602     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
10603     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
10604     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
10605     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
10606     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
10607     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
10608     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
10609     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
10610     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
10611       _codec ("MPEG-2 video");
10612       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
10613           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
10614       break;
10615     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
10616       _codec ("GIF still images");
10617       caps = gst_caps_new_empty_simple ("image/gif");
10618       break;
10619     case GST_MAKE_FOURCC ('h', '2', '6', '3'):
10620     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
10621     case GST_MAKE_FOURCC ('s', '2', '6', '3'):
10622     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
10623       _codec ("H.263");
10624       /* ffmpeg uses the height/width props, don't know why */
10625       caps = gst_caps_new_simple ("video/x-h263",
10626           "variant", G_TYPE_STRING, "itu", NULL);
10627       break;
10628     case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
10629     case GST_MAKE_FOURCC ('M', 'P', '4', 'V'):
10630       _codec ("MPEG-4 video");
10631       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
10632           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
10633       break;
10634     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
10635     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
10636       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
10637       caps = gst_caps_new_simple ("video/x-msmpeg",
10638           "msmpegversion", G_TYPE_INT, 43, NULL);
10639       break;
10640     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
10641       _codec ("DivX 3");
10642       caps = gst_caps_new_simple ("video/x-divx",
10643           "divxversion", G_TYPE_INT, 3, NULL);
10644       break;
10645     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
10646     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
10647       _codec ("DivX 4");
10648       caps = gst_caps_new_simple ("video/x-divx",
10649           "divxversion", G_TYPE_INT, 4, NULL);
10650       break;
10651     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
10652       _codec ("DivX 5");
10653       caps = gst_caps_new_simple ("video/x-divx",
10654           "divxversion", G_TYPE_INT, 5, NULL);
10655       break;
10656
10657     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
10658     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
10659     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
10660     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
10661     case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
10662     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
10663       caps = gst_caps_new_simple ("video/mpeg",
10664           "mpegversion", G_TYPE_INT, 4, NULL);
10665       if (codec_name)
10666         *codec_name = g_strdup ("MPEG-4");
10667       break;
10668
10669     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
10670       _codec ("Cinepak");
10671       caps = gst_caps_new_empty_simple ("video/x-cinepak");
10672       break;
10673     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
10674       _codec ("Apple QuickDraw");
10675       caps = gst_caps_new_empty_simple ("video/x-qdrw");
10676       break;
10677     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
10678       _codec ("Apple video");
10679       caps = gst_caps_new_empty_simple ("video/x-apple-video");
10680       break;
10681     case GST_MAKE_FOURCC ('H', '2', '6', '4'):
10682     case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
10683       _codec ("H.264 / AVC");
10684       caps = gst_caps_new_simple ("video/x-h264",
10685           "stream-format", G_TYPE_STRING, "avc",
10686           "alignment", G_TYPE_STRING, "au", NULL);
10687       break;
10688     case GST_MAKE_FOURCC ('a', 'v', 'c', '3'):
10689       _codec ("H.264 / AVC");
10690       caps = gst_caps_new_simple ("video/x-h264",
10691           "stream-format", G_TYPE_STRING, "avc3",
10692           "alignment", G_TYPE_STRING, "au", NULL);
10693       break;
10694     case GST_MAKE_FOURCC ('H', '2', '6', '5'):
10695     case GST_MAKE_FOURCC ('h', 'v', 'c', '1'):
10696       _codec ("H.265 / HEVC");
10697       caps = gst_caps_new_simple ("video/x-h265",
10698           "stream-format", G_TYPE_STRING, "hvc1",
10699           "alignment", G_TYPE_STRING, "au", NULL);
10700       break;
10701     case GST_MAKE_FOURCC ('h', 'e', 'v', '1'):
10702       _codec ("H.265 / HEVC");
10703       caps = gst_caps_new_simple ("video/x-h265",
10704           "stream-format", G_TYPE_STRING, "hev1",
10705           "alignment", G_TYPE_STRING, "au", NULL);
10706       break;
10707     case GST_MAKE_FOURCC ('r', 'l', 'e', ' '):
10708       _codec ("Run-length encoding");
10709       caps = gst_caps_new_simple ("video/x-rle",
10710           "layout", G_TYPE_STRING, "quicktime", NULL);
10711       break;
10712     case GST_MAKE_FOURCC ('W', 'R', 'L', 'E'):
10713       _codec ("Run-length encoding");
10714       caps = gst_caps_new_simple ("video/x-rle",
10715           "layout", G_TYPE_STRING, "microsoft", NULL);
10716       break;
10717     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
10718     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
10719       _codec ("Indeo Video 3");
10720       caps = gst_caps_new_simple ("video/x-indeo",
10721           "indeoversion", G_TYPE_INT, 3, NULL);
10722       break;
10723     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
10724     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
10725       _codec ("Intel Video 4");
10726       caps = gst_caps_new_simple ("video/x-indeo",
10727           "indeoversion", G_TYPE_INT, 4, NULL);
10728       break;
10729     case GST_MAKE_FOURCC ('d', 'v', 'c', 'p'):
10730     case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
10731     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
10732     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
10733     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
10734     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
10735     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
10736     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
10737       _codec ("DV Video");
10738       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
10739           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
10740       break;
10741     case GST_MAKE_FOURCC ('d', 'v', '5', 'n'): /* DVCPRO50 NTSC */
10742     case GST_MAKE_FOURCC ('d', 'v', '5', 'p'): /* DVCPRO50 PAL */
10743       _codec ("DVCPro50 Video");
10744       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
10745           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
10746       break;
10747     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
10748     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
10749       _codec ("DVCProHD Video");
10750       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
10751           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
10752       break;
10753     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
10754       _codec ("Apple Graphics (SMC)");
10755       caps = gst_caps_new_empty_simple ("video/x-smc");
10756       break;
10757     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
10758       _codec ("VP3");
10759       caps = gst_caps_new_empty_simple ("video/x-vp3");
10760       break;
10761     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
10762       _codec ("VP6 Flash");
10763       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
10764       break;
10765     case GST_MAKE_FOURCC ('X', 'i', 'T', 'h'):
10766       _codec ("Theora");
10767       caps = gst_caps_new_empty_simple ("video/x-theora");
10768       /* theora uses one byte of padding in the data stream because it does not
10769        * allow 0 sized packets while theora does */
10770       stream->padding = 1;
10771       break;
10772     case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'):
10773       _codec ("Dirac");
10774       caps = gst_caps_new_empty_simple ("video/x-dirac");
10775       break;
10776     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
10777       _codec ("TIFF still images");
10778       caps = gst_caps_new_empty_simple ("image/tiff");
10779       break;
10780     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
10781       _codec ("Apple Intermediate Codec");
10782       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
10783       break;
10784     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
10785       _codec ("AVID DNxHD");
10786       caps = gst_caps_from_string ("video/x-dnxhd");
10787       break;
10788     case GST_MAKE_FOURCC ('V', 'P', '8', '0'):
10789       _codec ("On2 VP8");
10790       caps = gst_caps_from_string ("video/x-vp8");
10791       break;
10792     case GST_MAKE_FOURCC ('a', 'p', 'c', 's'):
10793       _codec ("Apple ProRes LT");
10794       caps =
10795           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
10796           NULL);
10797       break;
10798     case GST_MAKE_FOURCC ('a', 'p', 'c', 'h'):
10799       _codec ("Apple ProRes HQ");
10800       caps =
10801           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
10802           NULL);
10803       break;
10804     case GST_MAKE_FOURCC ('a', 'p', 'c', 'n'):
10805       _codec ("Apple ProRes");
10806       caps =
10807           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
10808           "standard", NULL);
10809       break;
10810     case GST_MAKE_FOURCC ('a', 'p', 'c', 'o'):
10811       _codec ("Apple ProRes Proxy");
10812       caps =
10813           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
10814           "proxy", NULL);
10815       break;
10816     case GST_MAKE_FOURCC ('a', 'p', '4', 'h'):
10817       _codec ("Apple ProRes 4444");
10818       caps =
10819           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
10820           "4444", NULL);
10821       break;
10822     case FOURCC_ovc1:
10823       _codec ("VC-1");
10824       caps = gst_caps_new_simple ("video/x-wmv",
10825           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
10826       break;
10827     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
10828     default:
10829     {
10830       char *s, fourstr[5];
10831
10832       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10833       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
10834       caps = gst_caps_new_empty_simple (s);
10835       break;
10836     }
10837   }
10838
10839   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
10840     GstVideoInfo info;
10841
10842     gst_video_info_init (&info);
10843     gst_video_info_set_format (&info, format, stream->width, stream->height);
10844     caps = gst_video_info_to_caps (&info);
10845     *codec_name = gst_pb_utils_get_codec_description (caps);
10846
10847     /* enable clipping for raw video streams */
10848     stream->need_clip = TRUE;
10849   }
10850
10851   return caps;
10852 }
10853
10854 static GstCaps *
10855 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
10856     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
10857 {
10858   GstCaps *caps;
10859   const GstStructure *s;
10860   const gchar *name;
10861   gint endian = 0;
10862
10863   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc %08x", fourcc);
10864
10865   switch (fourcc) {
10866     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
10867     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
10868       _codec ("Raw 8-bit PCM audio");
10869       caps = gst_caps_new_simple ("audio/x-raw",
10870           "format", G_TYPE_STRING, "U8",
10871           "layout", G_TYPE_STRING, "interleaved", NULL);
10872       break;
10873     case GST_MAKE_FOURCC ('t', 'w', 'o', 's'):
10874       endian = G_BIG_ENDIAN;
10875       /* fall-through */
10876     case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
10877     {
10878       gchar *str;
10879       gint depth;
10880       GstAudioFormat format;
10881
10882       if (!endian)
10883         endian = G_LITTLE_ENDIAN;
10884
10885       depth = stream->bytes_per_packet * 8;
10886       format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
10887
10888       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
10889       _codec (str);
10890       g_free (str);
10891
10892       caps = gst_caps_new_simple ("audio/x-raw",
10893           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
10894           "layout", G_TYPE_STRING, "interleaved", NULL);
10895       break;
10896     }
10897     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
10898       _codec ("Raw 64-bit floating-point audio");
10899       caps = gst_caps_new_simple ("audio/x-raw",
10900           "format", G_TYPE_STRING, "F64BE",
10901           "layout", G_TYPE_STRING, "interleaved", NULL);
10902       break;
10903     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
10904       _codec ("Raw 32-bit floating-point audio");
10905       caps = gst_caps_new_simple ("audio/x-raw",
10906           "format", G_TYPE_STRING, "F32BE",
10907           "layout", G_TYPE_STRING, "interleaved", NULL);
10908       break;
10909     case FOURCC_in24:
10910       _codec ("Raw 24-bit PCM audio");
10911       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
10912        * endian later */
10913       caps = gst_caps_new_simple ("audio/x-raw",
10914           "format", G_TYPE_STRING, "S24BE",
10915           "layout", G_TYPE_STRING, "interleaved", NULL);
10916       break;
10917     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
10918       _codec ("Raw 32-bit PCM audio");
10919       caps = gst_caps_new_simple ("audio/x-raw",
10920           "format", G_TYPE_STRING, "S32BE",
10921           "layout", G_TYPE_STRING, "interleaved", NULL);
10922       break;
10923     case GST_MAKE_FOURCC ('u', 'l', 'a', 'w'):
10924       _codec ("Mu-law audio");
10925       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
10926       break;
10927     case GST_MAKE_FOURCC ('a', 'l', 'a', 'w'):
10928       _codec ("A-law audio");
10929       caps = gst_caps_new_empty_simple ("audio/x-alaw");
10930       break;
10931     case 0x0200736d:
10932     case 0x6d730002:
10933       _codec ("Microsoft ADPCM");
10934       /* Microsoft ADPCM-ACM code 2 */
10935       caps = gst_caps_new_simple ("audio/x-adpcm",
10936           "layout", G_TYPE_STRING, "microsoft", NULL);
10937       break;
10938     case 0x1100736d:
10939     case 0x6d730011:
10940       _codec ("DVI/IMA ADPCM");
10941       caps = gst_caps_new_simple ("audio/x-adpcm",
10942           "layout", G_TYPE_STRING, "dvi", NULL);
10943       break;
10944     case 0x1700736d:
10945     case 0x6d730017:
10946       _codec ("DVI/Intel IMA ADPCM");
10947       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
10948       caps = gst_caps_new_simple ("audio/x-adpcm",
10949           "layout", G_TYPE_STRING, "quicktime", NULL);
10950       break;
10951     case 0x5500736d:
10952     case 0x6d730055:
10953       /* MPEG layer 3, CBR only (pre QT4.1) */
10954     case GST_MAKE_FOURCC ('.', 'm', 'p', '3'):
10955       _codec ("MPEG-1 layer 3");
10956       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
10957       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
10958           "mpegversion", G_TYPE_INT, 1, NULL);
10959       break;
10960     case 0x20736d:
10961     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
10962       _codec ("EAC-3 audio");
10963       caps = gst_caps_new_simple ("audio/x-eac3",
10964           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
10965       stream->sampled = TRUE;
10966       break;
10967     case GST_MAKE_FOURCC ('a', 'c', '-', '3'):
10968       _codec ("AC-3 audio");
10969       caps = gst_caps_new_simple ("audio/x-ac3",
10970           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
10971       stream->sampled = TRUE;
10972       break;
10973     case GST_MAKE_FOURCC ('M', 'A', 'C', '3'):
10974       _codec ("MACE-3");
10975       caps = gst_caps_new_simple ("audio/x-mace",
10976           "maceversion", G_TYPE_INT, 3, NULL);
10977       break;
10978     case GST_MAKE_FOURCC ('M', 'A', 'C', '6'):
10979       _codec ("MACE-6");
10980       caps = gst_caps_new_simple ("audio/x-mace",
10981           "maceversion", G_TYPE_INT, 6, NULL);
10982       break;
10983     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
10984       /* ogg/vorbis */
10985       caps = gst_caps_new_empty_simple ("application/ogg");
10986       break;
10987     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
10988       _codec ("DV audio");
10989       caps = gst_caps_new_empty_simple ("audio/x-dv");
10990       break;
10991     case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):
10992       _codec ("MPEG-4 AAC audio");
10993       caps = gst_caps_new_simple ("audio/mpeg",
10994           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
10995           "stream-format", G_TYPE_STRING, "raw", NULL);
10996       break;
10997     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
10998       _codec ("QDesign Music");
10999       caps = gst_caps_new_empty_simple ("audio/x-qdm");
11000       break;
11001     case GST_MAKE_FOURCC ('Q', 'D', 'M', '2'):
11002       _codec ("QDesign Music v.2");
11003       /* FIXME: QDesign music version 2 (no constant) */
11004       if (FALSE && data) {
11005         caps = gst_caps_new_simple ("audio/x-qdm2",
11006             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
11007             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
11008             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
11009       } else {
11010         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
11011       }
11012       break;
11013     case GST_MAKE_FOURCC ('a', 'g', 's', 'm'):
11014       _codec ("GSM audio");
11015       caps = gst_caps_new_empty_simple ("audio/x-gsm");
11016       break;
11017     case GST_MAKE_FOURCC ('s', 'a', 'm', 'r'):
11018       _codec ("AMR audio");
11019       caps = gst_caps_new_empty_simple ("audio/AMR");
11020       break;
11021     case GST_MAKE_FOURCC ('s', 'a', 'w', 'b'):
11022       _codec ("AMR-WB audio");
11023       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
11024       break;
11025     case GST_MAKE_FOURCC ('i', 'm', 'a', '4'):
11026       _codec ("Quicktime IMA ADPCM");
11027       caps = gst_caps_new_simple ("audio/x-adpcm",
11028           "layout", G_TYPE_STRING, "quicktime", NULL);
11029       break;
11030     case GST_MAKE_FOURCC ('a', 'l', 'a', 'c'):
11031       _codec ("Apple lossless audio");
11032       caps = gst_caps_new_empty_simple ("audio/x-alac");
11033       break;
11034     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
11035       _codec ("QualComm PureVoice");
11036       caps = gst_caps_from_string ("audio/qcelp");
11037       break;
11038     case FOURCC_owma:
11039       _codec ("WMA");
11040       caps = gst_caps_new_empty_simple ("audio/x-wma");
11041       break;
11042     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
11043     {
11044       guint32 flags = 0;
11045       guint32 depth = 0;
11046       guint32 width = 0;
11047       GstAudioFormat format;
11048       enum
11049       {
11050         FLAG_IS_FLOAT = 0x1,
11051         FLAG_IS_BIG_ENDIAN = 0x2,
11052         FLAG_IS_SIGNED = 0x4,
11053         FLAG_IS_PACKED = 0x8,
11054         FLAG_IS_ALIGNED_HIGH = 0x10,
11055         FLAG_IS_NON_INTERLEAVED = 0x20
11056       };
11057       _codec ("Raw LPCM audio");
11058
11059       if (data && len >= 56) {
11060         depth = QT_UINT32 (data + 40);
11061         flags = QT_UINT32 (data + 44);
11062         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
11063       }
11064       if ((flags & FLAG_IS_FLOAT) == 0) {
11065         if (depth == 0)
11066           depth = 16;
11067         if (width == 0)
11068           width = 16;
11069         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
11070             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
11071             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
11072         caps = gst_caps_new_simple ("audio/x-raw",
11073             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
11074             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
11075             "non-interleaved" : "interleaved", NULL);
11076       } else {
11077         if (depth == 0)
11078           depth = 32;
11079         if (width == 0)
11080           width = 32;
11081         if (width == 64) {
11082           if (flags & FLAG_IS_BIG_ENDIAN)
11083             format = GST_AUDIO_FORMAT_F64BE;
11084           else
11085             format = GST_AUDIO_FORMAT_F64LE;
11086         } else {
11087           if (flags & FLAG_IS_BIG_ENDIAN)
11088             format = GST_AUDIO_FORMAT_F32BE;
11089           else
11090             format = GST_AUDIO_FORMAT_F32LE;
11091         }
11092         caps = gst_caps_new_simple ("audio/x-raw",
11093             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
11094             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
11095             "non-interleaved" : "interleaved", NULL);
11096       }
11097       break;
11098     }
11099     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
11100       /* ? */
11101     default:
11102     {
11103       char *s, fourstr[5];
11104
11105       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11106       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
11107       caps = gst_caps_new_empty_simple (s);
11108       break;
11109     }
11110   }
11111
11112   if (caps) {
11113     GstCaps *templ_caps =
11114         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
11115     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
11116     gst_caps_unref (caps);
11117     gst_caps_unref (templ_caps);
11118     caps = intersection;
11119   }
11120
11121   /* enable clipping for raw audio streams */
11122   s = gst_caps_get_structure (caps, 0);
11123   name = gst_structure_get_name (s);
11124   if (g_str_has_prefix (name, "audio/x-raw")) {
11125     stream->need_clip = TRUE;
11126     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
11127     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
11128   }
11129   return caps;
11130 }
11131
11132 static GstCaps *
11133 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
11134     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
11135 {
11136   GstCaps *caps;
11137
11138   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc %08x", fourcc);
11139
11140   switch (fourcc) {
11141     case GST_MAKE_FOURCC ('m', 'p', '4', 's'):
11142       _codec ("DVD subtitle");
11143       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
11144       stream->need_process = TRUE;
11145       break;
11146     case GST_MAKE_FOURCC ('t', 'e', 'x', 't'):
11147       _codec ("Quicktime timed text");
11148       goto text;
11149     case GST_MAKE_FOURCC ('t', 'x', '3', 'g'):
11150       _codec ("3GPP timed text");
11151     text:
11152       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
11153           "utf8", NULL);
11154       /* actual text piece needs to be extracted */
11155       stream->need_process = TRUE;
11156       break;
11157     default:
11158     {
11159       char *s, fourstr[5];
11160
11161       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11162       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
11163       caps = gst_caps_new_empty_simple (s);
11164       break;
11165     }
11166   }
11167   return caps;
11168 }
11169
11170 static GstCaps *
11171 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
11172     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
11173 {
11174   GstCaps *caps;
11175
11176   switch (fourcc) {
11177     case GST_MAKE_FOURCC ('m', '1', 'v', ' '):
11178       _codec ("MPEG 1 video");
11179       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
11180           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11181       break;
11182     default:
11183       caps = NULL;
11184       break;
11185   }
11186   return caps;
11187 }