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