Revert "Revert "qtdemux: respect qt segments in push-mode for empty starts""
[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  * Copyright (C) <2015> YouView TV Ltd.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public
24  * License along with this library; if not, write to the
25  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 /**
30  * SECTION:element-qtdemux
31  *
32  * Demuxes a .mov file into raw or compressed audio and/or video streams.
33  *
34  * This element supports both push and pull-based scheduling, depending on the
35  * capabilities of the upstream elements.
36  *
37  * <refsect2>
38  * <title>Example launch line</title>
39  * |[
40  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
41  * ]| Play (parse and decode) a .mov file and try to output it to
42  * an automatically detected soundcard and videosink. If the MOV file contains
43  * compressed audio or video data, this will only work if you have the
44  * right decoder elements/plugins installed.
45  * </refsect2>
46  */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #include "gst/gst-i18n-plugin.h"
53
54 #include <glib/gprintf.h>
55 #include <gst/tag/tag.h>
56 #include <gst/audio/audio.h>
57 #include <gst/video/video.h>
58
59 #include "qtatomparser.h"
60 #include "qtdemux_types.h"
61 #include "qtdemux_dump.h"
62 #include "fourcc.h"
63 #include "descriptors.h"
64 #include "qtdemux_lang.h"
65 #include "qtdemux.h"
66 #include "qtpalette.h"
67
68 #include "gst/riff/riff-media.h"
69 #include "gst/riff/riff-read.h"
70
71 #include <gst/pbutils/pbutils.h>
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include <math.h>
78 #include <gst/math-compat.h>
79
80 #ifdef HAVE_ZLIB
81 # include <zlib.h>
82 #endif
83
84 /* max. size considered 'sane' for non-mdat atoms */
85 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
86
87 /* if the sample index is larger than this, something is likely wrong */
88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
89
90 /* For converting qt creation times to unix epoch times */
91 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
92 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
93 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
94     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
95
96 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
97
98 GST_DEBUG_CATEGORY (qtdemux_debug);
99
100 /*typedef struct _QtNode QtNode; */
101 typedef struct _QtDemuxSegment QtDemuxSegment;
102 typedef struct _QtDemuxSample QtDemuxSample;
103
104 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
105
106 /*struct _QtNode
107 {
108   guint32 type;
109   guint8 *data;
110   gint len;
111 };*/
112
113 struct _QtDemuxSample
114 {
115   guint32 size;
116   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
117   guint64 offset;
118   guint64 timestamp;            /* DTS In mov time */
119   guint32 duration;             /* In mov time */
120   gboolean keyframe;            /* TRUE when this packet is a keyframe */
121 };
122
123 /* Macros for converting to/from timescale */
124 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
125 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
126
127 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
128 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
129
130 /* timestamp is the DTS */
131 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
132 /* timestamp + offset is the PTS */
133 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
134 /* timestamp + duration - dts is the duration */
135 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
136
137 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
138
139 /*
140  * Quicktime has tracks and segments. A track is a continuous piece of
141  * multimedia content. The track is not always played from start to finish but
142  * instead, pieces of the track are 'cut out' and played in sequence. This is
143  * what the segments do.
144  *
145  * Inside the track we have keyframes (K) and delta frames. The track has its
146  * own timing, which starts from 0 and extends to end. The position in the track
147  * is called the media_time.
148  *
149  * The segments now describe the pieces that should be played from this track
150  * and are basically tuples of media_time/duration/rate entries. We can have
151  * multiple segments and they are all played after one another. An example:
152  *
153  * segment 1: media_time: 1 second, duration: 1 second, rate 1
154  * segment 2: media_time: 3 second, duration: 2 second, rate 2
155  *
156  * To correctly play back this track, one must play: 1 second of media starting
157  * from media_time 1 followed by 2 seconds of media starting from media_time 3
158  * at a rate of 2.
159  *
160  * Each of the segments will be played at a specific time, the first segment at
161  * time 0, the second one after the duration of the first one, etc.. Note that
162  * the time in resulting playback is not identical to the media_time of the
163  * track anymore.
164  *
165  * Visually, assuming the track has 4 second of media_time:
166  *
167  *                (a)                   (b)          (c)              (d)
168  *         .-----------------------------------------------------------.
169  * track:  | K.....K.........K........K.......K.......K...........K... |
170  *         '-----------------------------------------------------------'
171  *         0              1              2              3              4
172  *           .------------^              ^   .----------^              ^
173  *          /              .-------------'  /       .------------------'
174  *         /              /          .-----'       /
175  *         .--------------.         .--------------.
176  *         | segment 1    |         | segment 2    |
177  *         '--------------'         '--------------'
178  *
179  * The challenge here is to cut out the right pieces of the track for each of
180  * the playback segments. This fortunately can easily be done with the SEGMENT
181  * events of GStreamer.
182  *
183  * For playback of segment 1, we need to provide the decoder with the keyframe
184  * (a), in the above figure, but we must instruct it only to output the decoded
185  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
186  * position set to the time of the segment: 0.
187  *
188  * We then proceed to push data from keyframe (a) to frame (b). The decoder
189  * decodes but clips all before media_time 1.
190  *
191  * After finishing a segment, we push out a new SEGMENT event with the clipping
192  * boundaries of the new data.
193  *
194  * This is a good usecase for the GStreamer accumulated SEGMENT events.
195  */
196
197 struct _QtDemuxSegment
198 {
199   /* global time and duration, all gst time */
200   GstClockTime time;
201   GstClockTime stop_time;
202   GstClockTime duration;
203   /* media time of trak, all gst time */
204   GstClockTime media_start;
205   GstClockTime media_stop;
206   gdouble rate;
207   /* Media start time in trak timescale units */
208   guint32 trak_media_start;
209 };
210
211 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
212
213 /* Used with fragmented MP4 files (mfra atom) */
214 typedef struct
215 {
216   GstClockTime ts;
217   guint64 moof_offset;
218 } QtDemuxRandomAccessEntry;
219
220 struct _QtDemuxStream
221 {
222   GstPad *pad;
223
224   /* stream type */
225   guint32 subtype;
226   GstCaps *caps;
227   guint32 fourcc;
228   gboolean sparse;
229
230   gboolean new_caps;
231   gboolean new_stream;          /* signals that a stream_start is required */
232   gboolean on_keyframe;         /* if this stream last pushed buffer was a
233                                  * keyframe. This is important to identify
234                                  * where to stop pushing buffers after a
235                                  * segment stop time */
236
237   /* if the stream has a redirect URI in its headers, we store it here */
238   gchar *redirect_uri;
239
240   /* track id */
241   guint track_id;
242
243   /* duration/scale */
244   guint64 duration;             /* in timescale */
245   guint32 timescale;
246
247   /* language */
248   gchar lang_id[4];             /* ISO 639-2T language code */
249
250   /* our samples */
251   guint32 n_samples;
252   QtDemuxSample *samples;
253   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
254   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
255                                    the framerate, in timescale units */
256   guint32 offset_in_sample;
257   guint32 max_buffer_size;
258
259   /* if we use chunks or samples */
260   gboolean sampled;
261   guint padding;
262
263   /* video info */
264   gint width;
265   gint height;
266   /* aspect ratio */
267   gint display_width;
268   gint display_height;
269   gint par_w;
270   gint par_h;
271   /* Numerator/denominator framerate */
272   gint fps_n;
273   gint fps_d;
274   guint16 bits_per_sample;
275   guint16 color_table_id;
276   GstMemory *rgb8_palette;
277
278   /* audio info */
279   gdouble rate;
280   gint n_channels;
281   guint samples_per_packet;
282   guint samples_per_frame;
283   guint bytes_per_packet;
284   guint bytes_per_sample;
285   guint bytes_per_frame;
286   guint compression;
287
288   /* allocation */
289   gboolean use_allocator;
290   GstAllocator *allocator;
291   GstAllocationParams params;
292
293   /* when a discontinuity is pending */
294   gboolean discont;
295
296   /* list of buffers to push first */
297   GSList *buffers;
298
299   /* if we need to clip this buffer. This is only needed for uncompressed
300    * data */
301   gboolean need_clip;
302
303   /* buffer needs some custom processing, e.g. subtitles */
304   gboolean need_process;
305
306   /* current position */
307   guint32 segment_index;
308   guint32 sample_index;
309   GstClockTime time_position;   /* in gst time */
310   guint64 accumulated_base;
311
312   /* the Gst segment we are processing out, used for clipping */
313   GstSegment segment;
314   guint32 segment_seqnum;       /* segment event seqnum obtained from seek */
315
316   /* quicktime segments */
317   guint32 n_segments;
318   QtDemuxSegment *segments;
319   gboolean dummy_segment;
320   guint32 from_sample;
321   guint32 to_sample;
322
323   gboolean sent_eos;
324   GstTagList *pending_tags;
325   gboolean send_global_tags;
326
327   GstEvent *pending_event;
328
329   GstByteReader stco;
330   GstByteReader stsz;
331   GstByteReader stsc;
332   GstByteReader stts;
333   GstByteReader stss;
334   GstByteReader stps;
335   GstByteReader ctts;
336
337   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
338   gint64 stbl_index;
339   /* stco */
340   guint co_size;
341   GstByteReader co_chunk;
342   guint32 first_chunk;
343   guint32 current_chunk;
344   guint32 last_chunk;
345   guint32 samples_per_chunk;
346   guint32 stco_sample_index;
347   /* stsz */
348   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
349   /* stsc */
350   guint32 stsc_index;
351   guint32 n_samples_per_chunk;
352   guint32 stsc_chunk_index;
353   guint32 stsc_sample_index;
354   guint64 chunk_offset;
355   /* stts */
356   guint32 stts_index;
357   guint32 stts_samples;
358   guint32 n_sample_times;
359   guint32 stts_sample_index;
360   guint64 stts_time;
361   guint32 stts_duration;
362   /* stss */
363   gboolean stss_present;
364   guint32 n_sample_syncs;
365   guint32 stss_index;
366   /* stps */
367   gboolean stps_present;
368   guint32 n_sample_partial_syncs;
369   guint32 stps_index;
370   QtDemuxRandomAccessEntry *ra_entries;
371   guint n_ra_entries;
372
373   const QtDemuxRandomAccessEntry *pending_seek;
374
375   /* ctts */
376   gboolean ctts_present;
377   guint32 n_composition_times;
378   guint32 ctts_index;
379   guint32 ctts_sample_index;
380   guint32 ctts_count;
381   gint32 ctts_soffset;
382
383   /* cslg */
384   guint32 cslg_shift;
385
386   /* fragmented */
387   gboolean parsed_trex;
388   guint32 def_sample_duration;
389   guint32 def_sample_size;
390   guint32 def_sample_flags;
391
392   gboolean disabled;
393
394   /* stereoscopic video streams */
395   GstVideoMultiviewMode multiview_mode;
396   GstVideoMultiviewFlags multiview_flags;
397
398   /* protected streams */
399   gboolean protected;
400   guint32 protection_scheme_type;
401   guint32 protection_scheme_version;
402   gpointer protection_scheme_info;      /* specific to the protection scheme */
403   GQueue protection_scheme_event_queue;
404 };
405
406 /* Contains properties and cryptographic info for a set of samples from a
407  * track protected using Common Encryption (cenc) */
408 struct _QtDemuxCencSampleSetInfo
409 {
410   GstStructure *default_properties;
411
412   /* @crypto_info holds one GstStructure per sample */
413   GPtrArray *crypto_info;
414 };
415
416 enum QtDemuxState
417 {
418   QTDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
419   QTDEMUX_STATE_HEADER,         /* Parsing the header */
420   QTDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
421   QTDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
422 };
423
424 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
425 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
426     guint32 fourcc, GstByteReader * parser);
427 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
428 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
429     guint32 fourcc, GstByteReader * parser);
430
431 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
432
433 static GstStaticPadTemplate gst_qtdemux_sink_template =
434     GST_STATIC_PAD_TEMPLATE ("sink",
435     GST_PAD_SINK,
436     GST_PAD_ALWAYS,
437     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
438         "application/x-3gp")
439     );
440
441 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
442 GST_STATIC_PAD_TEMPLATE ("video_%u",
443     GST_PAD_SRC,
444     GST_PAD_SOMETIMES,
445     GST_STATIC_CAPS_ANY);
446
447 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
448 GST_STATIC_PAD_TEMPLATE ("audio_%u",
449     GST_PAD_SRC,
450     GST_PAD_SOMETIMES,
451     GST_STATIC_CAPS_ANY);
452
453 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
454 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
455     GST_PAD_SRC,
456     GST_PAD_SOMETIMES,
457     GST_STATIC_CAPS_ANY);
458
459 #define gst_qtdemux_parent_class parent_class
460 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
461
462 static void gst_qtdemux_dispose (GObject * object);
463
464 static guint32
465 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
466     GstClockTime media_time);
467 static guint32
468 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
469     QtDemuxStream * str, gint64 media_offset);
470
471 #if 0
472 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
473 static GstIndex *gst_qtdemux_get_index (GstElement * element);
474 #endif
475 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
476     GstStateChange transition);
477 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
478 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
479     GstObject * parent, GstPadMode mode, gboolean active);
480
481 static void gst_qtdemux_loop (GstPad * pad);
482 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
483     GstBuffer * inbuf);
484 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
485     GstEvent * event);
486 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
487 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
488     QtDemuxStream * stream);
489 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
490     gboolean force);
491
492 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
493     const guint8 * buffer, guint length);
494 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
495     const guint8 * buffer, guint length);
496 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
497 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
498     GNode * udta);
499
500 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
501     QtDemuxStream * stream, GNode * esds, GstTagList * list);
502 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
503     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
504     gchar ** codec_name);
505 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
506     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
507     gchar ** codec_name);
508 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
509     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
510     gchar ** codec_name);
511 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
512     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
513     gchar ** codec_name);
514
515 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
516     QtDemuxStream * stream, guint32 n);
517 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
518 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
519     QtDemuxStream * stream);
520 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
521     QtDemuxStream * stream);
522 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
523 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
524 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
525     QtDemuxStream * stream);
526
527 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
528 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
529
530 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
531     const gchar * id);
532
533 static void
534 gst_qtdemux_class_init (GstQTDemuxClass * klass)
535 {
536   GObjectClass *gobject_class;
537   GstElementClass *gstelement_class;
538
539   gobject_class = (GObjectClass *) klass;
540   gstelement_class = (GstElementClass *) klass;
541
542   parent_class = g_type_class_peek_parent (klass);
543
544   gobject_class->dispose = gst_qtdemux_dispose;
545
546   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
547 #if 0
548   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
549   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
550 #endif
551
552   gst_tag_register_musicbrainz_tags ();
553
554   gst_element_class_add_pad_template (gstelement_class,
555       gst_static_pad_template_get (&gst_qtdemux_sink_template));
556   gst_element_class_add_pad_template (gstelement_class,
557       gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
558   gst_element_class_add_pad_template (gstelement_class,
559       gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
560   gst_element_class_add_pad_template (gstelement_class,
561       gst_static_pad_template_get (&gst_qtdemux_subsrc_template));
562   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
563       "Codec/Demuxer",
564       "Demultiplex a QuickTime file into audio and video streams",
565       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
566
567   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
568
569 }
570
571 static void
572 gst_qtdemux_init (GstQTDemux * qtdemux)
573 {
574   qtdemux->sinkpad =
575       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
576   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
577   gst_pad_set_activatemode_function (qtdemux->sinkpad,
578       qtdemux_sink_activate_mode);
579   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
580   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
581   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
582
583   qtdemux->state = QTDEMUX_STATE_INITIAL;
584   qtdemux->pullbased = FALSE;
585   qtdemux->posted_redirect = FALSE;
586   qtdemux->neededbytes = 16;
587   qtdemux->todrop = 0;
588   qtdemux->adapter = gst_adapter_new ();
589   qtdemux->offset = 0;
590   qtdemux->first_mdat = -1;
591   qtdemux->got_moov = FALSE;
592   qtdemux->mdatoffset = -1;
593   qtdemux->mdatbuffer = NULL;
594   qtdemux->restoredata_buffer = NULL;
595   qtdemux->restoredata_offset = -1;
596   qtdemux->fragment_start = -1;
597   qtdemux->fragment_start_offset = -1;
598   qtdemux->media_caps = NULL;
599   qtdemux->exposed = FALSE;
600   qtdemux->mss_mode = FALSE;
601   qtdemux->pending_newsegment = NULL;
602   qtdemux->upstream_format_is_time = FALSE;
603   qtdemux->have_group_id = FALSE;
604   qtdemux->group_id = G_MAXUINT;
605   qtdemux->cenc_aux_info_offset = 0;
606   qtdemux->cenc_aux_info_sizes = NULL;
607   qtdemux->cenc_aux_sample_count = 0;
608   qtdemux->protection_system_ids = NULL;
609   g_queue_init (&qtdemux->protection_event_queue);
610   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
611   qtdemux->flowcombiner = gst_flow_combiner_new ();
612
613   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
614 }
615
616 static void
617 gst_qtdemux_dispose (GObject * object)
618 {
619   GstQTDemux *qtdemux = GST_QTDEMUX (object);
620
621   if (qtdemux->adapter) {
622     g_object_unref (G_OBJECT (qtdemux->adapter));
623     qtdemux->adapter = NULL;
624   }
625   gst_flow_combiner_free (qtdemux->flowcombiner);
626   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
627       NULL);
628   g_queue_clear (&qtdemux->protection_event_queue);
629
630   g_free (qtdemux->cenc_aux_info_sizes);
631   qtdemux->cenc_aux_info_sizes = NULL;
632
633   G_OBJECT_CLASS (parent_class)->dispose (object);
634 }
635
636 static void
637 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
638 {
639   if (qtdemux->posted_redirect) {
640     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
641         (_("This file contains no playable streams.")),
642         ("no known streams found, a redirect message has been posted"));
643   } else {
644     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
645         (_("This file contains no playable streams.")),
646         ("no known streams found"));
647   }
648 }
649
650 static GstBuffer *
651 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
652 {
653   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
654       mem, size, 0, size, mem, free_func);
655 }
656
657 static GstFlowReturn
658 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
659     GstBuffer ** buf)
660 {
661   GstFlowReturn flow;
662   GstMapInfo map;
663   gsize bsize;
664
665   if (G_UNLIKELY (size == 0)) {
666     GstFlowReturn ret;
667     GstBuffer *tmp = NULL;
668
669     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
670     if (ret != GST_FLOW_OK)
671       return ret;
672
673     gst_buffer_map (tmp, &map, GST_MAP_READ);
674     size = QT_UINT32 (map.data);
675     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
676
677     gst_buffer_unmap (tmp, &map);
678     gst_buffer_unref (tmp);
679   }
680
681   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
682   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
683     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
684       /* we're pulling header but already got most interesting bits,
685        * so never mind the rest (e.g. tags) (that much) */
686       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
687           size);
688       return GST_FLOW_EOS;
689     } else {
690       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
691           (_("This file is invalid and cannot be played.")),
692           ("atom has bogus size %" G_GUINT64_FORMAT, size));
693       return GST_FLOW_ERROR;
694     }
695   }
696
697   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
698
699   if (G_UNLIKELY (flow != GST_FLOW_OK))
700     return flow;
701
702   bsize = gst_buffer_get_size (*buf);
703   /* Catch short reads - we don't want any partial atoms */
704   if (G_UNLIKELY (bsize < size)) {
705     GST_WARNING_OBJECT (qtdemux,
706         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
707     gst_buffer_unref (*buf);
708     *buf = NULL;
709     return GST_FLOW_EOS;
710   }
711
712   return flow;
713 }
714
715 #if 1
716 static gboolean
717 gst_qtdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
718     GstFormat dest_format, gint64 * dest_value)
719 {
720   gboolean res = TRUE;
721   QtDemuxStream *stream = gst_pad_get_element_private (pad);
722   GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
723   gint32 index;
724
725   if (stream->subtype != FOURCC_vide) {
726     res = FALSE;
727     goto done;
728   }
729
730   switch (src_format) {
731     case GST_FORMAT_TIME:
732       switch (dest_format) {
733         case GST_FORMAT_BYTES:{
734           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
735           if (-1 == index)
736             return FALSE;
737
738           *dest_value = stream->samples[index].offset;
739
740           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
741               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
742               GST_TIME_ARGS (src_value), *dest_value);
743           break;
744         }
745         default:
746           res = FALSE;
747           break;
748       }
749       break;
750     case GST_FORMAT_BYTES:
751       switch (dest_format) {
752         case GST_FORMAT_TIME:{
753           index =
754               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
755               stream, src_value);
756
757           if (-1 == index)
758             return FALSE;
759
760           *dest_value =
761               QTSTREAMTIME_TO_GSTTIME (stream,
762               stream->samples[index].timestamp);
763           GST_DEBUG_OBJECT (qtdemux,
764               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
765               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
766           break;
767         }
768         default:
769           res = FALSE;
770           break;
771       }
772       break;
773     default:
774       res = FALSE;
775   }
776
777 done:
778   gst_object_unref (qtdemux);
779
780   return res;
781 }
782 #endif
783
784 static gboolean
785 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
786 {
787   gboolean res = TRUE;
788
789   *duration = GST_CLOCK_TIME_NONE;
790
791   if (qtdemux->duration != 0) {
792     if (qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
793       *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
794     }
795   }
796   return res;
797 }
798
799 static gboolean
800 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
801     GstQuery * query)
802 {
803   gboolean res = FALSE;
804   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
805
806   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
807
808   switch (GST_QUERY_TYPE (query)) {
809     case GST_QUERY_POSITION:{
810       GstFormat fmt;
811
812       gst_query_parse_position (query, &fmt, NULL);
813       if (fmt == GST_FORMAT_TIME
814           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
815         gst_query_set_position (query, GST_FORMAT_TIME,
816             qtdemux->segment.position);
817         res = TRUE;
818       }
819     }
820       break;
821     case GST_QUERY_DURATION:{
822       GstFormat fmt;
823
824       gst_query_parse_duration (query, &fmt, NULL);
825       if (fmt == GST_FORMAT_TIME) {
826         /* First try to query upstream */
827         res = gst_pad_query_default (pad, parent, query);
828         if (!res) {
829           guint64 duration;
830           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
831             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
832             res = TRUE;
833           }
834         }
835       }
836       break;
837     }
838     case GST_QUERY_CONVERT:{
839       GstFormat src_fmt, dest_fmt;
840       gint64 src_value, dest_value = 0;
841
842       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
843
844       res = gst_qtdemux_src_convert (pad,
845           src_fmt, src_value, dest_fmt, &dest_value);
846       if (res) {
847         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
848         res = TRUE;
849       }
850       break;
851     }
852     case GST_QUERY_FORMATS:
853       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
854       res = TRUE;
855       break;
856     case GST_QUERY_SEEKING:{
857       GstFormat fmt;
858       gboolean seekable;
859
860       /* try upstream first */
861       res = gst_pad_query_default (pad, parent, query);
862
863       if (!res) {
864         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
865         if (fmt == GST_FORMAT_TIME) {
866           GstClockTime duration = GST_CLOCK_TIME_NONE;
867
868           gst_qtdemux_get_duration (qtdemux, &duration);
869           seekable = TRUE;
870           if (!qtdemux->pullbased) {
871             GstQuery *q;
872
873             /* we might be able with help from upstream */
874             seekable = FALSE;
875             q = gst_query_new_seeking (GST_FORMAT_BYTES);
876             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
877               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
878               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
879             }
880             gst_query_unref (q);
881           }
882           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
883           res = TRUE;
884         }
885       }
886       break;
887     }
888     case GST_QUERY_SEGMENT:
889     {
890       GstFormat format;
891       gint64 start, stop;
892
893       format = qtdemux->segment.format;
894
895       start =
896           gst_segment_to_stream_time (&qtdemux->segment, format,
897           qtdemux->segment.start);
898       if ((stop = qtdemux->segment.stop) == -1)
899         stop = qtdemux->segment.duration;
900       else
901         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
902
903       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
904       res = TRUE;
905       break;
906     }
907     default:
908       res = gst_pad_query_default (pad, parent, query);
909       break;
910   }
911
912   return res;
913 }
914
915 static void
916 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
917 {
918   if (G_LIKELY (stream->pad)) {
919     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
920         GST_DEBUG_PAD_NAME (stream->pad));
921
922     if (G_UNLIKELY (stream->pending_tags)) {
923       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
924           stream->pending_tags);
925       gst_pad_push_event (stream->pad,
926           gst_event_new_tag (stream->pending_tags));
927       stream->pending_tags = NULL;
928     }
929
930     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
931       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
932           qtdemux->tag_list);
933       gst_pad_push_event (stream->pad,
934           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
935       stream->send_global_tags = FALSE;
936     }
937   }
938 }
939
940 /* push event on all source pads; takes ownership of the event */
941 static void
942 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
943 {
944   guint n;
945   gboolean has_valid_stream = FALSE;
946   GstEventType etype = GST_EVENT_TYPE (event);
947
948   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
949       GST_EVENT_TYPE_NAME (event));
950
951   for (n = 0; n < qtdemux->n_streams; n++) {
952     GstPad *pad;
953     QtDemuxStream *stream = qtdemux->streams[n];
954     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
955
956     if ((pad = stream->pad)) {
957       has_valid_stream = TRUE;
958
959       if (etype == GST_EVENT_EOS) {
960         /* let's not send twice */
961         if (stream->sent_eos)
962           continue;
963         stream->sent_eos = TRUE;
964       }
965
966       gst_pad_push_event (pad, gst_event_ref (event));
967     }
968   }
969
970   gst_event_unref (event);
971
972   /* if it is EOS and there are no pads, post an error */
973   if (!has_valid_stream && etype == GST_EVENT_EOS) {
974     gst_qtdemux_post_no_playable_stream_error (qtdemux);
975   }
976 }
977
978 /* push a pending newsegment event, if any from the streaming thread */
979 static void
980 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
981 {
982   if (qtdemux->pending_newsegment) {
983     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
984     qtdemux->pending_newsegment = NULL;
985   }
986 }
987
988 typedef struct
989 {
990   guint64 media_time;
991 } FindData;
992
993 static gint
994 find_func (QtDemuxSample * s1, guint64 * media_time, gpointer user_data)
995 {
996   if (s1->timestamp + s1->pts_offset > *media_time)
997     return 1;
998
999   return -1;
1000 }
1001
1002 /* find the index of the sample that includes the data for @media_time using a
1003  * binary search.  Only to be called in optimized cases of linear search below.
1004  *
1005  * Returns the index of the sample.
1006  */
1007 static guint32
1008 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1009     guint64 media_time)
1010 {
1011   QtDemuxSample *result;
1012   guint32 index;
1013
1014   /* convert media_time to mov format */
1015   media_time =
1016       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1017
1018   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1019       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1020       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1021
1022   if (G_LIKELY (result))
1023     index = result - str->samples;
1024   else
1025     index = 0;
1026
1027   return index;
1028 }
1029
1030
1031
1032 /* find the index of the sample that includes the data for @media_offset using a
1033  * linear search
1034  *
1035  * Returns the index of the sample.
1036  */
1037 static guint32
1038 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1039     QtDemuxStream * str, gint64 media_offset)
1040 {
1041   QtDemuxSample *result = str->samples;
1042   guint32 index = 0;
1043
1044   if (result == NULL || str->n_samples == 0)
1045     return -1;
1046
1047   if (media_offset == result->offset)
1048     return index;
1049
1050   result++;
1051   while (index < str->n_samples - 1) {
1052     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1053       goto parse_failed;
1054
1055     if (media_offset < result->offset)
1056       break;
1057
1058     index++;
1059     result++;
1060   }
1061   return index;
1062
1063   /* ERRORS */
1064 parse_failed:
1065   {
1066     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1067     return -1;
1068   }
1069 }
1070
1071 /* find the index of the sample that includes the data for @media_time using a
1072  * linear search, and keeping in mind that not all samples may have been parsed
1073  * yet.  If possible, it will delegate to binary search.
1074  *
1075  * Returns the index of the sample.
1076  */
1077 static guint32
1078 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1079     GstClockTime media_time)
1080 {
1081   guint32 index = 0;
1082   guint64 mov_time;
1083   QtDemuxSample *sample;
1084
1085   /* convert media_time to mov format */
1086   mov_time =
1087       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1088
1089   sample = str->samples;
1090   if (mov_time == sample->timestamp + sample->pts_offset)
1091     return index;
1092
1093   /* use faster search if requested time in already parsed range */
1094   sample = str->samples + str->stbl_index;
1095   if (str->stbl_index >= 0 &&
1096       mov_time <= (sample->timestamp + sample->pts_offset))
1097     return gst_qtdemux_find_index (qtdemux, str, media_time);
1098
1099   while (index < str->n_samples - 1) {
1100     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1101       goto parse_failed;
1102
1103     sample = str->samples + index + 1;
1104     if (mov_time < (sample->timestamp + sample->pts_offset))
1105       break;
1106
1107     index++;
1108   }
1109   return index;
1110
1111   /* ERRORS */
1112 parse_failed:
1113   {
1114     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1115     return -1;
1116   }
1117 }
1118
1119 /* find the index of the keyframe needed to decode the sample at @index
1120  * of stream @str.
1121  *
1122  * Returns the index of the keyframe.
1123  */
1124 static guint32
1125 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1126     guint32 index)
1127 {
1128   guint32 new_index = index;
1129
1130   if (index >= str->n_samples) {
1131     new_index = str->n_samples;
1132     goto beach;
1133   }
1134
1135   /* all keyframes, return index */
1136   if (str->all_keyframe) {
1137     new_index = index;
1138     goto beach;
1139   }
1140
1141   /* else go back until we have a keyframe */
1142   while (TRUE) {
1143     if (str->samples[new_index].keyframe)
1144       break;
1145
1146     if (new_index == 0)
1147       break;
1148
1149     new_index--;
1150   }
1151
1152 beach:
1153   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1154       "gave %u", index, new_index);
1155
1156   return new_index;
1157 }
1158
1159 /* find the segment for @time_position for @stream
1160  *
1161  * Returns the index of the segment containing @time_position.
1162  * Returns the last segment and sets the @eos variable to TRUE
1163  * if the time is beyond the end. @eos may be NULL
1164  */
1165 static guint32
1166 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1167     GstClockTime time_position)
1168 {
1169   gint i;
1170   guint32 seg_idx;
1171
1172   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1173       GST_TIME_ARGS (time_position));
1174
1175   seg_idx = -1;
1176   for (i = 0; i < stream->n_segments; i++) {
1177     QtDemuxSegment *segment = &stream->segments[i];
1178
1179     GST_LOG_OBJECT (stream->pad,
1180         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1181         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1182
1183     /* For the last segment we include stop_time in the last segment */
1184     if (i < stream->n_segments - 1) {
1185       if (segment->time <= time_position && time_position < segment->stop_time) {
1186         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1187         seg_idx = i;
1188         break;
1189       }
1190     } else {
1191       /* Last segment always matches */
1192       seg_idx = i;
1193       break;
1194     }
1195   }
1196   return seg_idx;
1197 }
1198
1199 /* move the stream @str to the sample position @index.
1200  *
1201  * Updates @str->sample_index and marks discontinuity if needed.
1202  */
1203 static void
1204 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1205     guint32 index)
1206 {
1207   /* no change needed */
1208   if (index == str->sample_index)
1209     return;
1210
1211   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1212       str->n_samples);
1213
1214   /* position changed, we have a discont */
1215   str->sample_index = index;
1216   str->offset_in_sample = 0;
1217   /* Each time we move in the stream we store the position where we are
1218    * starting from */
1219   str->from_sample = index;
1220   str->discont = TRUE;
1221 }
1222
1223 static void
1224 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1225     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1226 {
1227   guint64 min_offset;
1228   gint64 min_byte_offset = -1;
1229   gint n;
1230
1231   min_offset = desired_time;
1232
1233   /* for each stream, find the index of the sample in the segment
1234    * and move back to the previous keyframe. */
1235   for (n = 0; n < qtdemux->n_streams; n++) {
1236     QtDemuxStream *str;
1237     guint32 index, kindex;
1238     guint32 seg_idx;
1239     GstClockTime media_start;
1240     GstClockTime media_time;
1241     GstClockTime seg_time;
1242     QtDemuxSegment *seg;
1243     gboolean empty_segment = FALSE;
1244
1245     str = qtdemux->streams[n];
1246
1247     if (str->sparse && !use_sparse)
1248       continue;
1249
1250     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1251     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1252
1253     /* get segment and time in the segment */
1254     seg = &str->segments[seg_idx];
1255     seg_time = desired_time - seg->time;
1256
1257     while (QTSEGMENT_IS_EMPTY (seg)) {
1258       seg_time = 0;
1259       empty_segment = TRUE;
1260       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1261           seg_idx);
1262       seg_idx++;
1263       if (seg_idx == str->n_segments)
1264         break;
1265       seg = &str->segments[seg_idx];
1266     }
1267
1268     if (seg_idx == str->n_segments) {
1269       /* FIXME track shouldn't have the last segment as empty, but if it
1270        * happens we better handle it */
1271       continue;
1272     }
1273
1274     /* get the media time in the segment */
1275     media_start = seg->media_start + seg_time;
1276
1277     /* get the index of the sample with media time */
1278     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1279     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1280         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1281         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1282         empty_segment);
1283
1284     if (!empty_segment) {
1285       /* find previous keyframe */
1286       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1287
1288       /* if the keyframe is at a different position, we need to update the
1289        * requested seek time */
1290       if (index != kindex) {
1291         index = kindex;
1292
1293         /* get timestamp of keyframe */
1294         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1295         GST_DEBUG_OBJECT (qtdemux,
1296             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1297             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1298             str->samples[kindex].offset);
1299
1300         /* keyframes in the segment get a chance to change the
1301          * desired_offset. keyframes out of the segment are
1302          * ignored. */
1303         if (media_time >= seg->media_start) {
1304           GstClockTime seg_time;
1305
1306           /* this keyframe is inside the segment, convert back to
1307            * segment time */
1308           seg_time = (media_time - seg->media_start) + seg->time;
1309           if (seg_time < min_offset)
1310             min_offset = seg_time;
1311         }
1312       }
1313     }
1314
1315     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1316       min_byte_offset = str->samples[index].offset;
1317   }
1318
1319   if (key_time)
1320     *key_time = min_offset;
1321   if (key_offset)
1322     *key_offset = min_byte_offset;
1323 }
1324
1325 static gboolean
1326 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1327     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1328 {
1329   gboolean res;
1330
1331   g_return_val_if_fail (format != NULL, FALSE);
1332   g_return_val_if_fail (cur != NULL, FALSE);
1333   g_return_val_if_fail (stop != NULL, FALSE);
1334
1335   if (*format == GST_FORMAT_TIME)
1336     return TRUE;
1337
1338   res = TRUE;
1339   if (cur_type != GST_SEEK_TYPE_NONE)
1340     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1341   if (res && stop_type != GST_SEEK_TYPE_NONE)
1342     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1343
1344   if (res)
1345     *format = GST_FORMAT_TIME;
1346
1347   return res;
1348 }
1349
1350 /* perform seek in push based mode:
1351    find BYTE position to move to based on time and delegate to upstream
1352 */
1353 static gboolean
1354 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1355 {
1356   gdouble rate;
1357   GstFormat format;
1358   GstSeekFlags flags;
1359   GstSeekType cur_type, stop_type;
1360   gint64 cur, stop, key_cur;
1361   gboolean res;
1362   gint64 byte_cur;
1363   gint64 original_stop;
1364   guint32 seqnum;
1365
1366   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1367
1368   gst_event_parse_seek (event, &rate, &format, &flags,
1369       &cur_type, &cur, &stop_type, &stop);
1370   seqnum = gst_event_get_seqnum (event);
1371
1372   /* only forward streaming and seeking is possible */
1373   if (rate <= 0)
1374     goto unsupported_seek;
1375
1376   /* convert to TIME if needed and possible */
1377   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1378           stop_type, &stop))
1379     goto no_format;
1380
1381   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1382    * the original stop position to use when upstream pushes the new segment
1383    * for this seek */
1384   original_stop = stop;
1385   stop = -1;
1386
1387   /* find reasonable corresponding BYTE position,
1388    * also try to mind about keyframes, since we can not go back a bit for them
1389    * later on */
1390   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1391
1392   if (byte_cur == -1)
1393     goto abort_seek;
1394
1395   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1396       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1397       stop);
1398
1399   GST_OBJECT_LOCK (qtdemux);
1400   qtdemux->seek_offset = byte_cur;
1401   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1402     qtdemux->push_seek_start = cur;
1403   } else {
1404     qtdemux->push_seek_start = key_cur;
1405   }
1406
1407   if (stop_type == GST_SEEK_TYPE_NONE) {
1408     qtdemux->push_seek_stop = qtdemux->segment.stop;
1409   } else {
1410     qtdemux->push_seek_stop = original_stop;
1411   }
1412   GST_OBJECT_UNLOCK (qtdemux);
1413
1414   /* BYTE seek event */
1415   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1416       stop_type, stop);
1417   gst_event_set_seqnum (event, seqnum);
1418   res = gst_pad_push_event (qtdemux->sinkpad, event);
1419
1420   return res;
1421
1422   /* ERRORS */
1423 abort_seek:
1424   {
1425     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1426         "seek aborted.");
1427     return FALSE;
1428   }
1429 unsupported_seek:
1430   {
1431     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1432     return FALSE;
1433   }
1434 no_format:
1435   {
1436     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1437     return FALSE;
1438   }
1439 }
1440
1441 /* perform the seek.
1442  *
1443  * We set all segment_indexes in the streams to unknown and
1444  * adjust the time_position to the desired position. this is enough
1445  * to trigger a segment switch in the streaming thread to start
1446  * streaming from the desired position.
1447  *
1448  * Keyframe seeking is a little more complicated when dealing with
1449  * segments. Ideally we want to move to the previous keyframe in
1450  * the segment but there might not be a keyframe in the segment. In
1451  * fact, none of the segments could contain a keyframe. We take a
1452  * practical approach: seek to the previous keyframe in the segment,
1453  * if there is none, seek to the beginning of the segment.
1454  *
1455  * Called with STREAM_LOCK
1456  */
1457 static gboolean
1458 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1459     guint32 seqnum, GstSeekFlags flags)
1460 {
1461   gint64 desired_offset;
1462   gint n;
1463
1464   desired_offset = segment->position;
1465
1466   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1467       GST_TIME_ARGS (desired_offset));
1468
1469   /* may not have enough fragmented info to do this adjustment,
1470    * and we can't scan (and probably should not) at this time with
1471    * possibly flushing upstream */
1472   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1473     gint64 min_offset;
1474
1475     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1476     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1477         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1478     desired_offset = min_offset;
1479   }
1480
1481   /* and set all streams to the final position */
1482   gst_flow_combiner_reset (qtdemux->flowcombiner);
1483   for (n = 0; n < qtdemux->n_streams; n++) {
1484     QtDemuxStream *stream = qtdemux->streams[n];
1485
1486     stream->time_position = desired_offset;
1487     stream->accumulated_base = 0;
1488     stream->sample_index = -1;
1489     stream->offset_in_sample = 0;
1490     stream->segment_index = -1;
1491     stream->sent_eos = FALSE;
1492     stream->segment_seqnum = seqnum;
1493
1494     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1495       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1496   }
1497   segment->position = desired_offset;
1498   segment->time = desired_offset;
1499   if (segment->rate >= 0) {
1500     segment->start = desired_offset;
1501
1502     /* we stop at the end */
1503     if (segment->stop == -1)
1504       segment->stop = segment->duration;
1505   } else {
1506     segment->stop = desired_offset;
1507   }
1508
1509   if (qtdemux->fragmented)
1510     qtdemux->fragmented_seek_pending = TRUE;
1511
1512   return TRUE;
1513 }
1514
1515 /* do a seek in pull based mode */
1516 static gboolean
1517 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1518 {
1519   gdouble rate;
1520   GstFormat format;
1521   GstSeekFlags flags;
1522   GstSeekType cur_type, stop_type;
1523   gint64 cur, stop;
1524   gboolean flush;
1525   gboolean update;
1526   GstSegment seeksegment;
1527   guint32 seqnum = 0;
1528   GstEvent *flush_event;
1529
1530   if (event) {
1531     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1532
1533     gst_event_parse_seek (event, &rate, &format, &flags,
1534         &cur_type, &cur, &stop_type, &stop);
1535     seqnum = gst_event_get_seqnum (event);
1536
1537     /* we have to have a format as the segment format. Try to convert
1538      * if not. */
1539     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1540             stop_type, &stop))
1541       goto no_format;
1542
1543     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1544   } else {
1545     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1546     flags = 0;
1547   }
1548
1549   flush = flags & GST_SEEK_FLAG_FLUSH;
1550
1551   /* stop streaming, either by flushing or by pausing the task */
1552   if (flush) {
1553     flush_event = gst_event_new_flush_start ();
1554     if (seqnum)
1555       gst_event_set_seqnum (flush_event, seqnum);
1556     /* unlock upstream pull_range */
1557     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1558     /* make sure out loop function exits */
1559     gst_qtdemux_push_event (qtdemux, flush_event);
1560   } else {
1561     /* non flushing seek, pause the task */
1562     gst_pad_pause_task (qtdemux->sinkpad);
1563   }
1564
1565   /* wait for streaming to finish */
1566   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1567
1568   /* copy segment, we need this because we still need the old
1569    * segment when we close the current segment. */
1570   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1571
1572   if (event) {
1573     /* configure the segment with the seek variables */
1574     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1575     gst_segment_do_seek (&seeksegment, rate, format, flags,
1576         cur_type, cur, stop_type, stop, &update);
1577   }
1578
1579   /* now do the seek, this actually never returns FALSE */
1580   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1581
1582   /* prepare for streaming again */
1583   if (flush) {
1584     flush_event = gst_event_new_flush_stop (TRUE);
1585     if (seqnum)
1586       gst_event_set_seqnum (flush_event, seqnum);
1587
1588     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1589     gst_qtdemux_push_event (qtdemux, flush_event);
1590   }
1591
1592   /* commit the new segment */
1593   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1594
1595   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1596     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1597         qtdemux->segment.format, qtdemux->segment.position);
1598     if (seqnum)
1599       gst_message_set_seqnum (msg, seqnum);
1600     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1601   }
1602
1603   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1604   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1605       qtdemux->sinkpad, NULL);
1606
1607   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1608
1609   return TRUE;
1610
1611   /* ERRORS */
1612 no_format:
1613   {
1614     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1615     return FALSE;
1616   }
1617 }
1618
1619 static gboolean
1620 qtdemux_ensure_index (GstQTDemux * qtdemux)
1621 {
1622   guint i;
1623
1624   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1625
1626   /* Build complete index */
1627   for (i = 0; i < qtdemux->n_streams; i++) {
1628     QtDemuxStream *stream = qtdemux->streams[i];
1629
1630     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1631       goto parse_error;
1632   }
1633   return TRUE;
1634
1635   /* ERRORS */
1636 parse_error:
1637   {
1638     GST_LOG_OBJECT (qtdemux,
1639         "Building complete index of stream %u for seeking failed!", i);
1640     return FALSE;
1641   }
1642 }
1643
1644 static gboolean
1645 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1646     GstEvent * event)
1647 {
1648   gboolean res = TRUE;
1649   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1650
1651   switch (GST_EVENT_TYPE (event)) {
1652     case GST_EVENT_SEEK:
1653     {
1654 #ifndef GST_DISABLE_GST_DEBUG
1655       GstClockTime ts = gst_util_get_timestamp ();
1656 #endif
1657
1658       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1659         /* seek should be handled by upstream, we might need to re-download fragments */
1660         GST_DEBUG_OBJECT (qtdemux,
1661             "let upstream handle seek for fragmented playback");
1662         goto upstream;
1663       }
1664
1665       /* Build complete index for seeking;
1666        * if not a fragmented file at least */
1667       if (!qtdemux->fragmented)
1668         if (!qtdemux_ensure_index (qtdemux))
1669           goto index_failed;
1670 #ifndef GST_DISABLE_GST_DEBUG
1671       ts = gst_util_get_timestamp () - ts;
1672       GST_INFO_OBJECT (qtdemux,
1673           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1674 #endif
1675     }
1676       if (qtdemux->pullbased) {
1677         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1678       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1679         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1680         res = TRUE;
1681       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1682           && !qtdemux->fragmented) {
1683         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1684       } else {
1685         GST_DEBUG_OBJECT (qtdemux,
1686             "ignoring seek in push mode in current state");
1687         res = FALSE;
1688       }
1689       gst_event_unref (event);
1690       break;
1691     case GST_EVENT_QOS:
1692     case GST_EVENT_NAVIGATION:
1693       res = FALSE;
1694       gst_event_unref (event);
1695       break;
1696     default:
1697     upstream:
1698       res = gst_pad_event_default (pad, parent, event);
1699       break;
1700   }
1701
1702 done:
1703   return res;
1704
1705   /* ERRORS */
1706 index_failed:
1707   {
1708     GST_ERROR_OBJECT (qtdemux, "Index failed");
1709     gst_event_unref (event);
1710     res = FALSE;
1711     goto done;
1712   }
1713 }
1714
1715 /* stream/index return sample that is min/max w.r.t. byte position,
1716  * time is min/max w.r.t. time of samples,
1717  * the latter need not be time of the former sample */
1718 static void
1719 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1720     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1721 {
1722   gint i, n, index;
1723   gint64 time, min_time;
1724   QtDemuxStream *stream;
1725
1726   min_time = -1;
1727   stream = NULL;
1728   index = -1;
1729
1730   for (n = 0; n < qtdemux->n_streams; ++n) {
1731     QtDemuxStream *str;
1732     gint inc;
1733     gboolean set_sample;
1734
1735     str = qtdemux->streams[n];
1736     set_sample = !set;
1737
1738     if (fw) {
1739       i = 0;
1740       inc = 1;
1741     } else {
1742       i = str->n_samples - 1;
1743       inc = -1;
1744     }
1745
1746     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1747       if (str->samples[i].size == 0)
1748         continue;
1749
1750       if (fw && (str->samples[i].offset < byte_pos))
1751         continue;
1752
1753       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1754         continue;
1755
1756       /* move stream to first available sample */
1757       if (set) {
1758         gst_qtdemux_move_stream (qtdemux, str, i);
1759         set_sample = TRUE;
1760       }
1761
1762       /* avoid index from sparse streams since they might be far away */
1763       if (!str->sparse) {
1764         /* determine min/max time */
1765         time = QTSAMPLE_PTS (str, &str->samples[i]);
1766         if (min_time == -1 || (!fw && time > min_time) ||
1767             (fw && time < min_time)) {
1768           min_time = time;
1769         }
1770
1771         /* determine stream with leading sample, to get its position */
1772         if (!stream ||
1773             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1774             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1775           stream = str;
1776           index = i;
1777         }
1778       }
1779       break;
1780     }
1781
1782     /* no sample for this stream, mark eos */
1783     if (!set_sample)
1784       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1785   }
1786
1787   if (_time)
1788     *_time = min_time;
1789   if (_stream)
1790     *_stream = stream;
1791   if (_index)
1792     *_index = index;
1793 }
1794
1795 static QtDemuxStream *
1796 _create_stream (void)
1797 {
1798   QtDemuxStream *stream;
1799
1800   stream = g_new0 (QtDemuxStream, 1);
1801   /* new streams always need a discont */
1802   stream->discont = TRUE;
1803   /* we enable clipping for raw audio/video streams */
1804   stream->need_clip = FALSE;
1805   stream->need_process = FALSE;
1806   stream->segment_index = -1;
1807   stream->time_position = 0;
1808   stream->sample_index = -1;
1809   stream->offset_in_sample = 0;
1810   stream->new_stream = TRUE;
1811   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1812   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1813   stream->protected = FALSE;
1814   stream->protection_scheme_type = 0;
1815   stream->protection_scheme_version = 0;
1816   stream->protection_scheme_info = NULL;
1817   g_queue_init (&stream->protection_scheme_event_queue);
1818   return stream;
1819 }
1820
1821 static gboolean
1822 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1823 {
1824   GstStructure *structure;
1825   const gchar *variant;
1826   const GstCaps *mediacaps = NULL;
1827
1828   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1829
1830   structure = gst_caps_get_structure (caps, 0);
1831   variant = gst_structure_get_string (structure, "variant");
1832
1833   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1834     QtDemuxStream *stream;
1835     const GValue *value;
1836
1837     demux->fragmented = TRUE;
1838     demux->mss_mode = TRUE;
1839
1840     if (demux->n_streams > 1) {
1841       /* can't do this, we can only renegotiate for another mss format */
1842       return FALSE;
1843     }
1844
1845     value = gst_structure_get_value (structure, "media-caps");
1846     /* create stream */
1847     if (value) {
1848       const GValue *timescale_v;
1849
1850       /* TODO update when stream changes during playback */
1851
1852       if (demux->n_streams == 0) {
1853         stream = _create_stream ();
1854         demux->streams[demux->n_streams] = stream;
1855         demux->n_streams = 1;
1856       } else {
1857         stream = demux->streams[0];
1858       }
1859
1860       timescale_v = gst_structure_get_value (structure, "timescale");
1861       if (timescale_v) {
1862         stream->timescale = g_value_get_uint64 (timescale_v);
1863       } else {
1864         /* default mss timescale */
1865         stream->timescale = 10000000;
1866       }
1867       demux->timescale = stream->timescale;
1868
1869       mediacaps = gst_value_get_caps (value);
1870       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1871         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1872             mediacaps);
1873         stream->new_caps = TRUE;
1874       }
1875       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1876       structure = gst_caps_get_structure (mediacaps, 0);
1877       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1878         stream->subtype = FOURCC_vide;
1879
1880         gst_structure_get_int (structure, "width", &stream->width);
1881         gst_structure_get_int (structure, "height", &stream->height);
1882         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1883             &stream->fps_d);
1884       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1885         gint rate = 0;
1886         stream->subtype = FOURCC_soun;
1887         gst_structure_get_int (structure, "channels", &stream->n_channels);
1888         gst_structure_get_int (structure, "rate", &rate);
1889         stream->rate = rate;
1890       }
1891     }
1892     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1893   } else {
1894     demux->mss_mode = FALSE;
1895   }
1896
1897   return TRUE;
1898 }
1899
1900 static void
1901 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1902 {
1903   gint n;
1904
1905   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1906   gst_pad_stop_task (qtdemux->sinkpad);
1907
1908   if (hard || qtdemux->upstream_format_is_time) {
1909     qtdemux->state = QTDEMUX_STATE_INITIAL;
1910     qtdemux->neededbytes = 16;
1911     qtdemux->todrop = 0;
1912     qtdemux->pullbased = FALSE;
1913     qtdemux->posted_redirect = FALSE;
1914     qtdemux->first_mdat = -1;
1915     qtdemux->header_size = 0;
1916     qtdemux->mdatoffset = -1;
1917     qtdemux->restoredata_offset = -1;
1918     if (qtdemux->mdatbuffer)
1919       gst_buffer_unref (qtdemux->mdatbuffer);
1920     if (qtdemux->restoredata_buffer)
1921       gst_buffer_unref (qtdemux->restoredata_buffer);
1922     qtdemux->mdatbuffer = NULL;
1923     qtdemux->restoredata_buffer = NULL;
1924     qtdemux->mdatleft = 0;
1925     if (qtdemux->comp_brands)
1926       gst_buffer_unref (qtdemux->comp_brands);
1927     qtdemux->comp_brands = NULL;
1928     qtdemux->last_moov_offset = -1;
1929     if (qtdemux->moov_node)
1930       g_node_destroy (qtdemux->moov_node);
1931     qtdemux->moov_node = NULL;
1932     qtdemux->moov_node_compressed = NULL;
1933     if (qtdemux->tag_list)
1934       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1935     qtdemux->tag_list = NULL;
1936 #if 0
1937     if (qtdemux->element_index)
1938       gst_object_unref (qtdemux->element_index);
1939     qtdemux->element_index = NULL;
1940 #endif
1941     qtdemux->major_brand = 0;
1942     if (qtdemux->pending_newsegment)
1943       gst_event_unref (qtdemux->pending_newsegment);
1944     qtdemux->pending_newsegment = NULL;
1945     qtdemux->upstream_format_is_time = FALSE;
1946     qtdemux->upstream_seekable = FALSE;
1947     qtdemux->upstream_size = 0;
1948
1949     qtdemux->fragment_start = -1;
1950     qtdemux->fragment_start_offset = -1;
1951     qtdemux->duration = 0;
1952     qtdemux->moof_offset = 0;
1953     qtdemux->chapters_track_id = 0;
1954     qtdemux->have_group_id = FALSE;
1955     qtdemux->group_id = G_MAXUINT;
1956
1957     if (qtdemux->protection_system_ids) {
1958       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
1959       qtdemux->protection_system_ids = NULL;
1960     }
1961     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1962         NULL);
1963     g_queue_clear (&qtdemux->protection_event_queue);
1964   }
1965   qtdemux->offset = 0;
1966   gst_adapter_clear (qtdemux->adapter);
1967   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1968
1969   if (hard) {
1970     for (n = 0; n < qtdemux->n_streams; n++) {
1971       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
1972       qtdemux->streams[n] = NULL;
1973     }
1974     qtdemux->n_streams = 0;
1975     qtdemux->n_video_streams = 0;
1976     qtdemux->n_audio_streams = 0;
1977     qtdemux->n_sub_streams = 0;
1978     qtdemux->exposed = FALSE;
1979     qtdemux->fragmented = FALSE;
1980     qtdemux->mss_mode = FALSE;
1981     gst_caps_replace (&qtdemux->media_caps, NULL);
1982     qtdemux->timescale = 0;
1983     qtdemux->got_moov = FALSE;
1984   } else if (qtdemux->mss_mode) {
1985     gst_flow_combiner_reset (qtdemux->flowcombiner);
1986     for (n = 0; n < qtdemux->n_streams; n++)
1987       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
1988   } else {
1989     gst_flow_combiner_reset (qtdemux->flowcombiner);
1990     for (n = 0; n < qtdemux->n_streams; n++) {
1991       qtdemux->streams[n]->sent_eos = FALSE;
1992       qtdemux->streams[n]->segment_seqnum = 0;
1993       qtdemux->streams[n]->time_position = 0;
1994       qtdemux->streams[n]->accumulated_base = 0;
1995     }
1996   }
1997 }
1998
1999 static gboolean
2000 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2001     GstEvent * event)
2002 {
2003   GstQTDemux *demux = GST_QTDEMUX (parent);
2004   gboolean res = TRUE;
2005
2006   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2007
2008   switch (GST_EVENT_TYPE (event)) {
2009     case GST_EVENT_SEGMENT:
2010     {
2011       gint64 offset = 0;
2012       QtDemuxStream *stream;
2013       gint idx;
2014       GstSegment segment;
2015       GstEvent *segment_event;
2016
2017       /* some debug output */
2018       gst_event_copy_segment (event, &segment);
2019       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2020           &segment);
2021
2022       if (segment.format == GST_FORMAT_TIME) {
2023         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2024         gst_event_replace (&demux->pending_newsegment, event);
2025         demux->upstream_format_is_time = TRUE;
2026       } else {
2027         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2028             "not in time format");
2029
2030         /* chain will send initial newsegment after pads have been added */
2031         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2032           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2033           goto exit;
2034         }
2035       }
2036
2037       /* check if this matches a time seek we received previously
2038        * FIXME for backwards compatibility reasons we use the
2039        * seek_offset here to compare. In the future we might want to
2040        * change this to use the seqnum as it uniquely should identify
2041        * the segment that corresponds to the seek. */
2042       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2043           ", received segment offset %" G_GINT64_FORMAT,
2044           demux->seek_offset, segment.start);
2045       if (segment.format == GST_FORMAT_BYTES
2046           && demux->seek_offset == segment.start) {
2047         GST_OBJECT_LOCK (demux);
2048         offset = segment.start;
2049
2050         segment.format = GST_FORMAT_TIME;
2051         segment.start = demux->push_seek_start;
2052         segment.stop = demux->push_seek_stop;
2053         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2054             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2055             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2056         GST_OBJECT_UNLOCK (demux);
2057       }
2058
2059       /* we only expect a BYTE segment, e.g. following a seek */
2060       if (segment.format == GST_FORMAT_BYTES) {
2061         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2062           offset = segment.start;
2063
2064           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2065               NULL, (gint64 *) & segment.start);
2066           if ((gint64) segment.start < 0)
2067             segment.start = 0;
2068         }
2069         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2070           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2071               NULL, (gint64 *) & segment.stop);
2072           /* keyframe seeking should already arrange for start >= stop,
2073            * but make sure in other rare cases */
2074           segment.stop = MAX (segment.stop, segment.start);
2075         }
2076       } else if (segment.format == GST_FORMAT_TIME) {
2077         /* push all data on the adapter before starting this
2078          * new segment */
2079         gst_qtdemux_process_adapter (demux, TRUE);
2080       } else {
2081         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2082         goto exit;
2083       }
2084
2085       /* accept upstream's notion of segment and distribute along */
2086       segment.format = GST_FORMAT_TIME;
2087       segment.position = segment.time = segment.start;
2088       segment.duration = demux->segment.duration;
2089       segment.base = gst_segment_to_running_time (&demux->segment,
2090           GST_FORMAT_TIME, demux->segment.position);
2091
2092       gst_segment_copy_into (&segment, &demux->segment);
2093       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2094       segment_event = gst_event_new_segment (&segment);
2095       gst_event_set_seqnum (segment_event, gst_event_get_seqnum (event));
2096       gst_qtdemux_push_event (demux, segment_event);
2097
2098       /* clear leftover in current segment, if any */
2099       gst_adapter_clear (demux->adapter);
2100
2101       /* set up streaming thread */
2102       demux->offset = offset;
2103       if (demux->upstream_format_is_time) {
2104         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2105             "set values to restart reading from a new atom");
2106         demux->neededbytes = 16;
2107         demux->todrop = 0;
2108       } else {
2109         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2110             NULL);
2111         if (stream) {
2112           demux->todrop = stream->samples[idx].offset - offset;
2113           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2114         } else {
2115           /* set up for EOS */
2116           demux->neededbytes = -1;
2117           demux->todrop = 0;
2118         }
2119       }
2120     exit:
2121       gst_event_unref (event);
2122       res = TRUE;
2123       goto drop;
2124     }
2125     case GST_EVENT_FLUSH_STOP:
2126     {
2127       guint64 dur;
2128
2129       dur = demux->segment.duration;
2130       gst_qtdemux_reset (demux, FALSE);
2131       demux->segment.duration = dur;
2132       break;
2133     }
2134     case GST_EVENT_EOS:
2135       /* If we are in push mode, and get an EOS before we've seen any streams,
2136        * then error out - we have nowhere to send the EOS */
2137       if (!demux->pullbased) {
2138         gint i;
2139         gboolean has_valid_stream = FALSE;
2140         for (i = 0; i < demux->n_streams; i++) {
2141           if (demux->streams[i]->pad != NULL) {
2142             has_valid_stream = TRUE;
2143             break;
2144           }
2145         }
2146         if (!has_valid_stream)
2147           gst_qtdemux_post_no_playable_stream_error (demux);
2148         else {
2149           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2150               (guint) gst_adapter_available (demux->adapter));
2151           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2152             res = FALSE;
2153           }
2154         }
2155       }
2156       break;
2157     case GST_EVENT_CAPS:{
2158       GstCaps *caps = NULL;
2159
2160       gst_event_parse_caps (event, &caps);
2161       gst_qtdemux_setcaps (demux, caps);
2162       res = TRUE;
2163       gst_event_unref (event);
2164       goto drop;
2165     }
2166     case GST_EVENT_PROTECTION:
2167     {
2168       const gchar *system_id = NULL;
2169
2170       gst_event_parse_protection (event, &system_id, NULL, NULL);
2171       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2172           system_id);
2173       gst_qtdemux_append_protection_system_id (demux, system_id);
2174       /* save the event for later, for source pads that have not been created */
2175       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2176       /* send it to all pads that already exist */
2177       gst_qtdemux_push_event (demux, event);
2178       res = TRUE;
2179       goto drop;
2180     }
2181     default:
2182       break;
2183   }
2184
2185   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2186
2187 drop:
2188   return res;
2189 }
2190
2191 #if 0
2192 static void
2193 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2194 {
2195   GstQTDemux *demux = GST_QTDEMUX (element);
2196
2197   GST_OBJECT_LOCK (demux);
2198   if (demux->element_index)
2199     gst_object_unref (demux->element_index);
2200   if (index) {
2201     demux->element_index = gst_object_ref (index);
2202   } else {
2203     demux->element_index = NULL;
2204   }
2205   GST_OBJECT_UNLOCK (demux);
2206   /* object lock might be taken again */
2207   if (index)
2208     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2209   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2210       demux->element_index, demux->index_id);
2211 }
2212
2213 static GstIndex *
2214 gst_qtdemux_get_index (GstElement * element)
2215 {
2216   GstIndex *result = NULL;
2217   GstQTDemux *demux = GST_QTDEMUX (element);
2218
2219   GST_OBJECT_LOCK (demux);
2220   if (demux->element_index)
2221     result = gst_object_ref (demux->element_index);
2222   GST_OBJECT_UNLOCK (demux);
2223
2224   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2225
2226   return result;
2227 }
2228 #endif
2229
2230 static void
2231 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2232 {
2233   g_free ((gpointer) stream->stco.data);
2234   stream->stco.data = NULL;
2235   g_free ((gpointer) stream->stsz.data);
2236   stream->stsz.data = NULL;
2237   g_free ((gpointer) stream->stsc.data);
2238   stream->stsc.data = NULL;
2239   g_free ((gpointer) stream->stts.data);
2240   stream->stts.data = NULL;
2241   g_free ((gpointer) stream->stss.data);
2242   stream->stss.data = NULL;
2243   g_free ((gpointer) stream->stps.data);
2244   stream->stps.data = NULL;
2245   g_free ((gpointer) stream->ctts.data);
2246   stream->ctts.data = NULL;
2247 }
2248
2249 static void
2250 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2251     QtDemuxStream * stream)
2252 {
2253   g_free (stream->segments);
2254   stream->segments = NULL;
2255   stream->segment_index = -1;
2256   stream->accumulated_base = 0;
2257 }
2258
2259 static void
2260 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2261     QtDemuxStream * stream)
2262 {
2263   g_free (stream->samples);
2264   stream->samples = NULL;
2265   gst_qtdemux_stbl_free (stream);
2266
2267   /* fragments */
2268   g_free (stream->ra_entries);
2269   stream->ra_entries = NULL;
2270   stream->n_ra_entries = 0;
2271
2272   stream->sample_index = -1;
2273   stream->stbl_index = -1;
2274   stream->n_samples = 0;
2275   stream->time_position = 0;
2276 }
2277
2278 static void
2279 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2280 {
2281   if (stream->allocator)
2282     gst_object_unref (stream->allocator);
2283   while (stream->buffers) {
2284     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2285     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2286   }
2287   if (stream->rgb8_palette) {
2288     gst_memory_unref (stream->rgb8_palette);
2289     stream->rgb8_palette = NULL;
2290   }
2291
2292   if (stream->pending_tags)
2293     gst_tag_list_unref (stream->pending_tags);
2294   stream->pending_tags = NULL;
2295   g_free (stream->redirect_uri);
2296   stream->redirect_uri = NULL;
2297   stream->sent_eos = FALSE;
2298   stream->sparse = FALSE;
2299   stream->protected = FALSE;
2300   if (stream->protection_scheme_info) {
2301     if (stream->protection_scheme_type == FOURCC_cenc) {
2302       QtDemuxCencSampleSetInfo *info =
2303           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2304       if (info->default_properties)
2305         gst_structure_free (info->default_properties);
2306       if (info->crypto_info)
2307         g_ptr_array_free (info->crypto_info, TRUE);
2308     }
2309     g_free (stream->protection_scheme_info);
2310     stream->protection_scheme_info = NULL;
2311   }
2312   stream->protection_scheme_type = 0;
2313   stream->protection_scheme_version = 0;
2314   g_queue_foreach (&stream->protection_scheme_event_queue,
2315       (GFunc) gst_event_unref, NULL);
2316   g_queue_clear (&stream->protection_scheme_event_queue);
2317   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2318   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2319 }
2320
2321 static void
2322 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2323 {
2324   gst_qtdemux_stream_clear (qtdemux, stream);
2325   if (stream->caps)
2326     gst_caps_unref (stream->caps);
2327   stream->caps = NULL;
2328   if (stream->pad) {
2329     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2330     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2331   }
2332   g_free (stream);
2333 }
2334
2335 static void
2336 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2337 {
2338   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2339
2340   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2341   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2342   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2343   qtdemux->n_streams--;
2344 }
2345
2346 static GstStateChangeReturn
2347 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2348 {
2349   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2350   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2351
2352   switch (transition) {
2353     case GST_STATE_CHANGE_PAUSED_TO_READY:
2354       break;
2355     default:
2356       break;
2357   }
2358
2359   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2360
2361   switch (transition) {
2362     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2363       gst_qtdemux_reset (qtdemux, TRUE);
2364       break;
2365     }
2366     default:
2367       break;
2368   }
2369
2370   return result;
2371 }
2372
2373 static void
2374 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2375 {
2376   /* counts as header data */
2377   qtdemux->header_size += length;
2378
2379   /* only consider at least a sufficiently complete ftyp atom */
2380   if (length >= 20) {
2381     GstBuffer *buf;
2382
2383     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2384     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2385         GST_FOURCC_ARGS (qtdemux->major_brand));
2386     if (qtdemux->comp_brands)
2387       gst_buffer_unref (qtdemux->comp_brands);
2388     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2389     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2390   }
2391 }
2392
2393 static void
2394 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2395     GstTagList * xmptaglist)
2396 {
2397   /* Strip out bogus fields */
2398   if (xmptaglist) {
2399     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2400       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2401       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2402     } else {
2403       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2404     }
2405
2406     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2407
2408     /* prioritize native tags using _KEEP mode */
2409     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2410     gst_tag_list_unref (xmptaglist);
2411   }
2412 }
2413
2414 static void
2415 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2416 {
2417   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2418     0x97, 0xA9, 0x42, 0xE8,
2419     0x9C, 0x71, 0x99, 0x94,
2420     0x91, 0xE3, 0xAF, 0xAC
2421   };
2422   static const guint8 playready_uuid[] = {
2423     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2424     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2425   };
2426   guint offset;
2427
2428   /* counts as header data */
2429   qtdemux->header_size += length;
2430
2431   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2432
2433   if (length <= offset + 16) {
2434     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2435     return;
2436   }
2437
2438   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2439     GstBuffer *buf;
2440     GstTagList *taglist;
2441
2442     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2443         length - offset - 16, NULL);
2444     taglist = gst_tag_list_from_xmp_buffer (buf);
2445     gst_buffer_unref (buf);
2446
2447     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2448
2449   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2450     int len;
2451     const gunichar2 *s_utf16;
2452     char *contents;
2453
2454     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2455     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2456     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2457     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2458
2459     g_free (contents);
2460
2461     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2462         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2463         (NULL));
2464   } else {
2465     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2466         GST_READ_UINT32_LE (buffer + offset),
2467         GST_READ_UINT32_LE (buffer + offset + 4),
2468         GST_READ_UINT32_LE (buffer + offset + 8),
2469         GST_READ_UINT32_LE (buffer + offset + 12));
2470   }
2471 }
2472
2473 static void
2474 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2475 {
2476   GstSidxParser sidx_parser;
2477   GstIsoffParserResult res;
2478   guint consumed;
2479
2480   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2481
2482   res =
2483       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2484       &consumed);
2485   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2486   if (res == GST_ISOFF_QT_PARSER_DONE) {
2487     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2488   }
2489   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2490 }
2491
2492 /* caller verifies at least 8 bytes in buf */
2493 static void
2494 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2495     guint64 * plength, guint32 * pfourcc)
2496 {
2497   guint64 length;
2498   guint32 fourcc;
2499
2500   length = QT_UINT32 (data);
2501   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2502   fourcc = QT_FOURCC (data + 4);
2503   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2504
2505   if (length == 0) {
2506     length = G_MAXUINT64;
2507   } else if (length == 1 && size >= 16) {
2508     /* this means we have an extended size, which is the 64 bit value of
2509      * the next 8 bytes */
2510     length = QT_UINT64 (data + 8);
2511     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2512   }
2513
2514   if (plength)
2515     *plength = length;
2516   if (pfourcc)
2517     *pfourcc = fourcc;
2518 }
2519
2520 static gboolean
2521 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2522 {
2523   guint32 version = 0;
2524   GstClockTime duration = 0;
2525
2526   if (!gst_byte_reader_get_uint32_be (br, &version))
2527     goto failed;
2528
2529   version >>= 24;
2530   if (version == 1) {
2531     if (!gst_byte_reader_get_uint64_be (br, &duration))
2532       goto failed;
2533   } else {
2534     guint32 dur = 0;
2535
2536     if (!gst_byte_reader_get_uint32_be (br, &dur))
2537       goto failed;
2538     duration = dur;
2539   }
2540
2541   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2542   qtdemux->duration = duration;
2543
2544   return TRUE;
2545
2546 failed:
2547   {
2548     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2549     return FALSE;
2550   }
2551 }
2552
2553 static gboolean
2554 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2555     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2556 {
2557   if (!stream->parsed_trex && qtdemux->moov_node) {
2558     GNode *mvex, *trex;
2559     GstByteReader trex_data;
2560
2561     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2562     if (mvex) {
2563       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2564           &trex_data);
2565       while (trex) {
2566         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2567
2568         /* skip version/flags */
2569         if (!gst_byte_reader_skip (&trex_data, 4))
2570           goto next;
2571         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2572           goto next;
2573         if (id != stream->track_id)
2574           goto next;
2575         /* sample description index; ignore */
2576         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2577           goto next;
2578         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2579           goto next;
2580         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2581           goto next;
2582         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2583           goto next;
2584
2585         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2586             "duration %d,  size %d, flags 0x%x", stream->track_id,
2587             dur, size, flags);
2588
2589         stream->parsed_trex = TRUE;
2590         stream->def_sample_duration = dur;
2591         stream->def_sample_size = size;
2592         stream->def_sample_flags = flags;
2593
2594       next:
2595         /* iterate all siblings */
2596         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2597             &trex_data);
2598       }
2599     }
2600   }
2601
2602   *ds_duration = stream->def_sample_duration;
2603   *ds_size = stream->def_sample_size;
2604   *ds_flags = stream->def_sample_flags;
2605
2606   /* even then, above values are better than random ... */
2607   if (G_UNLIKELY (!stream->parsed_trex)) {
2608     GST_WARNING_OBJECT (qtdemux,
2609         "failed to find fragment defaults for stream %d", stream->track_id);
2610     return FALSE;
2611   }
2612
2613   return TRUE;
2614 }
2615
2616 /* This method should be called whenever a more accurate duration might
2617  * have been found. It will update all relevant variables if/where needed
2618  */
2619 static void
2620 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2621 {
2622   guint i;
2623   guint64 movdur;
2624   GstClockTime prevdur;
2625
2626   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2627
2628   if (movdur > qtdemux->duration) {
2629     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2630     GST_DEBUG_OBJECT (qtdemux,
2631         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2632         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2633     qtdemux->duration = movdur;
2634     GST_DEBUG_OBJECT (qtdemux,
2635         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2636         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2637         GST_TIME_ARGS (qtdemux->segment.stop));
2638     if (qtdemux->segment.duration == prevdur) {
2639       /* If the current segment has duration/stop identical to previous duration
2640        * update them also (because they were set at that point in time with
2641        * the wrong duration */
2642       /* We convert the value *from* the timescale version to avoid rounding errors */
2643       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2644       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2645       qtdemux->segment.duration = fixeddur;
2646       qtdemux->segment.stop = fixeddur;
2647     }
2648   }
2649   for (i = 0; i < qtdemux->n_streams; i++) {
2650     QtDemuxStream *stream = qtdemux->streams[i];
2651     if (stream) {
2652       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2653       if (movdur > stream->duration) {
2654         GST_DEBUG_OBJECT (qtdemux,
2655             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2656             GST_TIME_ARGS (duration));
2657         stream->duration = movdur;
2658         if (stream->dummy_segment) {
2659           /* Update all dummy values to new duration */
2660           stream->segments[0].stop_time = duration;
2661           stream->segments[0].duration = duration;
2662           stream->segments[0].media_stop = duration;
2663         }
2664       }
2665     }
2666   }
2667 }
2668
2669 static gboolean
2670 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2671     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2672     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2673     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2674 {
2675   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2676   guint64 timestamp;
2677   gint32 data_offset = 0;
2678   guint32 flags = 0, first_flags = 0, samples_count = 0;
2679   gint i;
2680   guint8 *data;
2681   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2682   QtDemuxSample *sample;
2683   gboolean ismv = FALSE;
2684
2685   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2686       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2687       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2688       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2689
2690   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2691     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2692     return TRUE;
2693   }
2694
2695   /* presence of stss or not can't really tell us much,
2696    * and flags and so on tend to be marginally reliable in these files */
2697   if (stream->subtype == FOURCC_soun) {
2698     GST_DEBUG_OBJECT (qtdemux,
2699         "sound track in fragmented file; marking all keyframes");
2700     stream->all_keyframe = TRUE;
2701   }
2702
2703   if (!gst_byte_reader_skip (trun, 1) ||
2704       !gst_byte_reader_get_uint24_be (trun, &flags))
2705     goto fail;
2706
2707   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
2708     goto fail;
2709
2710   if (flags & TR_DATA_OFFSET) {
2711     /* note this is really signed */
2712     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
2713       goto fail;
2714     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
2715     /* default base offset = first byte of moof */
2716     if (*base_offset == -1) {
2717       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
2718       *base_offset = moof_offset;
2719     }
2720     *running_offset = *base_offset + data_offset;
2721   } else {
2722     /* if no offset at all, that would mean data starts at moof start,
2723      * which is a bit wrong and is ismv crappy way, so compensate
2724      * assuming data is in mdat following moof */
2725     if (*base_offset == -1) {
2726       *base_offset = moof_offset + moof_length + 8;
2727       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
2728       ismv = TRUE;
2729     }
2730     if (*running_offset == -1)
2731       *running_offset = *base_offset;
2732   }
2733
2734   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
2735       *running_offset);
2736   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
2737       data_offset, flags, samples_count);
2738
2739   if (flags & TR_FIRST_SAMPLE_FLAGS) {
2740     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
2741       GST_DEBUG_OBJECT (qtdemux,
2742           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
2743       flags ^= TR_FIRST_SAMPLE_FLAGS;
2744     } else {
2745       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
2746         goto fail;
2747       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
2748     }
2749   }
2750
2751   /* FIXME ? spec says other bits should also be checked to determine
2752    * entry size (and prefix size for that matter) */
2753   entry_size = 0;
2754   dur_offset = size_offset = 0;
2755   if (flags & TR_SAMPLE_DURATION) {
2756     GST_LOG_OBJECT (qtdemux, "entry duration present");
2757     dur_offset = entry_size;
2758     entry_size += 4;
2759   }
2760   if (flags & TR_SAMPLE_SIZE) {
2761     GST_LOG_OBJECT (qtdemux, "entry size present");
2762     size_offset = entry_size;
2763     entry_size += 4;
2764   }
2765   if (flags & TR_SAMPLE_FLAGS) {
2766     GST_LOG_OBJECT (qtdemux, "entry flags present");
2767     flags_offset = entry_size;
2768     entry_size += 4;
2769   }
2770   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
2771     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
2772     ct_offset = entry_size;
2773     entry_size += 4;
2774   }
2775
2776   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
2777     goto fail;
2778   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
2779
2780   if (stream->n_samples + samples_count >=
2781       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
2782     goto index_too_big;
2783
2784   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
2785       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
2786       (stream->n_samples + samples_count) *
2787       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
2788
2789   /* create a new array of samples if it's the first sample parsed */
2790   if (stream->n_samples == 0) {
2791     g_assert (stream->samples == NULL);
2792     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
2793     /* or try to reallocate it with space enough to insert the new samples */
2794   } else
2795     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
2796         stream->n_samples + samples_count);
2797   if (stream->samples == NULL)
2798     goto out_of_memory;
2799
2800   if (qtdemux->fragment_start != -1) {
2801     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
2802     qtdemux->fragment_start = -1;
2803   } else {
2804     if (stream->n_samples == 0) {
2805       if (decode_ts > 0) {
2806         timestamp = decode_ts;
2807       } else if (stream->pending_seek != NULL) {
2808         /* if we don't have a timestamp from a tfdt box, we'll use the one
2809          * from the mfra seek table */
2810         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
2811             GST_TIME_ARGS (stream->pending_seek->ts));
2812
2813         /* FIXME: this is not fully correct, the timestamp refers to the random
2814          * access sample refered to in the tfra entry, which may not necessarily
2815          * be the first sample in the tfrag/trun (but hopefully/usually is) */
2816         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
2817       } else {
2818         timestamp = 0;
2819       }
2820
2821       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
2822       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
2823           GST_TIME_ARGS (gst_ts));
2824     } else {
2825       /* subsequent fragments extend stream */
2826       timestamp =
2827           stream->samples[stream->n_samples - 1].timestamp +
2828           stream->samples[stream->n_samples - 1].duration;
2829
2830       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
2831       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
2832           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
2833     }
2834   }
2835
2836   sample = stream->samples + stream->n_samples;
2837   for (i = 0; i < samples_count; i++) {
2838     guint32 dur, size, sflags, ct;
2839
2840     /* first read sample data */
2841     if (flags & TR_SAMPLE_DURATION) {
2842       dur = QT_UINT32 (data + dur_offset);
2843     } else {
2844       dur = d_sample_duration;
2845     }
2846     if (flags & TR_SAMPLE_SIZE) {
2847       size = QT_UINT32 (data + size_offset);
2848     } else {
2849       size = d_sample_size;
2850     }
2851     if (flags & TR_FIRST_SAMPLE_FLAGS) {
2852       if (i == 0) {
2853         sflags = first_flags;
2854       } else {
2855         sflags = d_sample_flags;
2856       }
2857     } else if (flags & TR_SAMPLE_FLAGS) {
2858       sflags = QT_UINT32 (data + flags_offset);
2859     } else {
2860       sflags = d_sample_flags;
2861     }
2862     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
2863       ct = QT_UINT32 (data + ct_offset);
2864     } else {
2865       ct = 0;
2866     }
2867     data += entry_size;
2868
2869     /* fill the sample information */
2870     sample->offset = *running_offset;
2871     sample->pts_offset = ct;
2872     sample->size = size;
2873     sample->timestamp = timestamp;
2874     sample->duration = dur;
2875     /* sample-is-difference-sample */
2876     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
2877      * now idea how it relates to bitfield other than massive LE/BE confusion */
2878     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
2879     *running_offset += size;
2880     timestamp += dur;
2881     sample++;
2882   }
2883
2884   /* Update total duration if needed */
2885   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
2886
2887   stream->n_samples += samples_count;
2888
2889   if (stream->pending_seek != NULL)
2890     stream->pending_seek = NULL;
2891
2892   return TRUE;
2893
2894 fail:
2895   {
2896     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
2897     return FALSE;
2898   }
2899 out_of_memory:
2900   {
2901     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
2902         stream->n_samples);
2903     return FALSE;
2904   }
2905 index_too_big:
2906   {
2907     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
2908         "be larger than %uMB (broken file?)", stream->n_samples,
2909         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
2910     return FALSE;
2911   }
2912 }
2913
2914 /* find stream with @id */
2915 static inline QtDemuxStream *
2916 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
2917 {
2918   QtDemuxStream *stream;
2919   gint i;
2920
2921   /* check */
2922   if (G_UNLIKELY (!id)) {
2923     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
2924     return NULL;
2925   }
2926
2927   /* try to get it fast and simple */
2928   if (G_LIKELY (id <= qtdemux->n_streams)) {
2929     stream = qtdemux->streams[id - 1];
2930     if (G_LIKELY (stream->track_id == id))
2931       return stream;
2932   }
2933
2934   /* linear search otherwise */
2935   for (i = 0; i < qtdemux->n_streams; i++) {
2936     stream = qtdemux->streams[i];
2937     if (stream->track_id == id)
2938       return stream;
2939   }
2940   if (qtdemux->mss_mode) {
2941     /* mss should have only 1 stream anyway */
2942     return qtdemux->streams[0];
2943   }
2944
2945   return NULL;
2946 }
2947
2948 static gboolean
2949 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
2950     guint32 * fragment_number)
2951 {
2952   if (!gst_byte_reader_skip (mfhd, 4))
2953     goto fail;
2954   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
2955     goto fail;
2956   return TRUE;
2957 fail:
2958   {
2959     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
2960     return FALSE;
2961   }
2962 }
2963
2964 static gboolean
2965 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
2966     QtDemuxStream ** stream, guint32 * default_sample_duration,
2967     guint32 * default_sample_size, guint32 * default_sample_flags,
2968     gint64 * base_offset)
2969 {
2970   guint32 flags = 0;
2971   guint32 track_id = 0;
2972
2973   if (!gst_byte_reader_skip (tfhd, 1) ||
2974       !gst_byte_reader_get_uint24_be (tfhd, &flags))
2975     goto invalid_track;
2976
2977   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
2978     goto invalid_track;
2979
2980   *stream = qtdemux_find_stream (qtdemux, track_id);
2981   if (G_UNLIKELY (!*stream))
2982     goto unknown_stream;
2983
2984   if (flags & TF_DEFAULT_BASE_IS_MOOF)
2985     *base_offset = qtdemux->moof_offset;
2986
2987   if (flags & TF_BASE_DATA_OFFSET)
2988     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
2989       goto invalid_track;
2990
2991   /* obtain stream defaults */
2992   qtdemux_parse_trex (qtdemux, *stream,
2993       default_sample_duration, default_sample_size, default_sample_flags);
2994
2995   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
2996   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
2997     if (!gst_byte_reader_skip (tfhd, 4))
2998       goto invalid_track;
2999
3000   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3001     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3002       goto invalid_track;
3003
3004   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3005     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3006       goto invalid_track;
3007
3008   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3009     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3010       goto invalid_track;
3011
3012   return TRUE;
3013
3014 invalid_track:
3015   {
3016     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3017     return FALSE;
3018   }
3019 unknown_stream:
3020   {
3021     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3022     return TRUE;
3023   }
3024 }
3025
3026 static gboolean
3027 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3028     guint64 * decode_time)
3029 {
3030   guint32 version = 0;
3031
3032   if (!gst_byte_reader_get_uint32_be (br, &version))
3033     return FALSE;
3034
3035   version >>= 24;
3036   if (version == 1) {
3037     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3038       goto failed;
3039   } else {
3040     guint32 dec_time = 0;
3041     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3042       goto failed;
3043     *decode_time = dec_time;
3044   }
3045
3046   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3047       *decode_time);
3048
3049   return TRUE;
3050
3051 failed:
3052   {
3053     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3054     return FALSE;
3055   }
3056 }
3057
3058 /* Returns a pointer to a GstStructure containing the properties of
3059  * the stream sample identified by @sample_index. The caller must unref
3060  * the returned object after use. Returns NULL if unsuccessful. */
3061 static GstStructure *
3062 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3063     QtDemuxStream * stream, guint sample_index)
3064 {
3065   QtDemuxCencSampleSetInfo *info = NULL;
3066
3067   g_return_val_if_fail (stream != NULL, NULL);
3068   g_return_val_if_fail (stream->protected, NULL);
3069   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3070
3071   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3072
3073   /* Currently, cenc properties for groups of samples are not supported, so
3074    * simply return a copy of the default sample properties */
3075   return gst_structure_copy (info->default_properties);
3076 }
3077
3078 /* Parses the sizes of sample auxiliary information contained within a stream,
3079  * as given in a saiz box. Returns array of sample_count guint8 size values,
3080  * or NULL on failure */
3081 static guint8 *
3082 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3083     GstByteReader * br, guint32 * sample_count)
3084 {
3085   guint32 flags = 0;
3086   guint8 *info_sizes;
3087   guint8 default_info_size;
3088
3089   g_return_val_if_fail (qtdemux != NULL, NULL);
3090   g_return_val_if_fail (stream != NULL, NULL);
3091   g_return_val_if_fail (br != NULL, NULL);
3092   g_return_val_if_fail (sample_count != NULL, NULL);
3093
3094   if (!gst_byte_reader_get_uint32_be (br, &flags))
3095     return NULL;
3096
3097   if (flags & 0x1) {
3098     /* aux_info_type and aux_info_type_parameter are ignored */
3099     if (!gst_byte_reader_skip (br, 8))
3100       return NULL;
3101   }
3102
3103   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3104     return NULL;
3105   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3106
3107   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3108     return NULL;
3109   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3110
3111
3112   if (default_info_size == 0) {
3113     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3114       return NULL;
3115     }
3116   } else {
3117     info_sizes = g_new (guint8, *sample_count);
3118     memset (info_sizes, default_info_size, *sample_count);
3119   }
3120
3121   return info_sizes;
3122 }
3123
3124 /* Parses the offset of sample auxiliary information contained within a stream,
3125  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3126 static gboolean
3127 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3128     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3129     guint64 * offset)
3130 {
3131   guint8 version = 0;
3132   guint32 flags = 0;
3133   guint32 aux_info_type = 0;
3134   guint32 aux_info_type_parameter = 0;
3135   guint32 entry_count;
3136   guint32 off_32;
3137   guint64 off_64;
3138
3139   g_return_val_if_fail (qtdemux != NULL, FALSE);
3140   g_return_val_if_fail (stream != NULL, FALSE);
3141   g_return_val_if_fail (br != NULL, FALSE);
3142   g_return_val_if_fail (offset != NULL, FALSE);
3143
3144   if (!gst_byte_reader_get_uint8 (br, &version))
3145     return FALSE;
3146
3147   if (!gst_byte_reader_get_uint24_be (br, &flags))
3148     return FALSE;
3149
3150   if (flags & 0x1) {
3151     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type))
3152       return FALSE;
3153     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3154       return FALSE;
3155   } else if (stream->protected) {
3156     aux_info_type = stream->protection_scheme_type;
3157   } else {
3158     aux_info_type = stream->fourcc;
3159   }
3160
3161   if (info_type)
3162     *info_type = aux_info_type;
3163   if (info_type_parameter)
3164     *info_type_parameter = aux_info_type_parameter;
3165
3166   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3167       "aux_info_type_parameter:  %#06x",
3168       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3169
3170   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3171     return FALSE;
3172
3173   if (entry_count != 1) {
3174     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3175     return FALSE;
3176   }
3177
3178   if (version == 0) {
3179     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3180       return FALSE;
3181     *offset = (guint64) off_32;
3182   } else {
3183     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3184       return FALSE;
3185     *offset = off_64;
3186   }
3187
3188   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3189   return TRUE;
3190 }
3191
3192 static void
3193 qtdemux_gst_structure_free (GstStructure * gststructure)
3194 {
3195   if (gststructure) {
3196     gst_structure_free (gststructure);
3197   }
3198 }
3199
3200 /* Parses auxiliary information relating to samples protected using Common
3201  * Encryption (cenc); the format of this information is defined in
3202  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3203 static gboolean
3204 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3205     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3206 {
3207   QtDemuxCencSampleSetInfo *ss_info = NULL;
3208   guint8 size;
3209   gint i;
3210
3211   g_return_val_if_fail (qtdemux != NULL, FALSE);
3212   g_return_val_if_fail (stream != NULL, FALSE);
3213   g_return_val_if_fail (br != NULL, FALSE);
3214   g_return_val_if_fail (stream->protected, FALSE);
3215   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3216
3217   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3218
3219   if (ss_info->crypto_info) {
3220     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3221     g_ptr_array_free (ss_info->crypto_info, TRUE);
3222   }
3223
3224   ss_info->crypto_info =
3225       g_ptr_array_new_full (sample_count,
3226       (GDestroyNotify) qtdemux_gst_structure_free);
3227
3228   for (i = 0; i < sample_count; ++i) {
3229     GstStructure *properties;
3230     guint16 n_subsamples;
3231     guint8 *data;
3232     guint iv_size;
3233     GstBuffer *buf;
3234
3235     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3236     if (properties == NULL) {
3237       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3238       return FALSE;
3239     }
3240     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3241       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3242       gst_structure_free (properties);
3243       return FALSE;
3244     }
3245     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3246       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3247       gst_structure_free (properties);
3248       return FALSE;
3249     }
3250     buf = gst_buffer_new_wrapped (data, iv_size);
3251     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3252     size = info_sizes[i];
3253     if (size > iv_size) {
3254       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3255           || !(n_subsamples > 0)) {
3256         gst_structure_free (properties);
3257         GST_ERROR_OBJECT (qtdemux,
3258             "failed to get subsample count for sample %u", i);
3259         return FALSE;
3260       }
3261       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3262       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3263         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3264             i);
3265         gst_structure_free (properties);
3266         return FALSE;
3267       }
3268       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3269       if (!buf) {
3270         gst_structure_free (properties);
3271         return FALSE;
3272       }
3273       gst_structure_set (properties,
3274           "subsample_count", G_TYPE_UINT, n_subsamples,
3275           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3276     } else {
3277       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3278     }
3279     g_ptr_array_add (ss_info->crypto_info, properties);
3280   }
3281   return TRUE;
3282 }
3283
3284 /* Converts a UUID in raw byte form to a string representation, as defined in
3285  * RFC 4122. The caller takes ownership of the returned string and is
3286  * responsible for freeing it after use. */
3287 static gchar *
3288 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3289 {
3290   const guint8 *uuid = (const guint8 *) uuid_bytes;
3291
3292   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3293       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3294       uuid[0], uuid[1], uuid[2], uuid[3],
3295       uuid[4], uuid[5], uuid[6], uuid[7],
3296       uuid[8], uuid[9], uuid[10], uuid[11],
3297       uuid[12], uuid[13], uuid[14], uuid[15]);
3298 }
3299
3300 /* Parses a Protection System Specific Header box (pssh), as defined in the
3301  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3302  * information needed by a specific content protection system in order to
3303  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3304  * otherwise. */
3305 static gboolean
3306 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3307 {
3308   gchar *sysid_string;
3309   guint32 pssh_size = QT_UINT32 (node->data);
3310   GstBuffer *pssh = NULL;
3311   GstEvent *event = NULL;
3312   guint32 parent_box_type;
3313   gint i;
3314
3315   if (G_UNLIKELY (pssh_size < 32U)) {
3316     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3317     return FALSE;
3318   }
3319
3320   sysid_string =
3321       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3322
3323   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3324
3325   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3326   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3327       gst_buffer_get_size (pssh));
3328
3329   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3330
3331   /* Push an event containing the pssh box onto the queues of all streams. */
3332   event = gst_event_new_protection (sysid_string, pssh,
3333       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3334   for (i = 0; i < qtdemux->n_streams; ++i) {
3335     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3336         gst_event_ref (event));
3337   }
3338   g_free (sysid_string);
3339   gst_event_unref (event);
3340   gst_buffer_unref (pssh);
3341   return TRUE;
3342 }
3343
3344 static gboolean
3345 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3346     guint64 moof_offset, QtDemuxStream * stream)
3347 {
3348   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3349   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3350   GNode *saiz_node, *saio_node, *pssh_node;
3351   GstByteReader saiz_data, saio_data;
3352   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3353   gint64 base_offset, running_offset;
3354   guint32 frag_num;
3355
3356   /* NOTE @stream ignored */
3357
3358   moof_node = g_node_new ((guint8 *) buffer);
3359   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3360   qtdemux_node_dump (qtdemux, moof_node);
3361
3362   /* Get fragment number from mfhd and check it's valid */
3363   mfhd_node =
3364       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3365   if (mfhd_node == NULL)
3366     goto missing_mfhd;
3367   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3368     goto fail;
3369   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3370
3371   /* unknown base_offset to start with */
3372   base_offset = running_offset = -1;
3373   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3374   while (traf_node) {
3375     guint64 decode_time = 0;
3376
3377     /* Fragment Header node */
3378     tfhd_node =
3379         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3380         &tfhd_data);
3381     if (!tfhd_node)
3382       goto missing_tfhd;
3383     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3384             &ds_size, &ds_flags, &base_offset))
3385       goto missing_tfhd;
3386
3387     /* The following code assumes at most a single set of sample auxiliary
3388      * data in the fragment (consisting of a saiz box and a corresponding saio
3389      * box); in theory, however, there could be multiple sets of sample
3390      * auxiliary data in a fragment. */
3391     saiz_node =
3392         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3393         &saiz_data);
3394     if (saiz_node) {
3395       guint32 info_type = 0;
3396       guint64 offset = 0;
3397       guint32 info_type_parameter = 0;
3398
3399       g_free (qtdemux->cenc_aux_info_sizes);
3400
3401       qtdemux->cenc_aux_info_sizes =
3402           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3403           &qtdemux->cenc_aux_sample_count);
3404       if (qtdemux->cenc_aux_info_sizes == NULL) {
3405         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3406         goto fail;
3407       }
3408       saio_node =
3409           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3410           &saio_data);
3411       if (!saio_node) {
3412         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3413         g_free (qtdemux->cenc_aux_info_sizes);
3414         qtdemux->cenc_aux_info_sizes = NULL;
3415         goto fail;
3416       }
3417
3418       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3419                   &info_type, &info_type_parameter, &offset))) {
3420         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3421         g_free (qtdemux->cenc_aux_info_sizes);
3422         qtdemux->cenc_aux_info_sizes = NULL;
3423         goto fail;
3424       }
3425       if (base_offset > qtdemux->moof_offset)
3426         offset += (guint64) (base_offset - qtdemux->moof_offset);
3427       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3428         GstByteReader br;
3429         if (offset > length) {
3430           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3431           qtdemux->cenc_aux_info_offset = offset;
3432         } else {
3433           gst_byte_reader_init (&br, buffer + offset, length - offset);
3434           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3435                   qtdemux->cenc_aux_info_sizes,
3436                   qtdemux->cenc_aux_sample_count)) {
3437             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3438             g_free (qtdemux->cenc_aux_info_sizes);
3439             qtdemux->cenc_aux_info_sizes = NULL;
3440             goto fail;
3441           }
3442         }
3443       }
3444     }
3445
3446     tfdt_node =
3447         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3448         &tfdt_data);
3449     if (tfdt_node) {
3450       GstClockTime decode_time_ts;
3451
3452       /* We'll use decode_time to interpolate timestamps
3453        * in case the input timestamps are missing */
3454       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3455
3456       decode_time_ts = QTSTREAMTIME_TO_GSTTIME (stream, decode_time);
3457
3458       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3459           " (%" GST_TIME_FORMAT ")", decode_time,
3460           GST_TIME_ARGS (decode_time_ts));
3461
3462       /* Discard the fragment buffer timestamp info to avoid using it.
3463        * Rely on tfdt instead as it is more accurate than the timestamp
3464        * that is fetched from a manifest/playlist and is usually
3465        * less accurate. */
3466       qtdemux->fragment_start = -1;
3467     }
3468
3469     if (G_UNLIKELY (!stream)) {
3470       /* we lost track of offset, we'll need to regain it,
3471        * but can delay complaining until later or avoid doing so altogether */
3472       base_offset = -2;
3473       goto next;
3474     }
3475     if (G_UNLIKELY (base_offset < -1))
3476       goto lost_offset;
3477
3478     if (qtdemux->upstream_format_is_time)
3479       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3480
3481     /* Track Run node */
3482     trun_node =
3483         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3484         &trun_data);
3485     while (trun_node) {
3486       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3487           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3488           &running_offset, decode_time);
3489       /* iterate all siblings */
3490       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3491           &trun_data);
3492     }
3493     /* if no new base_offset provided for next traf,
3494      * base is end of current traf */
3495     base_offset = running_offset;
3496     running_offset = -1;
3497   next:
3498     /* iterate all siblings */
3499     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3500   }
3501
3502   /* parse any protection system info */
3503   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3504   while (pssh_node) {
3505     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3506     qtdemux_parse_pssh (qtdemux, pssh_node);
3507     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3508   }
3509
3510   g_node_destroy (moof_node);
3511   return TRUE;
3512
3513 missing_tfhd:
3514   {
3515     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3516     goto fail;
3517   }
3518 missing_mfhd:
3519   {
3520     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3521     goto fail;
3522   }
3523 lost_offset:
3524   {
3525     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3526     goto fail;
3527   }
3528 fail:
3529   {
3530     g_node_destroy (moof_node);
3531     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3532         (_("This file is corrupt and cannot be played.")), (NULL));
3533     return FALSE;
3534   }
3535 }
3536
3537 #if 0
3538 /* might be used if some day we actually use mfra & co
3539  * for random access to fragments,
3540  * but that will require quite some modifications and much less relying
3541  * on a sample array */
3542 #endif
3543
3544 static gboolean
3545 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3546 {
3547   QtDemuxStream *stream;
3548   guint32 ver_flags, track_id, len, num_entries, i;
3549   guint value_size, traf_size, trun_size, sample_size;
3550   guint64 time = 0, moof_offset = 0;
3551 #if 0
3552   GstBuffer *buf = NULL;
3553   GstFlowReturn ret;
3554 #endif
3555   GstByteReader tfra;
3556
3557   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3558
3559   if (!gst_byte_reader_skip (&tfra, 8))
3560     return FALSE;
3561
3562   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3563     return FALSE;
3564
3565   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3566       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3567       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3568     return FALSE;
3569
3570   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3571
3572   stream = qtdemux_find_stream (qtdemux, track_id);
3573   if (stream == NULL)
3574     goto unknown_trackid;
3575
3576   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3577   sample_size = (len & 3) + 1;
3578   trun_size = ((len & 12) >> 2) + 1;
3579   traf_size = ((len & 48) >> 4) + 1;
3580
3581   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3582       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3583
3584   if (num_entries == 0)
3585     goto no_samples;
3586
3587   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3588           value_size + value_size + traf_size + trun_size + sample_size))
3589     goto corrupt_file;
3590
3591   g_free (stream->ra_entries);
3592   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3593   stream->n_ra_entries = num_entries;
3594
3595   for (i = 0; i < num_entries; i++) {
3596     qt_atom_parser_get_offset (&tfra, value_size, &time);
3597     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3598     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3599     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3600     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3601
3602     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3603
3604     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3605         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3606
3607     stream->ra_entries[i].ts = time;
3608     stream->ra_entries[i].moof_offset = moof_offset;
3609
3610     /* don't want to go through the entire file and read all moofs at startup */
3611 #if 0
3612     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3613     if (ret != GST_FLOW_OK)
3614       goto corrupt_file;
3615     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3616         moof_offset, stream);
3617     gst_buffer_unref (buf);
3618 #endif
3619   }
3620
3621   check_update_duration (qtdemux, time);
3622
3623   return TRUE;
3624
3625 /* ERRORS */
3626 unknown_trackid:
3627   {
3628     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3629     return FALSE;
3630   }
3631 corrupt_file:
3632   {
3633     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3634     return FALSE;
3635   }
3636 no_samples:
3637   {
3638     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3639     return FALSE;
3640   }
3641 }
3642
3643 static gboolean
3644 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3645 {
3646   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3647   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3648   GstBuffer *mfro = NULL, *mfra = NULL;
3649   GstFlowReturn flow;
3650   gboolean ret = FALSE;
3651   GNode *mfra_node, *tfra_node;
3652   guint64 mfra_offset = 0;
3653   guint32 fourcc, mfra_size;
3654   gint64 len;
3655
3656   /* query upstream size in bytes */
3657   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3658     goto size_query_failed;
3659
3660   /* mfro box should be at the very end of the file */
3661   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3662   if (flow != GST_FLOW_OK)
3663     goto exit;
3664
3665   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3666
3667   fourcc = QT_FOURCC (mfro_map.data + 4);
3668   if (fourcc != FOURCC_mfro)
3669     goto exit;
3670
3671   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3672   if (mfro_map.size < 16)
3673     goto invalid_mfro_size;
3674
3675   mfra_size = QT_UINT32 (mfro_map.data + 12);
3676   if (mfra_size >= len)
3677     goto invalid_mfra_size;
3678
3679   mfra_offset = len - mfra_size;
3680
3681   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
3682       mfra_offset, mfra_size);
3683
3684   /* now get and parse mfra box */
3685   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
3686   if (flow != GST_FLOW_OK)
3687     goto broken_file;
3688
3689   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
3690
3691   mfra_node = g_node_new ((guint8 *) mfra_map.data);
3692   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
3693
3694   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
3695
3696   while (tfra_node) {
3697     qtdemux_parse_tfra (qtdemux, tfra_node);
3698     /* iterate all siblings */
3699     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
3700   }
3701   g_node_destroy (mfra_node);
3702
3703   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
3704   ret = TRUE;
3705
3706 exit:
3707
3708   if (mfro) {
3709     if (mfro_map.memory != NULL)
3710       gst_buffer_unmap (mfro, &mfro_map);
3711     gst_buffer_unref (mfro);
3712   }
3713   if (mfra) {
3714     if (mfra_map.memory != NULL)
3715       gst_buffer_unmap (mfra, &mfra_map);
3716     gst_buffer_unref (mfra);
3717   }
3718   return ret;
3719
3720 /* ERRORS */
3721 size_query_failed:
3722   {
3723     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
3724     goto exit;
3725   }
3726 invalid_mfro_size:
3727   {
3728     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
3729     goto exit;
3730   }
3731 invalid_mfra_size:
3732   {
3733     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
3734     goto exit;
3735   }
3736 broken_file:
3737   {
3738     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
3739     goto exit;
3740   }
3741 }
3742
3743 static guint64
3744 add_offset (guint64 offset, guint64 advance)
3745 {
3746   /* Avoid 64-bit overflow by clamping */
3747   if (offset > G_MAXUINT64 - advance)
3748     return G_MAXUINT64;
3749   return offset + advance;
3750 }
3751
3752 static GstFlowReturn
3753 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
3754 {
3755   guint64 length = 0;
3756   guint32 fourcc = 0;
3757   GstBuffer *buf = NULL;
3758   GstFlowReturn ret = GST_FLOW_OK;
3759   guint64 cur_offset = qtdemux->offset;
3760   GstMapInfo map;
3761
3762   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
3763   if (G_UNLIKELY (ret != GST_FLOW_OK))
3764     goto beach;
3765   gst_buffer_map (buf, &map, GST_MAP_READ);
3766   if (G_LIKELY (map.size >= 8))
3767     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
3768   gst_buffer_unmap (buf, &map);
3769   gst_buffer_unref (buf);
3770
3771   /* maybe we already got most we needed, so only consider this eof */
3772   if (G_UNLIKELY (length == 0)) {
3773     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
3774         (_("Invalid atom size.")),
3775         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
3776             GST_FOURCC_ARGS (fourcc)));
3777     ret = GST_FLOW_EOS;
3778     goto beach;
3779   }
3780
3781   switch (fourcc) {
3782     case FOURCC_moof:
3783       /* record for later parsing when needed */
3784       if (!qtdemux->moof_offset) {
3785         qtdemux->moof_offset = qtdemux->offset;
3786       }
3787       if (qtdemux_pull_mfro_mfra (qtdemux)) {
3788         /* FIXME */
3789       } else {
3790         qtdemux->offset += length;      /* skip moof and keep going */
3791       }
3792       if (qtdemux->got_moov) {
3793         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
3794         ret = GST_FLOW_EOS;
3795         goto beach;
3796       }
3797       break;
3798     case FOURCC_mdat:
3799     case FOURCC_free:
3800     case FOURCC_wide:
3801     case FOURCC_PICT:
3802     case FOURCC_pnot:
3803     {
3804       GST_LOG_OBJECT (qtdemux,
3805           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
3806           GST_FOURCC_ARGS (fourcc), cur_offset);
3807       qtdemux->offset = add_offset (qtdemux->offset, length);
3808       break;
3809     }
3810     case FOURCC_moov:
3811     {
3812       GstBuffer *moov = NULL;
3813
3814       if (qtdemux->got_moov) {
3815         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
3816         qtdemux->offset = add_offset (qtdemux->offset, length);
3817         goto beach;
3818       }
3819
3820       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
3821       if (ret != GST_FLOW_OK)
3822         goto beach;
3823       gst_buffer_map (moov, &map, GST_MAP_READ);
3824
3825       if (length != map.size) {
3826         /* Some files have a 'moov' atom at the end of the file which contains
3827          * a terminal 'free' atom where the body of the atom is missing.
3828          * Check for, and permit, this special case.
3829          */
3830         if (map.size >= 8) {
3831           guint8 *final_data = map.data + (map.size - 8);
3832           guint32 final_length = QT_UINT32 (final_data);
3833           guint32 final_fourcc = QT_FOURCC (final_data + 4);
3834
3835           if (final_fourcc == FOURCC_free
3836               && map.size + final_length - 8 == length) {
3837             /* Ok, we've found that special case. Allocate a new buffer with
3838              * that free atom actually present. */
3839             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
3840             gst_buffer_fill (newmoov, 0, map.data, map.size);
3841             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
3842             gst_buffer_unmap (moov, &map);
3843             gst_buffer_unref (moov);
3844             moov = newmoov;
3845             gst_buffer_map (moov, &map, GST_MAP_READ);
3846           }
3847         }
3848       }
3849
3850       if (length != map.size) {
3851         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3852             (_("This file is incomplete and cannot be played.")),
3853             ("We got less than expected (received %" G_GSIZE_FORMAT
3854                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
3855                 (guint) length, cur_offset));
3856         gst_buffer_unmap (moov, &map);
3857         gst_buffer_unref (moov);
3858         ret = GST_FLOW_ERROR;
3859         goto beach;
3860       }
3861       qtdemux->offset += length;
3862
3863       qtdemux_parse_moov (qtdemux, map.data, length);
3864       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
3865
3866       qtdemux_parse_tree (qtdemux);
3867       g_node_destroy (qtdemux->moov_node);
3868       gst_buffer_unmap (moov, &map);
3869       gst_buffer_unref (moov);
3870       qtdemux->moov_node = NULL;
3871       qtdemux->got_moov = TRUE;
3872
3873       break;
3874     }
3875     case FOURCC_ftyp:
3876     {
3877       GstBuffer *ftyp = NULL;
3878
3879       /* extract major brand; might come in handy for ISO vs QT issues */
3880       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
3881       if (ret != GST_FLOW_OK)
3882         goto beach;
3883       qtdemux->offset += length;
3884       gst_buffer_map (ftyp, &map, GST_MAP_READ);
3885       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
3886       gst_buffer_unmap (ftyp, &map);
3887       gst_buffer_unref (ftyp);
3888       break;
3889     }
3890     case FOURCC_uuid:
3891     {
3892       GstBuffer *uuid = NULL;
3893
3894       /* uuid are extension atoms */
3895       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
3896       if (ret != GST_FLOW_OK)
3897         goto beach;
3898       qtdemux->offset += length;
3899       gst_buffer_map (uuid, &map, GST_MAP_READ);
3900       qtdemux_parse_uuid (qtdemux, map.data, map.size);
3901       gst_buffer_unmap (uuid, &map);
3902       gst_buffer_unref (uuid);
3903       break;
3904     }
3905     case FOURCC_sidx:
3906     {
3907       GstBuffer *sidx = NULL;
3908       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
3909       if (ret != GST_FLOW_OK)
3910         goto beach;
3911       qtdemux->offset += length;
3912       gst_buffer_map (sidx, &map, GST_MAP_READ);
3913       qtdemux_parse_sidx (qtdemux, map.data, map.size);
3914       gst_buffer_unmap (sidx, &map);
3915       gst_buffer_unref (sidx);
3916       break;
3917     }
3918     default:
3919     {
3920       GstBuffer *unknown = NULL;
3921
3922       GST_LOG_OBJECT (qtdemux,
3923           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
3924           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
3925           cur_offset);
3926       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
3927       if (ret != GST_FLOW_OK)
3928         goto beach;
3929       gst_buffer_map (unknown, &map, GST_MAP_READ);
3930       GST_MEMDUMP ("Unknown tag", map.data, map.size);
3931       gst_buffer_unmap (unknown, &map);
3932       gst_buffer_unref (unknown);
3933       qtdemux->offset += length;
3934       break;
3935     }
3936   }
3937
3938 beach:
3939   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
3940     /* digested all data, show what we have */
3941     qtdemux_prepare_streams (qtdemux);
3942     ret = qtdemux_expose_streams (qtdemux);
3943
3944     qtdemux->state = QTDEMUX_STATE_MOVIE;
3945     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
3946         qtdemux->state);
3947     return ret;
3948   }
3949   return ret;
3950 }
3951
3952 /* Seeks to the previous keyframe of the indexed stream and
3953  * aligns other streams with respect to the keyframe timestamp
3954  * of indexed stream. Only called in case of Reverse Playback
3955  */
3956 static GstFlowReturn
3957 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
3958 {
3959   guint8 n = 0;
3960   guint32 seg_idx = 0, k_index = 0;
3961   guint32 ref_seg_idx, ref_k_index;
3962   GstClockTime k_pos = 0, last_stop = 0;
3963   QtDemuxSegment *seg = NULL;
3964   QtDemuxStream *ref_str = NULL;
3965   guint64 seg_media_start_mov;  /* segment media start time in mov format */
3966   guint64 target_ts;
3967
3968   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
3969    * and finally align all the other streams on that timestamp with their
3970    * respective keyframes */
3971   for (n = 0; n < qtdemux->n_streams; n++) {
3972     QtDemuxStream *str = qtdemux->streams[n];
3973
3974     /* No candidate yet, take the first stream */
3975     if (!ref_str) {
3976       ref_str = str;
3977       continue;
3978     }
3979
3980     /* So that stream has a segment, we prefer video streams */
3981     if (str->subtype == FOURCC_vide) {
3982       ref_str = str;
3983       break;
3984     }
3985   }
3986
3987   if (G_UNLIKELY (!ref_str)) {
3988     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
3989     goto eos;
3990   }
3991
3992   if (G_UNLIKELY (!ref_str->from_sample)) {
3993     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
3994     goto eos;
3995   }
3996
3997   /* So that stream has been playing from from_sample to to_sample. We will
3998    * get the timestamp of the previous sample and search for a keyframe before
3999    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4000   if (ref_str->subtype == FOURCC_vide) {
4001     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4002         ref_str->from_sample - 1);
4003   } else {
4004     if (ref_str->from_sample >= 10)
4005       k_index = ref_str->from_sample - 10;
4006     else
4007       k_index = 0;
4008   }
4009
4010   target_ts =
4011       ref_str->samples[k_index].timestamp +
4012       ref_str->samples[k_index].pts_offset;
4013
4014   /* get current segment for that stream */
4015   seg = &ref_str->segments[ref_str->segment_index];
4016   /* Use segment start in original timescale for comparisons */
4017   seg_media_start_mov = seg->trak_media_start;
4018
4019   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4020       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4021       k_index, target_ts, seg_media_start_mov,
4022       GST_TIME_ARGS (seg->media_start));
4023
4024   /* Crawl back through segments to find the one containing this I frame */
4025   while (target_ts < seg_media_start_mov) {
4026     GST_DEBUG_OBJECT (qtdemux,
4027         "keyframe position (sample %u) is out of segment %u " " target %"
4028         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4029         ref_str->segment_index, target_ts, seg_media_start_mov);
4030
4031     if (G_UNLIKELY (!ref_str->segment_index)) {
4032       /* Reached first segment, let's consider it's EOS */
4033       goto eos;
4034     }
4035     ref_str->segment_index--;
4036     seg = &ref_str->segments[ref_str->segment_index];
4037     /* Use segment start in original timescale for comparisons */
4038     seg_media_start_mov = seg->trak_media_start;
4039   }
4040   /* Calculate time position of the keyframe and where we should stop */
4041   k_pos =
4042       QTSTREAMTIME_TO_GSTTIME (ref_str,
4043       target_ts - seg->trak_media_start) + seg->time;
4044   last_stop =
4045       QTSTREAMTIME_TO_GSTTIME (ref_str,
4046       ref_str->samples[ref_str->from_sample].timestamp -
4047       seg->trak_media_start) + seg->time;
4048
4049   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4050       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4051       k_index, GST_TIME_ARGS (k_pos));
4052
4053   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4054   qtdemux->segment.position = last_stop;
4055   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4056       GST_TIME_ARGS (last_stop));
4057
4058   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4059     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4060     goto eos;
4061   }
4062
4063   ref_seg_idx = ref_str->segment_index;
4064   ref_k_index = k_index;
4065
4066   /* Align them all on this */
4067   for (n = 0; n < qtdemux->n_streams; n++) {
4068     guint32 index = 0;
4069     GstClockTime seg_time = 0;
4070     QtDemuxStream *str = qtdemux->streams[n];
4071
4072     /* aligning reference stream again might lead to backing up to yet another
4073      * keyframe (due to timestamp rounding issues),
4074      * potentially putting more load on downstream; so let's try to avoid */
4075     if (str == ref_str) {
4076       seg_idx = ref_seg_idx;
4077       seg = &str->segments[seg_idx];
4078       k_index = ref_k_index;
4079       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4080           "sample at index %d", n, ref_str->segment_index, k_index);
4081     } else {
4082       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4083       GST_DEBUG_OBJECT (qtdemux,
4084           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4085           seg_idx, GST_TIME_ARGS (k_pos));
4086
4087       /* get segment and time in the segment */
4088       seg = &str->segments[seg_idx];
4089       seg_time = k_pos - seg->time;
4090
4091       /* get the media time in the segment.
4092        * No adjustment for empty "filler" segments */
4093       if (seg->media_start != GST_CLOCK_TIME_NONE)
4094         seg_time += seg->media_start;
4095
4096       /* get the index of the sample with media time */
4097       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4098       GST_DEBUG_OBJECT (qtdemux,
4099           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4100           GST_TIME_ARGS (seg_time), index);
4101
4102       /* find previous keyframe */
4103       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4104     }
4105
4106     /* Remember until where we want to go */
4107     str->to_sample = str->from_sample - 1;
4108     /* Define our time position */
4109     target_ts =
4110         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4111     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4112     if (seg->media_start != GST_CLOCK_TIME_NONE)
4113       str->time_position -= seg->media_start;
4114
4115     /* Now seek back in time */
4116     gst_qtdemux_move_stream (qtdemux, str, k_index);
4117     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4118         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4119         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4120   }
4121
4122   return GST_FLOW_OK;
4123
4124 eos:
4125   return GST_FLOW_EOS;
4126 }
4127
4128 /* activate the given segment number @seg_idx of @stream at time @offset.
4129  * @offset is an absolute global position over all the segments.
4130  *
4131  * This will push out a NEWSEGMENT event with the right values and
4132  * position the stream index to the first decodable sample before
4133  * @offset.
4134  */
4135 static gboolean
4136 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4137     guint32 seg_idx, GstClockTime offset)
4138 {
4139   GstEvent *event;
4140   QtDemuxSegment *segment;
4141   guint32 index, kf_index;
4142   GstClockTime seg_time;
4143   GstClockTime start, stop, time;
4144   gdouble rate;
4145
4146   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4147       seg_idx, GST_TIME_ARGS (offset));
4148
4149   /* update the current segment */
4150   stream->segment_index = seg_idx;
4151
4152   /* get the segment */
4153   segment = &stream->segments[seg_idx];
4154
4155   if (G_UNLIKELY (offset < segment->time)) {
4156     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4157         GST_TIME_ARGS (segment->time));
4158     return FALSE;
4159   }
4160
4161   /* segment lies beyond total indicated duration */
4162   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4163           segment->time > qtdemux->segment.duration)) {
4164     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4165         " < segment->time %" GST_TIME_FORMAT,
4166         GST_TIME_ARGS (qtdemux->segment.duration),
4167         GST_TIME_ARGS (segment->time));
4168     return FALSE;
4169   }
4170
4171   /* get time in this segment */
4172   seg_time = offset - segment->time;
4173
4174   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4175       GST_TIME_ARGS (seg_time));
4176
4177   if (G_UNLIKELY (seg_time > segment->duration)) {
4178     GST_LOG_OBJECT (stream->pad,
4179         "seg_time > segment->duration %" GST_TIME_FORMAT,
4180         GST_TIME_ARGS (segment->duration));
4181     seg_time = segment->duration;
4182   }
4183
4184   /* qtdemux->segment.stop is in outside-time-realm, whereas
4185    * segment->media_stop is in track-time-realm.
4186    *
4187    * In order to compare the two, we need to bring segment.stop
4188    * into the track-time-realm */
4189
4190   stop = qtdemux->segment.stop;
4191   if (stop == GST_CLOCK_TIME_NONE)
4192     stop = qtdemux->segment.duration;
4193   if (stop == GST_CLOCK_TIME_NONE)
4194     stop = segment->media_stop;
4195   else
4196     stop =
4197         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4198
4199   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4200     start = segment->time + seg_time;
4201     time = offset;
4202     stop = start - seg_time + segment->duration;
4203   } else if (qtdemux->segment.rate >= 0) {
4204     start = MIN (segment->media_start + seg_time, stop);
4205     time = offset;
4206   } else {
4207     if (segment->media_start >= qtdemux->segment.start) {
4208       time = segment->time;
4209     } else {
4210       time = segment->time + (qtdemux->segment.start - segment->media_start);
4211     }
4212
4213     start = MAX (segment->media_start, qtdemux->segment.start);
4214     stop = MIN (segment->media_start + seg_time, stop);
4215   }
4216
4217   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4218       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4219       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4220
4221   /* combine global rate with that of the segment */
4222   rate = segment->rate * qtdemux->segment.rate;
4223
4224   /* Copy flags from main segment */
4225   stream->segment.flags = qtdemux->segment.flags;
4226
4227   /* update the segment values used for clipping */
4228   stream->segment.offset = qtdemux->segment.offset;
4229   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4230   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4231   stream->segment.rate = rate;
4232   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4233       stream->cslg_shift);
4234   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4235       stream->cslg_shift);
4236   stream->segment.time = time;
4237   stream->segment.position = stream->segment.start;
4238
4239   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4240       &stream->segment);
4241
4242   /* now prepare and send the segment */
4243   if (stream->pad) {
4244     event = gst_event_new_segment (&stream->segment);
4245     if (stream->segment_seqnum) {
4246       gst_event_set_seqnum (event, stream->segment_seqnum);
4247     }
4248     gst_pad_push_event (stream->pad, event);
4249     /* assume we can send more data now */
4250     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4251     /* clear to send tags on this pad now */
4252     gst_qtdemux_push_tags (qtdemux, stream);
4253   }
4254
4255   /* in the fragmented case, we pick a fragment that starts before our
4256    * desired position and rely on downstream to wait for a keyframe
4257    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4258    * tfra entries tells us which trun/sample the key unit is in, but we don't
4259    * make use of this additional information at the moment) */
4260   if (qtdemux->fragmented) {
4261     stream->to_sample = G_MAXUINT32;
4262     return TRUE;
4263   }
4264
4265   /* We don't need to look for a sample in push-based */
4266   if (!qtdemux->pullbased)
4267     return TRUE;
4268
4269   /* and move to the keyframe before the indicated media time of the
4270    * segment */
4271   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4272     if (qtdemux->segment.rate >= 0) {
4273       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4274       stream->to_sample = G_MAXUINT32;
4275       GST_DEBUG_OBJECT (stream->pad,
4276           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4277           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4278           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4279     } else {
4280       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4281       stream->to_sample = index;
4282       GST_DEBUG_OBJECT (stream->pad,
4283           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4284           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4285           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4286     }
4287   } else {
4288     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4289         "this is an empty segment");
4290     return TRUE;
4291   }
4292
4293   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4294    * encountered an error and printed a message so we return appropriately */
4295   if (index == -1)
4296     return FALSE;
4297
4298   /* we're at the right spot */
4299   if (index == stream->sample_index) {
4300     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4301     return TRUE;
4302   }
4303
4304   /* find keyframe of the target index */
4305   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4306
4307 /* *INDENT-OFF* */
4308 /* indent does stupid stuff with stream->samples[].timestamp */
4309
4310   /* if we move forwards, we don't have to go back to the previous
4311    * keyframe since we already sent that. We can also just jump to
4312    * the keyframe right before the target index if there is one. */
4313   if (index > stream->sample_index) {
4314     /* moving forwards check if we move past a keyframe */
4315     if (kf_index > stream->sample_index) {
4316       GST_DEBUG_OBJECT (stream->pad,
4317            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4318            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4319            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4320       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4321     } else {
4322       GST_DEBUG_OBJECT (stream->pad,
4323           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4324           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4325           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4326     }
4327   } else {
4328     GST_DEBUG_OBJECT (stream->pad,
4329         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4330         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4331         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4332     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4333   }
4334
4335 /* *INDENT-ON* */
4336
4337   return TRUE;
4338 }
4339
4340 /* prepare to get the current sample of @stream, getting essential values.
4341  *
4342  * This function will also prepare and send the segment when needed.
4343  *
4344  * Return FALSE if the stream is EOS.
4345  *
4346  * PULL-BASED
4347  */
4348 static gboolean
4349 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4350     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4351     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4352     gboolean * keyframe)
4353 {
4354   QtDemuxSample *sample;
4355   GstClockTime time_position;
4356   guint32 seg_idx;
4357
4358   g_return_val_if_fail (stream != NULL, FALSE);
4359
4360   time_position = stream->time_position;
4361   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4362     goto eos;
4363
4364   seg_idx = stream->segment_index;
4365   if (G_UNLIKELY (seg_idx == -1)) {
4366     /* find segment corresponding to time_position if we are looking
4367      * for a segment. */
4368     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4369   }
4370
4371   /* different segment, activate it, sample_index will be set. */
4372   if (G_UNLIKELY (stream->segment_index != seg_idx))
4373     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4374
4375   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4376                   segment_index]))) {
4377     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4378
4379     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4380         " prepare empty sample");
4381
4382     *empty = TRUE;
4383     *pts = *dts = time_position;
4384     *duration = seg->duration - (time_position - seg->time);
4385
4386     return TRUE;
4387   }
4388
4389   *empty = FALSE;
4390
4391   if (stream->sample_index == -1)
4392     stream->sample_index = 0;
4393
4394   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4395       stream->sample_index, stream->n_samples);
4396
4397   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4398     if (!qtdemux->fragmented)
4399       goto eos;
4400
4401     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4402     do {
4403       GstFlowReturn flow;
4404
4405       GST_OBJECT_LOCK (qtdemux);
4406       flow = qtdemux_add_fragmented_samples (qtdemux);
4407       GST_OBJECT_UNLOCK (qtdemux);
4408
4409       if (flow != GST_FLOW_OK)
4410         goto eos;
4411     }
4412     while (stream->sample_index >= stream->n_samples);
4413   }
4414
4415   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4416     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4417         stream->sample_index);
4418     return FALSE;
4419   }
4420
4421   /* now get the info for the sample we're at */
4422   sample = &stream->samples[stream->sample_index];
4423
4424   *dts = QTSAMPLE_DTS (stream, sample);
4425   *pts = QTSAMPLE_PTS (stream, sample);
4426   *offset = sample->offset;
4427   *size = sample->size;
4428   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4429   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4430
4431   return TRUE;
4432
4433   /* special cases */
4434 eos:
4435   {
4436     stream->time_position = GST_CLOCK_TIME_NONE;
4437     return FALSE;
4438   }
4439 }
4440
4441 /* move to the next sample in @stream.
4442  *
4443  * Moves to the next segment when needed.
4444  */
4445 static void
4446 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4447 {
4448   QtDemuxSample *sample;
4449   QtDemuxSegment *segment;
4450
4451   /* get current segment */
4452   segment = &stream->segments[stream->segment_index];
4453
4454   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4455     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4456     goto next_segment;
4457   }
4458
4459   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4460     /* Mark the stream as EOS */
4461     GST_DEBUG_OBJECT (qtdemux,
4462         "reached max allowed sample %u, mark EOS", stream->to_sample);
4463     stream->time_position = GST_CLOCK_TIME_NONE;
4464     return;
4465   }
4466
4467   /* move to next sample */
4468   stream->sample_index++;
4469   stream->offset_in_sample = 0;
4470
4471   /* reached the last sample, we need the next segment */
4472   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4473     goto next_segment;
4474
4475   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4476     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4477         stream->sample_index);
4478     return;
4479   }
4480
4481   /* get next sample */
4482   sample = &stream->samples[stream->sample_index];
4483
4484   /* see if we are past the segment */
4485   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4486     goto next_segment;
4487
4488   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4489     /* inside the segment, update time_position, looks very familiar to
4490      * GStreamer segments, doesn't it? */
4491     stream->time_position =
4492         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4493   } else {
4494     /* not yet in segment, time does not yet increment. This means
4495      * that we are still prerolling keyframes to the decoder so it can
4496      * decode the first sample of the segment. */
4497     stream->time_position = segment->time;
4498   }
4499   return;
4500
4501   /* move to the next segment */
4502 next_segment:
4503   {
4504     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4505
4506     if (stream->segment_index == stream->n_segments - 1) {
4507       /* are we at the end of the last segment, we're EOS */
4508       stream->time_position = GST_CLOCK_TIME_NONE;
4509     } else {
4510       /* else we're only at the end of the current segment */
4511       stream->time_position = segment->stop_time;
4512     }
4513     /* make sure we select a new segment */
4514
4515     /* accumulate previous segments */
4516     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4517       stream->accumulated_base +=
4518           (stream->segment.stop -
4519           stream->segment.start) / ABS (stream->segment.rate);
4520
4521     stream->segment_index = -1;
4522   }
4523 }
4524
4525 static void
4526 gst_qtdemux_sync_streams (GstQTDemux * demux)
4527 {
4528   gint i;
4529
4530   if (demux->n_streams <= 1)
4531     return;
4532
4533   for (i = 0; i < demux->n_streams; i++) {
4534     QtDemuxStream *stream;
4535     GstClockTime end_time;
4536
4537     stream = demux->streams[i];
4538
4539     if (!stream->pad)
4540       continue;
4541
4542     /* TODO advance time on subtitle streams here, if any some day */
4543
4544     /* some clips/trailers may have unbalanced streams at the end,
4545      * so send EOS on shorter stream to prevent stalling others */
4546
4547     /* do not mess with EOS if SEGMENT seeking */
4548     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4549       continue;
4550
4551     if (demux->pullbased) {
4552       /* loop mode is sample time based */
4553       if (!STREAM_IS_EOS (stream))
4554         continue;
4555     } else {
4556       /* push mode is byte position based */
4557       if (stream->n_samples &&
4558           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4559         continue;
4560     }
4561
4562     if (stream->sent_eos)
4563       continue;
4564
4565     /* only act if some gap */
4566     end_time = stream->segments[stream->n_segments - 1].stop_time;
4567     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4568         ", stream end: %" GST_TIME_FORMAT,
4569         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4570     if (GST_CLOCK_TIME_IS_VALID (end_time)
4571         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4572       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4573           GST_PAD_NAME (stream->pad));
4574       stream->sent_eos = TRUE;
4575       gst_pad_push_event (stream->pad, gst_event_new_eos ());
4576     }
4577   }
4578 }
4579
4580 /* EOS and NOT_LINKED need to be combined. This means that we return:
4581  *
4582  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4583  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4584  */
4585 static GstFlowReturn
4586 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4587     GstFlowReturn ret)
4588 {
4589   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4590
4591   if (stream->pad)
4592     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4593         ret);
4594   else
4595     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4596
4597   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4598   return ret;
4599 }
4600
4601 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4602  * completely clipped
4603  *
4604  * Should be used only with raw buffers */
4605 static GstBuffer *
4606 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4607     GstBuffer * buf)
4608 {
4609   guint64 start, stop, cstart, cstop, diff;
4610   GstClockTime pts, duration;
4611   gsize size, osize;
4612   gint num_rate, denom_rate;
4613   gint frame_size;
4614   gboolean clip_data;
4615   guint offset;
4616
4617   osize = size = gst_buffer_get_size (buf);
4618   offset = 0;
4619
4620   /* depending on the type, setup the clip parameters */
4621   if (stream->subtype == FOURCC_soun) {
4622     frame_size = stream->bytes_per_frame;
4623     num_rate = GST_SECOND;
4624     denom_rate = (gint) stream->rate;
4625     clip_data = TRUE;
4626   } else if (stream->subtype == FOURCC_vide) {
4627     frame_size = size;
4628     num_rate = stream->fps_n;
4629     denom_rate = stream->fps_d;
4630     clip_data = FALSE;
4631   } else
4632     goto wrong_type;
4633
4634   if (frame_size <= 0)
4635     goto bad_frame_size;
4636
4637   /* we can only clip if we have a valid pts */
4638   pts = GST_BUFFER_PTS (buf);
4639   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
4640     goto no_pts;
4641
4642   duration = GST_BUFFER_DURATION (buf);
4643
4644   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
4645     duration =
4646         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
4647   }
4648
4649   start = pts;
4650   stop = start + duration;
4651
4652   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
4653               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
4654     goto clipped;
4655
4656   /* see if some clipping happened */
4657   diff = cstart - start;
4658   if (diff > 0) {
4659     pts += diff;
4660     duration -= diff;
4661
4662     if (clip_data) {
4663       /* bring clipped time to samples and to bytes */
4664       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4665       diff *= frame_size;
4666
4667       GST_DEBUG_OBJECT (qtdemux,
4668           "clipping start to %" GST_TIME_FORMAT " %"
4669           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
4670
4671       offset = diff;
4672       size -= diff;
4673     }
4674   }
4675   diff = stop - cstop;
4676   if (diff > 0) {
4677     duration -= diff;
4678
4679     if (clip_data) {
4680       /* bring clipped time to samples and then to bytes */
4681       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4682       diff *= frame_size;
4683       GST_DEBUG_OBJECT (qtdemux,
4684           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
4685           " bytes", GST_TIME_ARGS (cstop), diff);
4686       size -= diff;
4687     }
4688   }
4689
4690   if (offset != 0 || size != osize)
4691     gst_buffer_resize (buf, offset, size);
4692
4693   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
4694   GST_BUFFER_PTS (buf) = pts;
4695   GST_BUFFER_DURATION (buf) = duration;
4696
4697   return buf;
4698
4699   /* dropped buffer */
4700 wrong_type:
4701   {
4702     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
4703     return buf;
4704   }
4705 bad_frame_size:
4706   {
4707     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
4708     return buf;
4709   }
4710 no_pts:
4711   {
4712     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
4713     return buf;
4714   }
4715 clipped:
4716   {
4717     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
4718     gst_buffer_unref (buf);
4719     return NULL;
4720   }
4721 }
4722
4723 /* the input buffer metadata must be writable,
4724  * but time/duration etc not yet set and need not be preserved */
4725 static GstBuffer *
4726 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4727     GstBuffer * buf)
4728 {
4729   GstMapInfo map;
4730   guint nsize = 0;
4731   gchar *str;
4732
4733   /* not many cases for now */
4734   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
4735     /* send a one time dvd clut event */
4736     if (stream->pending_event && stream->pad)
4737       gst_pad_push_event (stream->pad, stream->pending_event);
4738     stream->pending_event = NULL;
4739   }
4740
4741   if (G_UNLIKELY (stream->subtype != FOURCC_text
4742           && stream->subtype != FOURCC_sbtl &&
4743           stream->subtype != FOURCC_subp)) {
4744     return buf;
4745   }
4746
4747   gst_buffer_map (buf, &map, GST_MAP_READ);
4748
4749   /* empty buffer is sent to terminate previous subtitle */
4750   if (map.size <= 2) {
4751     gst_buffer_unmap (buf, &map);
4752     gst_buffer_unref (buf);
4753     return NULL;
4754   }
4755   if (stream->subtype == FOURCC_subp) {
4756     /* That's all the processing needed for subpictures */
4757     gst_buffer_unmap (buf, &map);
4758     return buf;
4759   }
4760
4761   nsize = GST_READ_UINT16_BE (map.data);
4762   nsize = MIN (nsize, map.size - 2);
4763
4764   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
4765       nsize, map.size);
4766
4767   /* takes care of UTF-8 validation or UTF-16 recognition,
4768    * no other encoding expected */
4769   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
4770   gst_buffer_unmap (buf, &map);
4771   if (str) {
4772     gst_buffer_unref (buf);
4773     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
4774   } else {
4775     /* this should not really happen unless the subtitle is corrupted */
4776     gst_buffer_unref (buf);
4777     buf = NULL;
4778   }
4779
4780   /* FIXME ? convert optional subsequent style info to markup */
4781
4782   return buf;
4783 }
4784
4785 /* Sets a buffer's attributes properly and pushes it downstream.
4786  * Also checks for additional actions and custom processing that may
4787  * need to be done first.
4788  */
4789 static GstFlowReturn
4790 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
4791     QtDemuxStream * stream, GstBuffer * buf,
4792     GstClockTime dts, GstClockTime pts, GstClockTime duration,
4793     gboolean keyframe, GstClockTime position, guint64 byte_position)
4794 {
4795   GstFlowReturn ret = GST_FLOW_OK;
4796
4797   /* offset the timestamps according to the edit list */
4798
4799   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
4800     gchar *url;
4801     GstMapInfo map;
4802
4803     gst_buffer_map (buf, &map, GST_MAP_READ);
4804     url = g_strndup ((gchar *) map.data, map.size);
4805     gst_buffer_unmap (buf, &map);
4806     if (url != NULL && strlen (url) != 0) {
4807       /* we have RTSP redirect now */
4808       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
4809           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
4810               gst_structure_new ("redirect",
4811                   "new-location", G_TYPE_STRING, url, NULL)));
4812       qtdemux->posted_redirect = TRUE;
4813     } else {
4814       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
4815           "posting");
4816     }
4817     g_free (url);
4818   }
4819
4820   /* position reporting */
4821   if (qtdemux->segment.rate >= 0) {
4822     qtdemux->segment.position = position;
4823     gst_qtdemux_sync_streams (qtdemux);
4824   }
4825
4826   if (G_UNLIKELY (!stream->pad)) {
4827     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
4828     gst_buffer_unref (buf);
4829     goto exit;
4830   }
4831
4832   /* send out pending buffers */
4833   while (stream->buffers) {
4834     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
4835
4836     if (G_UNLIKELY (stream->discont)) {
4837       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4838       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
4839       stream->discont = FALSE;
4840     } else {
4841       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4842     }
4843
4844     gst_pad_push (stream->pad, buffer);
4845
4846     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
4847   }
4848
4849   /* we're going to modify the metadata */
4850   buf = gst_buffer_make_writable (buf);
4851
4852   if (G_UNLIKELY (stream->need_process))
4853     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
4854
4855   if (!buf) {
4856     goto exit;
4857   }
4858
4859   GST_BUFFER_DTS (buf) = dts;
4860   GST_BUFFER_PTS (buf) = pts;
4861   GST_BUFFER_DURATION (buf) = duration;
4862   GST_BUFFER_OFFSET (buf) = -1;
4863   GST_BUFFER_OFFSET_END (buf) = -1;
4864
4865   if (G_UNLIKELY (stream->rgb8_palette))
4866     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
4867
4868   if (G_UNLIKELY (stream->padding)) {
4869     gst_buffer_resize (buf, stream->padding, -1);
4870   }
4871 #if 0
4872   if (G_UNLIKELY (qtdemux->element_index)) {
4873     GstClockTime stream_time;
4874
4875     stream_time =
4876         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
4877         timestamp);
4878     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
4879       GST_LOG_OBJECT (qtdemux,
4880           "adding association %" GST_TIME_FORMAT "-> %"
4881           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
4882       gst_index_add_association (qtdemux->element_index,
4883           qtdemux->index_id,
4884           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
4885           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
4886           GST_FORMAT_BYTES, byte_position, NULL);
4887     }
4888   }
4889 #endif
4890
4891   if (stream->need_clip)
4892     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
4893
4894   if (G_UNLIKELY (buf == NULL))
4895     goto exit;
4896
4897   if (G_UNLIKELY (stream->discont)) {
4898     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4899     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
4900     stream->discont = FALSE;
4901   } else {
4902     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4903   }
4904
4905   if (!keyframe) {
4906     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
4907     stream->on_keyframe = FALSE;
4908   } else {
4909     stream->on_keyframe = TRUE;
4910   }
4911
4912
4913   GST_LOG_OBJECT (qtdemux,
4914       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
4915       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
4916       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
4917       GST_PAD_NAME (stream->pad));
4918
4919   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
4920     GstStructure *crypto_info;
4921     QtDemuxCencSampleSetInfo *info =
4922         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4923     gint index;
4924     GstEvent *event;
4925
4926     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
4927       gst_pad_push_event (stream->pad, event);
4928     }
4929
4930     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
4931     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
4932       /* steal structure from array */
4933       crypto_info = g_ptr_array_index (info->crypto_info, index);
4934       g_ptr_array_index (info->crypto_info, index) = NULL;
4935       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
4936       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
4937         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
4938     }
4939   }
4940
4941   ret = gst_pad_push (stream->pad, buf);
4942
4943   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
4944     /* mark position in stream, we'll need this to know when to send GAP event */
4945     stream->segment.position = pts + duration;
4946   }
4947
4948 exit:
4949   return ret;
4950 }
4951
4952 static const QtDemuxRandomAccessEntry *
4953 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4954     GstClockTime pos, gboolean after)
4955 {
4956   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
4957   guint n_entries = stream->n_ra_entries;
4958   guint i;
4959
4960   /* we assume the table is sorted */
4961   for (i = 0; i < n_entries; ++i) {
4962     if (entries[i].ts > pos)
4963       break;
4964   }
4965
4966   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
4967    * probably okay to assume that the index lists the very first fragment */
4968   if (i == 0)
4969     return &entries[0];
4970
4971   if (after)
4972     return &entries[i];
4973   else
4974     return &entries[i - 1];
4975 }
4976
4977 static gboolean
4978 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
4979 {
4980   const QtDemuxRandomAccessEntry *best_entry = NULL;
4981   guint i;
4982
4983   GST_OBJECT_LOCK (qtdemux);
4984
4985   g_assert (qtdemux->n_streams > 0);
4986
4987   for (i = 0; i < qtdemux->n_streams; i++) {
4988     const QtDemuxRandomAccessEntry *entry;
4989     QtDemuxStream *stream;
4990     gboolean is_audio_or_video;
4991
4992     stream = qtdemux->streams[i];
4993
4994     g_free (stream->samples);
4995     stream->samples = NULL;
4996     stream->n_samples = 0;
4997     stream->stbl_index = -1;    /* no samples have yet been parsed */
4998     stream->sample_index = -1;
4999
5000     if (stream->ra_entries == NULL)
5001       continue;
5002
5003     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5004       is_audio_or_video = TRUE;
5005     else
5006       is_audio_or_video = FALSE;
5007
5008     entry =
5009         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5010         stream->time_position, !is_audio_or_video);
5011
5012     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5013         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5014
5015     stream->pending_seek = entry;
5016
5017     /* decide position to jump to just based on audio/video tracks, not subs */
5018     if (!is_audio_or_video)
5019       continue;
5020
5021     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5022       best_entry = entry;
5023   }
5024
5025   if (best_entry == NULL) {
5026     GST_OBJECT_UNLOCK (qtdemux);
5027     return FALSE;
5028   }
5029
5030   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5031       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5032       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5033       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5034
5035   qtdemux->moof_offset = best_entry->moof_offset;
5036
5037   qtdemux_add_fragmented_samples (qtdemux);
5038
5039   GST_OBJECT_UNLOCK (qtdemux);
5040   return TRUE;
5041 }
5042
5043 static GstFlowReturn
5044 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5045 {
5046   GstFlowReturn ret = GST_FLOW_OK;
5047   GstBuffer *buf = NULL;
5048   QtDemuxStream *stream;
5049   GstClockTime min_time;
5050   guint64 offset = 0;
5051   GstClockTime dts = GST_CLOCK_TIME_NONE;
5052   GstClockTime pts = GST_CLOCK_TIME_NONE;
5053   GstClockTime duration = 0;
5054   gboolean keyframe = FALSE;
5055   guint sample_size = 0;
5056   gboolean empty = 0;
5057   guint size;
5058   gint index;
5059   gint i;
5060
5061   gst_qtdemux_push_pending_newsegment (qtdemux);
5062
5063   if (qtdemux->fragmented_seek_pending) {
5064     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5065     gst_qtdemux_do_fragmented_seek (qtdemux);
5066     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5067     qtdemux->fragmented_seek_pending = FALSE;
5068   }
5069
5070   /* Figure out the next stream sample to output, min_time is expressed in
5071    * global time and runs over the edit list segments. */
5072   min_time = G_MAXUINT64;
5073   index = -1;
5074   for (i = 0; i < qtdemux->n_streams; i++) {
5075     GstClockTime position;
5076
5077     stream = qtdemux->streams[i];
5078     position = stream->time_position;
5079
5080     /* position of -1 is EOS */
5081     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5082       min_time = position;
5083       index = i;
5084     }
5085   }
5086   /* all are EOS */
5087   if (G_UNLIKELY (index == -1)) {
5088     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5089     goto eos;
5090   }
5091
5092   /* check for segment end */
5093   if (G_UNLIKELY (qtdemux->segment.stop != -1
5094           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5095               || (qtdemux->segment.rate < 0
5096                   && qtdemux->segment.start > min_time))
5097           && qtdemux->streams[index]->on_keyframe)) {
5098     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5099     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5100     goto eos_stream;
5101   }
5102
5103   /* gap events for subtitle streams */
5104   for (i = 0; i < qtdemux->n_streams; i++) {
5105     stream = qtdemux->streams[i];
5106     if (stream->pad && (stream->subtype == FOURCC_subp
5107             || stream->subtype == FOURCC_text
5108             || stream->subtype == FOURCC_sbtl)) {
5109       /* send one second gap events until the stream catches up */
5110       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5111       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5112           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5113           stream->segment.position + GST_SECOND < min_time) {
5114         GstEvent *gap =
5115             gst_event_new_gap (stream->segment.position, GST_SECOND);
5116         gst_pad_push_event (stream->pad, gap);
5117         stream->segment.position += GST_SECOND;
5118       }
5119     }
5120   }
5121
5122   stream = qtdemux->streams[index];
5123   if (stream->new_caps) {
5124     gst_qtdemux_configure_stream (qtdemux, stream);
5125     qtdemux_do_allocation (qtdemux, stream);
5126   }
5127
5128   /* fetch info for the current sample of this stream */
5129   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5130               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5131     goto eos_stream;
5132
5133   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5134   if (G_UNLIKELY (qtdemux->
5135           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5136     if (stream->subtype == FOURCC_vide && !keyframe) {
5137       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5138       goto next;
5139     }
5140   }
5141
5142   GST_DEBUG_OBJECT (qtdemux,
5143       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5144       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5145       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5146       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5147
5148   if (G_UNLIKELY (empty)) {
5149     /* empty segment, push a gap and move to the next one */
5150     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5151     stream->segment.position = pts + duration;
5152     goto next;
5153   }
5154
5155   /* hmm, empty sample, skip and move to next sample */
5156   if (G_UNLIKELY (sample_size <= 0))
5157     goto next;
5158
5159   /* last pushed sample was out of boundary, goto next sample */
5160   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5161     goto next;
5162
5163   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5164     size = sample_size;
5165   } else {
5166     GST_DEBUG_OBJECT (qtdemux,
5167         "size %d larger than stream max_buffer_size %d, trimming",
5168         sample_size, stream->max_buffer_size);
5169     size =
5170         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5171   }
5172
5173   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5174       offset);
5175
5176   if (stream->use_allocator) {
5177     /* if we have a per-stream allocator, use it */
5178     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5179   }
5180
5181   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5182       size, &buf);
5183   if (G_UNLIKELY (ret != GST_FLOW_OK))
5184     goto beach;
5185
5186   if (size != sample_size) {
5187     pts += gst_util_uint64_scale_int (GST_SECOND,
5188         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5189     dts += gst_util_uint64_scale_int (GST_SECOND,
5190         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5191     duration = gst_util_uint64_scale_int (GST_SECOND,
5192         size / stream->bytes_per_frame, stream->timescale);
5193   }
5194
5195   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5196       dts, pts, duration, keyframe, min_time, offset);
5197
5198   if (size != sample_size) {
5199     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5200     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5201
5202     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5203         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5204     if (time_position >= segment->media_start) {
5205       /* inside the segment, update time_position, looks very familiar to
5206        * GStreamer segments, doesn't it? */
5207       stream->time_position = (time_position - segment->media_start) +
5208           segment->time;
5209     } else {
5210       /* not yet in segment, time does not yet increment. This means
5211        * that we are still prerolling keyframes to the decoder so it can
5212        * decode the first sample of the segment. */
5213       stream->time_position = segment->time;
5214     }
5215   }
5216
5217   /* combine flows */
5218   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5219   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5220    * we have no more data for the pad to push */
5221   if (ret == GST_FLOW_EOS)
5222     ret = GST_FLOW_OK;
5223
5224   stream->offset_in_sample += size;
5225   if (stream->offset_in_sample >= sample_size) {
5226     gst_qtdemux_advance_sample (qtdemux, stream);
5227   }
5228   goto beach;
5229
5230 next:
5231   gst_qtdemux_advance_sample (qtdemux, stream);
5232
5233 beach:
5234   return ret;
5235
5236   /* special cases */
5237 eos:
5238   {
5239     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5240     ret = GST_FLOW_EOS;
5241     goto beach;
5242   }
5243 eos_stream:
5244   {
5245     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5246     /* EOS will be raised if all are EOS */
5247     ret = GST_FLOW_OK;
5248     goto beach;
5249   }
5250 }
5251
5252 static void
5253 gst_qtdemux_loop (GstPad * pad)
5254 {
5255   GstQTDemux *qtdemux;
5256   guint64 cur_offset;
5257   GstFlowReturn ret;
5258
5259   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5260
5261   cur_offset = qtdemux->offset;
5262   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
5263       cur_offset, qtdemux->state);
5264
5265   switch (qtdemux->state) {
5266     case QTDEMUX_STATE_INITIAL:
5267     case QTDEMUX_STATE_HEADER:
5268       ret = gst_qtdemux_loop_state_header (qtdemux);
5269       break;
5270     case QTDEMUX_STATE_MOVIE:
5271       ret = gst_qtdemux_loop_state_movie (qtdemux);
5272       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5273         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5274       }
5275       break;
5276     default:
5277       /* ouch */
5278       goto invalid_state;
5279   }
5280
5281   /* if something went wrong, pause */
5282   if (ret != GST_FLOW_OK)
5283     goto pause;
5284
5285 done:
5286   gst_object_unref (qtdemux);
5287   return;
5288
5289   /* ERRORS */
5290 invalid_state:
5291   {
5292     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5293         (NULL), ("streaming stopped, invalid state"));
5294     gst_pad_pause_task (pad);
5295     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5296     goto done;
5297   }
5298 pause:
5299   {
5300     const gchar *reason = gst_flow_get_name (ret);
5301
5302     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5303
5304     gst_pad_pause_task (pad);
5305
5306     /* fatal errors need special actions */
5307     /* check EOS */
5308     if (ret == GST_FLOW_EOS) {
5309       if (qtdemux->n_streams == 0) {
5310         /* we have no streams, post an error */
5311         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5312       }
5313       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5314         gint64 stop;
5315
5316         if ((stop = qtdemux->segment.stop) == -1)
5317           stop = qtdemux->segment.duration;
5318
5319         if (qtdemux->segment.rate >= 0) {
5320           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5321           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5322               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5323                   GST_FORMAT_TIME, stop));
5324           gst_qtdemux_push_event (qtdemux,
5325               gst_event_new_segment_done (GST_FORMAT_TIME, stop));
5326         } else {
5327           /*  For Reverse Playback */
5328           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5329           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5330               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5331                   GST_FORMAT_TIME, qtdemux->segment.start));
5332           gst_qtdemux_push_event (qtdemux,
5333               gst_event_new_segment_done (GST_FORMAT_TIME,
5334                   qtdemux->segment.start));
5335         }
5336       } else {
5337         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5338         gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5339       }
5340     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5341       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5342           (NULL), ("streaming stopped, reason %s", reason));
5343       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5344     }
5345     goto done;
5346   }
5347 }
5348
5349 /*
5350  * has_next_entry
5351  *
5352  * Returns if there are samples to be played.
5353  */
5354 static gboolean
5355 has_next_entry (GstQTDemux * demux)
5356 {
5357   QtDemuxStream *stream;
5358   int i;
5359
5360   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5361
5362   for (i = 0; i < demux->n_streams; i++) {
5363     stream = demux->streams[i];
5364
5365     if (stream->sample_index == -1) {
5366       stream->sample_index = 0;
5367       stream->offset_in_sample = 0;
5368     }
5369
5370     if (stream->sample_index >= stream->n_samples) {
5371       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5372       continue;
5373     }
5374     GST_DEBUG_OBJECT (demux, "Found a sample");
5375     return TRUE;
5376   }
5377
5378   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5379   return FALSE;
5380 }
5381
5382 /*
5383  * next_entry_size
5384  *
5385  * Returns the size of the first entry at the current offset.
5386  * If -1, there are none (which means EOS or empty file).
5387  */
5388 static guint64
5389 next_entry_size (GstQTDemux * demux)
5390 {
5391   QtDemuxStream *stream;
5392   int i;
5393   int smallidx = -1;
5394   guint64 smalloffs = (guint64) - 1;
5395   QtDemuxSample *sample;
5396
5397   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5398       demux->offset);
5399
5400   for (i = 0; i < demux->n_streams; i++) {
5401     stream = demux->streams[i];
5402
5403     if (stream->sample_index == -1) {
5404       stream->sample_index = 0;
5405       stream->offset_in_sample = 0;
5406     }
5407
5408     if (stream->sample_index >= stream->n_samples) {
5409       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5410       continue;
5411     }
5412
5413     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5414       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5415           stream->sample_index);
5416       return -1;
5417     }
5418
5419     sample = &stream->samples[stream->sample_index];
5420
5421     GST_LOG_OBJECT (demux,
5422         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5423         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5424         sample->offset, sample->size);
5425
5426     if (((smalloffs == -1)
5427             || (sample->offset < smalloffs)) && (sample->size)) {
5428       smallidx = i;
5429       smalloffs = sample->offset;
5430     }
5431   }
5432
5433   GST_LOG_OBJECT (demux,
5434       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5435       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5436
5437   if (smallidx == -1)
5438     return -1;
5439
5440   stream = demux->streams[smallidx];
5441   sample = &stream->samples[stream->sample_index];
5442
5443   if (sample->offset >= demux->offset) {
5444     demux->todrop = sample->offset - demux->offset;
5445     return sample->size + demux->todrop;
5446   }
5447
5448   GST_DEBUG_OBJECT (demux,
5449       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5450   return -1;
5451 }
5452
5453 static void
5454 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5455 {
5456   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5457
5458   gst_element_post_message (GST_ELEMENT_CAST (demux),
5459       gst_message_new_element (GST_OBJECT_CAST (demux),
5460           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5461 }
5462
5463 static gboolean
5464 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5465 {
5466   GstEvent *event;
5467   gboolean res = 0;
5468
5469   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5470
5471   event =
5472       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5473       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5474       GST_SEEK_TYPE_NONE, -1);
5475
5476   res = gst_pad_push_event (demux->sinkpad, event);
5477
5478   return res;
5479 }
5480
5481 /* check for seekable upstream, above and beyond a mere query */
5482 static void
5483 gst_qtdemux_check_seekability (GstQTDemux * demux)
5484 {
5485   GstQuery *query;
5486   gboolean seekable = FALSE;
5487   gint64 start = -1, stop = -1;
5488
5489   if (demux->upstream_size)
5490     return;
5491
5492   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5493   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5494     GST_DEBUG_OBJECT (demux, "seeking query failed");
5495     goto done;
5496   }
5497
5498   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5499
5500   /* try harder to query upstream size if we didn't get it the first time */
5501   if (seekable && stop == -1) {
5502     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5503     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5504   }
5505
5506   /* if upstream doesn't know the size, it's likely that it's not seekable in
5507    * practice even if it technically may be seekable */
5508   if (seekable && (start != 0 || stop <= start)) {
5509     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5510     seekable = FALSE;
5511   }
5512
5513 done:
5514   gst_query_unref (query);
5515
5516   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5517       G_GUINT64_FORMAT ")", seekable, start, stop);
5518   demux->upstream_seekable = seekable;
5519   demux->upstream_size = seekable ? stop : -1;
5520 }
5521
5522 static void
5523 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5524 {
5525   g_return_if_fail (bytes <= demux->todrop);
5526
5527   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5528   gst_adapter_flush (demux->adapter, bytes);
5529   demux->neededbytes -= bytes;
5530   demux->offset += bytes;
5531   demux->todrop -= bytes;
5532 }
5533
5534 static void
5535 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5536 {
5537   if (G_UNLIKELY (demux->pending_newsegment)) {
5538     gint i;
5539
5540     gst_qtdemux_push_pending_newsegment (demux);
5541     /* clear to send tags on all streams */
5542     for (i = 0; i < demux->n_streams; i++) {
5543       QtDemuxStream *stream;
5544       stream = demux->streams[i];
5545       gst_qtdemux_push_tags (demux, stream);
5546       if (stream->sparse) {
5547         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5548         gst_pad_push_event (stream->pad,
5549             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
5550       }
5551     }
5552   }
5553 }
5554
5555 static void
5556 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
5557     QtDemuxStream * stream)
5558 {
5559   gint i;
5560
5561   /* Push any initial gap segments before proceeding to the
5562    * 'real' data */
5563   for (i = 0; i < stream->n_segments; i++) {
5564     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
5565
5566     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
5567       GstClockTime ts, dur;
5568       GstEvent *gap;
5569
5570       ts = stream->time_position;
5571       dur =
5572           stream->segments[i].duration - (stream->time_position -
5573           stream->segments[i].time);
5574       gap = gst_event_new_gap (ts, dur);
5575       stream->time_position += dur;
5576
5577       GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
5578           "segment: %" GST_PTR_FORMAT, gap);
5579       gst_pad_push_event (stream->pad, gap);
5580     } else {
5581       /* Only support empty segment at the beginning followed by
5582        * one non-empty segment, this was checked when parsing the
5583        * edts atom, arriving here is unexpected */
5584       g_assert (i + 1 == stream->n_segments);
5585       break;
5586     }
5587   }
5588 }
5589
5590 static GstFlowReturn
5591 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
5592 {
5593   GstQTDemux *demux;
5594
5595   demux = GST_QTDEMUX (parent);
5596
5597   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
5598     gint i;
5599
5600     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
5601
5602     for (i = 0; i < demux->n_streams; i++) {
5603       demux->streams[i]->discont = TRUE;
5604     }
5605
5606     /* Reverse fragmented playback, need to flush all we have before
5607      * consuming a new fragment.
5608      * The samples array have the timestamps calculated by accumulating the
5609      * durations but this won't work for reverse playback of fragments as
5610      * the timestamps of a subsequent fragment should be smaller than the
5611      * previously received one. */
5612     if (demux->fragmented && demux->segment.rate < 0) {
5613       gst_qtdemux_process_adapter (demux, TRUE);
5614       for (i = 0; i < demux->n_streams; i++)
5615         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
5616     }
5617   }
5618
5619   gst_adapter_push (demux->adapter, inbuf);
5620
5621   GST_DEBUG_OBJECT (demux,
5622       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
5623       demux->neededbytes, gst_adapter_available (demux->adapter));
5624
5625   return gst_qtdemux_process_adapter (demux, FALSE);
5626 }
5627
5628 static GstFlowReturn
5629 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
5630 {
5631   GstFlowReturn ret = GST_FLOW_OK;
5632
5633   /* we never really mean to buffer that much */
5634   if (demux->neededbytes == -1) {
5635     goto eos;
5636   }
5637
5638   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
5639       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
5640
5641     GST_DEBUG_OBJECT (demux,
5642         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
5643         demux->state, demux->neededbytes, demux->offset);
5644
5645     switch (demux->state) {
5646       case QTDEMUX_STATE_INITIAL:{
5647         const guint8 *data;
5648         guint32 fourcc;
5649         guint64 size;
5650
5651         gst_qtdemux_check_seekability (demux);
5652
5653         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5654
5655         /* get fourcc/length, set neededbytes */
5656         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
5657             &size, &fourcc);
5658         gst_adapter_unmap (demux->adapter);
5659         data = NULL;
5660         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
5661             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
5662         if (size == 0) {
5663           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5664               (_("This file is invalid and cannot be played.")),
5665               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
5666                   GST_FOURCC_ARGS (fourcc)));
5667           ret = GST_FLOW_ERROR;
5668           break;
5669         }
5670         if (fourcc == FOURCC_mdat) {
5671           gint next_entry = next_entry_size (demux);
5672           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
5673             /* we have the headers, start playback */
5674             demux->state = QTDEMUX_STATE_MOVIE;
5675             demux->neededbytes = next_entry;
5676             demux->mdatleft = size;
5677           } else {
5678             /* no headers yet, try to get them */
5679             guint bs;
5680             gboolean res;
5681             guint64 old, target;
5682
5683           buffer_data:
5684             old = demux->offset;
5685             target = old + size;
5686
5687             /* try to jump over the atom with a seek */
5688             /* only bother if it seems worth doing so,
5689              * and avoids possible upstream/server problems */
5690             if (demux->upstream_seekable &&
5691                 demux->upstream_size > 4 * (1 << 20)) {
5692               res = qtdemux_seek_offset (demux, target);
5693             } else {
5694               GST_DEBUG_OBJECT (demux, "skipping seek");
5695               res = FALSE;
5696             }
5697
5698             if (res) {
5699               GST_DEBUG_OBJECT (demux, "seek success");
5700               /* remember the offset fo the first mdat so we can seek back to it
5701                * after we have the headers */
5702               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
5703                 demux->first_mdat = old;
5704                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
5705                     demux->first_mdat);
5706               }
5707               /* seek worked, continue reading */
5708               demux->offset = target;
5709               demux->neededbytes = 16;
5710               demux->state = QTDEMUX_STATE_INITIAL;
5711             } else {
5712               /* seek failed, need to buffer */
5713               demux->offset = old;
5714               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
5715               /* there may be multiple mdat (or alike) buffers */
5716               /* sanity check */
5717               if (demux->mdatbuffer)
5718                 bs = gst_buffer_get_size (demux->mdatbuffer);
5719               else
5720                 bs = 0;
5721               if (size + bs > 10 * (1 << 20))
5722                 goto no_moov;
5723               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
5724               demux->neededbytes = size;
5725               if (!demux->mdatbuffer)
5726                 demux->mdatoffset = demux->offset;
5727             }
5728           }
5729         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
5730           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5731               (_("This file is invalid and cannot be played.")),
5732               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
5733                   GST_FOURCC_ARGS (fourcc), size));
5734           ret = GST_FLOW_ERROR;
5735           break;
5736         } else {
5737           /* this means we already started buffering and still no moov header,
5738            * let's continue buffering everything till we get moov */
5739           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
5740                   || fourcc == FOURCC_moof))
5741             goto buffer_data;
5742           demux->neededbytes = size;
5743           demux->state = QTDEMUX_STATE_HEADER;
5744         }
5745         break;
5746       }
5747       case QTDEMUX_STATE_HEADER:{
5748         const guint8 *data;
5749         guint32 fourcc;
5750
5751         GST_DEBUG_OBJECT (demux, "In header");
5752
5753         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5754
5755         /* parse the header */
5756         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
5757             &fourcc);
5758         if (fourcc == FOURCC_moov) {
5759           gint n;
5760
5761           /* in usual fragmented setup we could try to scan for more
5762            * and end up at the the moov (after mdat) again */
5763           if (demux->got_moov && demux->n_streams > 0 &&
5764               (!demux->fragmented
5765                   || demux->last_moov_offset == demux->offset)) {
5766             GST_DEBUG_OBJECT (demux,
5767                 "Skipping moov atom as we have (this) one already");
5768           } else {
5769             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
5770
5771             if (demux->got_moov && demux->fragmented) {
5772               GST_DEBUG_OBJECT (demux,
5773                   "Got a second moov, clean up data from old one");
5774               if (demux->moov_node)
5775                 g_node_destroy (demux->moov_node);
5776               demux->moov_node = NULL;
5777               demux->moov_node_compressed = NULL;
5778             } else {
5779               /* prepare newsegment to send when streaming actually starts */
5780               if (!demux->pending_newsegment)
5781                 demux->pending_newsegment =
5782                     gst_event_new_segment (&demux->segment);
5783             }
5784
5785             demux->last_moov_offset = demux->offset;
5786
5787             qtdemux_parse_moov (demux, data, demux->neededbytes);
5788             qtdemux_node_dump (demux, demux->moov_node);
5789             qtdemux_parse_tree (demux);
5790             qtdemux_prepare_streams (demux);
5791             if (!demux->got_moov)
5792               qtdemux_expose_streams (demux);
5793             else {
5794
5795               for (n = 0; n < demux->n_streams; n++) {
5796                 QtDemuxStream *stream = demux->streams[n];
5797
5798                 gst_qtdemux_configure_stream (demux, stream);
5799               }
5800             }
5801
5802             demux->got_moov = TRUE;
5803             gst_qtdemux_check_send_pending_segment (demux);
5804             for (n = 0; n < demux->n_streams; n++) {
5805               gst_qtdemux_stream_send_initial_gap_segments (demux,
5806                   demux->streams[n]);
5807             }
5808
5809             g_node_destroy (demux->moov_node);
5810             demux->moov_node = NULL;
5811             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
5812           }
5813         } else if (fourcc == FOURCC_moof) {
5814           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
5815             guint64 dist = 0;
5816             GstClockTime prev_pts;
5817             guint64 prev_offset;
5818
5819             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
5820
5821             /*
5822              * The timestamp of the moof buffer is relevant as some scenarios
5823              * won't have the initial timestamp in the atoms. Whenever a new
5824              * buffer has started, we get that buffer's PTS and use it as a base
5825              * timestamp for the trun entries.
5826              *
5827              * To keep track of the current buffer timestamp and starting point
5828              * we use gst_adapter_prev_pts that gives us the PTS and the distance
5829              * from the beggining of the buffer, with the distance and demux->offset
5830              * we know if it is still the same buffer or not.
5831              */
5832             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
5833             prev_offset = demux->offset - dist;
5834             if (demux->fragment_start_offset == -1
5835                 || prev_offset > demux->fragment_start_offset) {
5836               demux->fragment_start_offset = prev_offset;
5837               demux->fragment_start = prev_pts;
5838               GST_DEBUG_OBJECT (demux,
5839                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
5840                   GST_TIME_FORMAT, demux->fragment_start_offset,
5841                   GST_TIME_ARGS (demux->fragment_start));
5842             }
5843
5844             demux->moof_offset = demux->offset;
5845             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
5846                     demux->offset, NULL)) {
5847               gst_adapter_unmap (demux->adapter);
5848               ret = GST_FLOW_ERROR;
5849               goto done;
5850             }
5851             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
5852             if (demux->mss_mode && !demux->exposed) {
5853               if (!demux->pending_newsegment) {
5854                 GstSegment segment;
5855                 gst_segment_init (&segment, GST_FORMAT_TIME);
5856                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
5857                 demux->pending_newsegment = gst_event_new_segment (&segment);
5858               }
5859               qtdemux_expose_streams (demux);
5860             }
5861           } else {
5862             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
5863           }
5864         } else if (fourcc == FOURCC_ftyp) {
5865           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
5866           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
5867         } else if (fourcc == FOURCC_uuid) {
5868           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
5869           qtdemux_parse_uuid (demux, data, demux->neededbytes);
5870         } else if (fourcc == FOURCC_sidx) {
5871           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
5872           qtdemux_parse_sidx (demux, data, demux->neededbytes);
5873         } else {
5874           GST_WARNING_OBJECT (demux,
5875               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
5876               GST_FOURCC_ARGS (fourcc));
5877           /* Let's jump that one and go back to initial state */
5878         }
5879         gst_adapter_unmap (demux->adapter);
5880         data = NULL;
5881
5882         if (demux->mdatbuffer && demux->n_streams) {
5883           gsize remaining_data_size = 0;
5884
5885           /* the mdat was before the header */
5886           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
5887               demux->n_streams, demux->mdatbuffer);
5888           /* restore our adapter/offset view of things with upstream;
5889            * put preceding buffered data ahead of current moov data.
5890            * This should also handle evil mdat, moov, mdat cases and alike */
5891           gst_adapter_flush (demux->adapter, demux->neededbytes);
5892
5893           /* Store any remaining data after the mdat for later usage */
5894           remaining_data_size = gst_adapter_available (demux->adapter);
5895           if (remaining_data_size > 0) {
5896             g_assert (demux->restoredata_buffer == NULL);
5897             demux->restoredata_buffer =
5898                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
5899             demux->restoredata_offset = demux->offset + demux->neededbytes;
5900             GST_DEBUG_OBJECT (demux,
5901                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
5902                 G_GUINT64_FORMAT, remaining_data_size,
5903                 demux->restoredata_offset);
5904           }
5905
5906           gst_adapter_push (demux->adapter, demux->mdatbuffer);
5907           demux->mdatbuffer = NULL;
5908           demux->offset = demux->mdatoffset;
5909           demux->neededbytes = next_entry_size (demux);
5910           demux->state = QTDEMUX_STATE_MOVIE;
5911           demux->mdatleft = gst_adapter_available (demux->adapter);
5912         } else {
5913           GST_DEBUG_OBJECT (demux, "Carrying on normally");
5914           gst_adapter_flush (demux->adapter, demux->neededbytes);
5915
5916           /* only go back to the mdat if there are samples to play */
5917           if (demux->got_moov && demux->first_mdat != -1
5918               && has_next_entry (demux)) {
5919             gboolean res;
5920
5921             /* we need to seek back */
5922             res = qtdemux_seek_offset (demux, demux->first_mdat);
5923             if (res) {
5924               demux->offset = demux->first_mdat;
5925             } else {
5926               GST_DEBUG_OBJECT (demux, "Seek back failed");
5927             }
5928           } else {
5929             demux->offset += demux->neededbytes;
5930           }
5931           demux->neededbytes = 16;
5932           demux->state = QTDEMUX_STATE_INITIAL;
5933         }
5934
5935         break;
5936       }
5937       case QTDEMUX_STATE_BUFFER_MDAT:{
5938         GstBuffer *buf;
5939         guint8 fourcc[4];
5940
5941         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
5942             demux->offset);
5943         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
5944         gst_buffer_extract (buf, 0, fourcc, 4);
5945         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
5946             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
5947         if (demux->mdatbuffer)
5948           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
5949         else
5950           demux->mdatbuffer = buf;
5951         demux->offset += demux->neededbytes;
5952         demux->neededbytes = 16;
5953         demux->state = QTDEMUX_STATE_INITIAL;
5954         gst_qtdemux_post_progress (demux, 1, 1);
5955
5956         break;
5957       }
5958       case QTDEMUX_STATE_MOVIE:{
5959         QtDemuxStream *stream = NULL;
5960         QtDemuxSample *sample;
5961         int i = -1;
5962         GstClockTime dts, pts, duration;
5963         gboolean keyframe;
5964
5965         GST_DEBUG_OBJECT (demux,
5966             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
5967
5968         if (demux->fragmented) {
5969           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
5970               demux->mdatleft);
5971           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
5972             /* if needed data starts within this atom,
5973              * then it should not exceed this atom */
5974             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
5975               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5976                   (_("This file is invalid and cannot be played.")),
5977                   ("sample data crosses atom boundary"));
5978               ret = GST_FLOW_ERROR;
5979               break;
5980             }
5981             demux->mdatleft -= demux->neededbytes;
5982           } else {
5983             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
5984             /* so we are dropping more than left in this atom */
5985             gst_qtdemux_drop_data (demux, demux->mdatleft);
5986             demux->mdatleft = 0;
5987
5988             /* need to resume atom parsing so we do not miss any other pieces */
5989             demux->state = QTDEMUX_STATE_INITIAL;
5990             demux->neededbytes = 16;
5991
5992             /* check if there was any stored post mdat data from previous buffers */
5993             if (demux->restoredata_buffer) {
5994               g_assert (gst_adapter_available (demux->adapter) == 0);
5995
5996               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
5997               demux->restoredata_buffer = NULL;
5998               demux->offset = demux->restoredata_offset;
5999             }
6000
6001             break;
6002           }
6003         }
6004
6005         if (demux->todrop) {
6006           if (demux->cenc_aux_info_offset > 0) {
6007             GstByteReader br;
6008             const guint8 *data;
6009
6010             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6011             data = gst_adapter_map (demux->adapter, demux->todrop);
6012             gst_byte_reader_init (&br, data + 8, demux->todrop);
6013             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6014                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6015               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6016               ret = GST_FLOW_ERROR;
6017               gst_adapter_unmap (demux->adapter);
6018               g_free (demux->cenc_aux_info_sizes);
6019               demux->cenc_aux_info_sizes = NULL;
6020               goto done;
6021             }
6022             demux->cenc_aux_info_offset = 0;
6023             g_free (demux->cenc_aux_info_sizes);
6024             demux->cenc_aux_info_sizes = NULL;
6025             gst_adapter_unmap (demux->adapter);
6026           }
6027           gst_qtdemux_drop_data (demux, demux->todrop);
6028         }
6029
6030         /* first buffer? */
6031         /* initial newsegment sent here after having added pads,
6032          * possible others in sink_event */
6033         gst_qtdemux_check_send_pending_segment (demux);
6034
6035         /* Figure out which stream this packet belongs to */
6036         for (i = 0; i < demux->n_streams; i++) {
6037           stream = demux->streams[i];
6038           if (stream->sample_index >= stream->n_samples)
6039             continue;
6040           GST_LOG_OBJECT (demux,
6041               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6042               " / size:%d)", i, stream->sample_index,
6043               stream->samples[stream->sample_index].offset,
6044               stream->samples[stream->sample_index].size);
6045
6046           if (stream->samples[stream->sample_index].offset == demux->offset)
6047             break;
6048         }
6049
6050         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6051           goto unknown_stream;
6052
6053         if (stream->new_caps) {
6054           gst_qtdemux_configure_stream (demux, stream);
6055         }
6056
6057         /* Put data in a buffer, set timestamps, caps, ... */
6058         sample = &stream->samples[stream->sample_index];
6059
6060         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6061           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6062               GST_FOURCC_ARGS (stream->fourcc));
6063
6064           dts = QTSAMPLE_DTS (stream, sample);
6065           pts = QTSAMPLE_PTS (stream, sample);
6066           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6067           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6068
6069           /* check for segment end */
6070           if (G_UNLIKELY (demux->segment.stop != -1
6071                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6072             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6073             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6074
6075             /* skip this data, stream is EOS */
6076             gst_adapter_flush (demux->adapter, demux->neededbytes);
6077
6078             /* check if all streams are eos */
6079             ret = GST_FLOW_EOS;
6080             for (i = 0; i < demux->n_streams; i++) {
6081               if (!STREAM_IS_EOS (demux->streams[i])) {
6082                 ret = GST_FLOW_OK;
6083                 break;
6084               }
6085             }
6086
6087             if (ret == GST_FLOW_EOS) {
6088               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6089               goto eos;
6090             }
6091           } else {
6092             GstBuffer *outbuf;
6093
6094             outbuf =
6095                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6096
6097             /* FIXME: should either be an assert or a plain check */
6098             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6099
6100             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6101                 dts, pts, duration, keyframe, dts, demux->offset);
6102           }
6103
6104           /* combine flows */
6105           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6106         } else {
6107           /* skip this data, stream is EOS */
6108           gst_adapter_flush (demux->adapter, demux->neededbytes);
6109         }
6110
6111         stream->sample_index++;
6112         stream->offset_in_sample = 0;
6113
6114         /* update current offset and figure out size of next buffer */
6115         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6116             demux->offset, demux->neededbytes);
6117         demux->offset += demux->neededbytes;
6118         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6119             demux->offset);
6120
6121         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6122           if (demux->fragmented) {
6123             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6124             /* there may be more to follow, only finish this atom */
6125             demux->todrop = demux->mdatleft;
6126             demux->neededbytes = demux->todrop;
6127             break;
6128           }
6129           goto eos;
6130         }
6131         break;
6132       }
6133       default:
6134         goto invalid_state;
6135     }
6136   }
6137
6138   /* when buffering movie data, at least show user something is happening */
6139   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6140       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6141     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6142         demux->neededbytes);
6143   }
6144 done:
6145
6146   return ret;
6147
6148   /* ERRORS */
6149 unknown_stream:
6150   {
6151     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6152     ret = GST_FLOW_ERROR;
6153     goto done;
6154   }
6155 eos:
6156   {
6157     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6158     ret = GST_FLOW_EOS;
6159     goto done;
6160   }
6161 invalid_state:
6162   {
6163     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6164         (NULL), ("qtdemuxer invalid state %d", demux->state));
6165     ret = GST_FLOW_ERROR;
6166     goto done;
6167   }
6168 no_moov:
6169   {
6170     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6171         (NULL), ("no 'moov' atom within the first 10 MB"));
6172     ret = GST_FLOW_ERROR;
6173     goto done;
6174   }
6175 }
6176
6177 static gboolean
6178 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6179 {
6180   GstQuery *query;
6181   gboolean pull_mode;
6182
6183   query = gst_query_new_scheduling ();
6184
6185   if (!gst_pad_peer_query (sinkpad, query)) {
6186     gst_query_unref (query);
6187     goto activate_push;
6188   }
6189
6190   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6191       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6192   gst_query_unref (query);
6193
6194   if (!pull_mode)
6195     goto activate_push;
6196
6197   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6198   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6199
6200 activate_push:
6201   {
6202     GST_DEBUG_OBJECT (sinkpad, "activating push");
6203     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6204   }
6205 }
6206
6207 static gboolean
6208 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6209     GstPadMode mode, gboolean active)
6210 {
6211   gboolean res;
6212   GstQTDemux *demux = GST_QTDEMUX (parent);
6213
6214   switch (mode) {
6215     case GST_PAD_MODE_PUSH:
6216       demux->pullbased = FALSE;
6217       res = TRUE;
6218       break;
6219     case GST_PAD_MODE_PULL:
6220       if (active) {
6221         demux->pullbased = TRUE;
6222         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6223             sinkpad, NULL);
6224       } else {
6225         res = gst_pad_stop_task (sinkpad);
6226       }
6227       break;
6228     default:
6229       res = FALSE;
6230       break;
6231   }
6232   return res;
6233 }
6234
6235 #ifdef HAVE_ZLIB
6236 static void *
6237 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6238 {
6239   return g_malloc (items * size);
6240 }
6241
6242 static void
6243 qtdemux_zfree (void *opaque, void *addr)
6244 {
6245   g_free (addr);
6246 }
6247
6248 static void *
6249 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6250 {
6251   guint8 *buffer;
6252   z_stream *z;
6253   int ret;
6254
6255   z = g_new0 (z_stream, 1);
6256   z->zalloc = qtdemux_zalloc;
6257   z->zfree = qtdemux_zfree;
6258   z->opaque = NULL;
6259
6260   z->next_in = z_buffer;
6261   z->avail_in = z_length;
6262
6263   buffer = (guint8 *) g_malloc (length);
6264   ret = inflateInit (z);
6265   while (z->avail_in > 0) {
6266     if (z->avail_out == 0) {
6267       length += 1024;
6268       buffer = (guint8 *) g_realloc (buffer, length);
6269       z->next_out = buffer + z->total_out;
6270       z->avail_out = 1024;
6271     }
6272     ret = inflate (z, Z_SYNC_FLUSH);
6273     if (ret != Z_OK)
6274       break;
6275   }
6276   if (ret != Z_STREAM_END) {
6277     g_warning ("inflate() returned %d", ret);
6278   }
6279
6280   g_free (z);
6281   return buffer;
6282 }
6283 #endif /* HAVE_ZLIB */
6284
6285 static gboolean
6286 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6287 {
6288   GNode *cmov;
6289
6290   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6291
6292   /* counts as header data */
6293   qtdemux->header_size += length;
6294
6295   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6296   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6297
6298   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6299   if (cmov) {
6300     guint32 method;
6301     GNode *dcom;
6302     GNode *cmvd;
6303
6304     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6305     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6306     if (dcom == NULL || cmvd == NULL)
6307       goto invalid_compression;
6308
6309     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6310     switch (method) {
6311 #ifdef HAVE_ZLIB
6312       case GST_MAKE_FOURCC ('z', 'l', 'i', 'b'):{
6313         guint uncompressed_length;
6314         guint compressed_length;
6315         guint8 *buf;
6316
6317         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6318         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6319         GST_LOG ("length = %u", uncompressed_length);
6320
6321         buf =
6322             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6323             compressed_length, uncompressed_length);
6324
6325         qtdemux->moov_node_compressed = qtdemux->moov_node;
6326         qtdemux->moov_node = g_node_new (buf);
6327
6328         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6329             uncompressed_length);
6330         break;
6331       }
6332 #endif /* HAVE_ZLIB */
6333       default:
6334         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6335             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6336         break;
6337     }
6338   }
6339   return TRUE;
6340
6341   /* ERRORS */
6342 invalid_compression:
6343   {
6344     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6345     return FALSE;
6346   }
6347 }
6348
6349 static gboolean
6350 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6351     const guint8 * end)
6352 {
6353   while (G_UNLIKELY (buf < end)) {
6354     GNode *child;
6355     guint32 len;
6356
6357     if (G_UNLIKELY (buf + 4 > end)) {
6358       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6359       break;
6360     }
6361     len = QT_UINT32 (buf);
6362     if (G_UNLIKELY (len == 0)) {
6363       GST_LOG_OBJECT (qtdemux, "empty container");
6364       break;
6365     }
6366     if (G_UNLIKELY (len < 8)) {
6367       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6368       break;
6369     }
6370     if (G_UNLIKELY (len > (end - buf))) {
6371       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6372           (gint) (end - buf));
6373       break;
6374     }
6375
6376     child = g_node_new ((guint8 *) buf);
6377     g_node_append (node, child);
6378     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6379     qtdemux_parse_node (qtdemux, child, buf, len);
6380
6381     buf += len;
6382   }
6383   return TRUE;
6384 }
6385
6386 static gboolean
6387 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6388     GNode * xdxt)
6389 {
6390   int len = QT_UINT32 (xdxt->data);
6391   guint8 *buf = xdxt->data;
6392   guint8 *end = buf + len;
6393   GstBuffer *buffer;
6394
6395   /* skip size and type */
6396   buf += 8;
6397   end -= 8;
6398
6399   while (buf < end) {
6400     gint size;
6401     guint32 type;
6402
6403     size = QT_UINT32 (buf);
6404     type = QT_FOURCC (buf + 4);
6405
6406     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6407
6408     if (buf + size > end || size <= 0)
6409       break;
6410
6411     buf += 8;
6412     size -= 8;
6413
6414     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6415         GST_FOURCC_ARGS (type));
6416
6417     switch (type) {
6418       case FOURCC_tCtH:
6419         buffer = gst_buffer_new_and_alloc (size);
6420         gst_buffer_fill (buffer, 0, buf, size);
6421         stream->buffers = g_slist_append (stream->buffers, buffer);
6422         GST_LOG_OBJECT (qtdemux, "parsing theora header");
6423         break;
6424       case FOURCC_tCt_:
6425         buffer = gst_buffer_new_and_alloc (size);
6426         gst_buffer_fill (buffer, 0, buf, size);
6427         stream->buffers = g_slist_append (stream->buffers, buffer);
6428         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6429         break;
6430       case FOURCC_tCtC:
6431         buffer = gst_buffer_new_and_alloc (size);
6432         gst_buffer_fill (buffer, 0, buf, size);
6433         stream->buffers = g_slist_append (stream->buffers, buffer);
6434         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6435         break;
6436       default:
6437         GST_WARNING_OBJECT (qtdemux,
6438             "unknown theora cookie %" GST_FOURCC_FORMAT,
6439             GST_FOURCC_ARGS (type));
6440         break;
6441     }
6442     buf += size;
6443   }
6444   return TRUE;
6445 }
6446
6447 static gboolean
6448 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
6449     guint length)
6450 {
6451   guint32 fourcc = 0;
6452   guint32 node_length = 0;
6453   const QtNodeType *type;
6454   const guint8 *end;
6455
6456   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
6457
6458   if (G_UNLIKELY (length < 8))
6459     goto not_enough_data;
6460
6461   node_length = QT_UINT32 (buffer);
6462   fourcc = QT_FOURCC (buffer + 4);
6463
6464   /* ignore empty nodes */
6465   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
6466     return TRUE;
6467
6468   type = qtdemux_type_get (fourcc);
6469
6470   end = buffer + length;
6471
6472   GST_LOG_OBJECT (qtdemux,
6473       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
6474       GST_FOURCC_ARGS (fourcc), node_length, type->name);
6475
6476   if (node_length > length)
6477     goto broken_atom_size;
6478
6479   if (type->flags & QT_FLAG_CONTAINER) {
6480     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
6481   } else {
6482     switch (fourcc) {
6483       case FOURCC_stsd:
6484       {
6485         if (node_length < 20) {
6486           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
6487           break;
6488         }
6489         GST_DEBUG_OBJECT (qtdemux,
6490             "parsing stsd (sample table, sample description) atom");
6491         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
6492         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6493         break;
6494       }
6495       case FOURCC_mp4a:
6496       case FOURCC_alac:
6497       {
6498         guint32 version;
6499         guint32 offset;
6500         guint min_size;
6501
6502         /* also read alac (or whatever) in stead of mp4a in the following,
6503          * since a similar layout is used in other cases as well */
6504         if (fourcc == FOURCC_mp4a)
6505           min_size = 20;
6506         else
6507           min_size = 40;
6508
6509         /* There are two things we might encounter here: a true mp4a atom, and
6510            an mp4a entry in an stsd atom. The latter is what we're interested
6511            in, and it looks like an atom, but isn't really one. The true mp4a
6512            atom is short, so we detect it based on length here. */
6513         if (length < min_size) {
6514           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
6515               GST_FOURCC_ARGS (fourcc));
6516           break;
6517         }
6518
6519         /* 'version' here is the sound sample description version. Types 0 and
6520            1 are documented in the QTFF reference, but type 2 is not: it's
6521            described in Apple header files instead (struct SoundDescriptionV2
6522            in Movies.h) */
6523         version = QT_UINT16 (buffer + 16);
6524
6525         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
6526             GST_FOURCC_ARGS (fourcc), version);
6527
6528         /* parse any esds descriptors */
6529         switch (version) {
6530           case 0:
6531             offset = 0x24;
6532             break;
6533           case 1:
6534             offset = 0x34;
6535             break;
6536           case 2:
6537             offset = 0x48;
6538             break;
6539           default:
6540             GST_WARNING_OBJECT (qtdemux,
6541                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
6542                 GST_FOURCC_ARGS (fourcc), version);
6543             offset = 0;
6544             break;
6545         }
6546         if (offset)
6547           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6548         break;
6549       }
6550       case FOURCC_mp4v:
6551       case FOURCC_MP4V:
6552       case FOURCC_fmp4:
6553       case FOURCC_FMP4:
6554       case FOURCC_apcs:
6555       case FOURCC_apch:
6556       case FOURCC_apcn:
6557       case FOURCC_apco:
6558       case FOURCC_ap4h:
6559       {
6560         const guint8 *buf;
6561         guint32 version;
6562         int tlen;
6563
6564         /* codec_data is contained inside these atoms, which all have
6565          * the same format. */
6566
6567         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
6568             GST_FOURCC_ARGS (fourcc));
6569         version = QT_UINT32 (buffer + 16);
6570         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
6571         if (1 || version == 0x00000000) {
6572           buf = buffer + 0x32;
6573
6574           /* FIXME Quicktime uses PASCAL string while
6575            * the iso format uses C strings. Check the file
6576            * type before attempting to parse the string here. */
6577           tlen = QT_UINT8 (buf);
6578           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
6579           buf++;
6580           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
6581           /* the string has a reserved space of 32 bytes so skip
6582            * the remaining 31 */
6583           buf += 31;
6584           buf += 4;             /* and 4 bytes reserved */
6585
6586           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
6587
6588           qtdemux_parse_container (qtdemux, node, buf, end);
6589         }
6590         break;
6591       }
6592       case FOURCC_H264:
6593       {
6594         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
6595         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6596         break;
6597       }
6598       case FOURCC_avc1:
6599       {
6600         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
6601         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6602         break;
6603       }
6604       case FOURCC_avc3:
6605       {
6606         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
6607         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6608         break;
6609       }
6610       case FOURCC_H265:
6611       {
6612         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
6613         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6614         break;
6615       }
6616       case FOURCC_hvc1:
6617       {
6618         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
6619         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6620         break;
6621       }
6622       case FOURCC_hev1:
6623       {
6624         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
6625         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6626         break;
6627       }
6628       case FOURCC_mjp2:
6629       {
6630         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6631         break;
6632       }
6633       case FOURCC_meta:
6634       {
6635         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
6636         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
6637         break;
6638       }
6639       case FOURCC_mp4s:
6640       {
6641         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
6642         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
6643         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6644         break;
6645       }
6646       case FOURCC_XiTh:
6647       {
6648         guint32 version;
6649         guint32 offset;
6650
6651         version = QT_UINT32 (buffer + 12);
6652         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
6653
6654         switch (version) {
6655           case 0x00000001:
6656             offset = 0x62;
6657             break;
6658           default:
6659             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
6660             offset = 0;
6661             break;
6662         }
6663         if (offset)
6664           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6665         break;
6666       }
6667       case FOURCC_in24:
6668       {
6669         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
6670         break;
6671       }
6672       case FOURCC_uuid:
6673       {
6674         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
6675         break;
6676       }
6677       case FOURCC_encv:
6678       {
6679         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6680         break;
6681       }
6682       case FOURCC_enca:
6683       {
6684         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
6685         break;
6686       }
6687       default:
6688         if (!strcmp (type->name, "unknown"))
6689           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
6690         break;
6691     }
6692   }
6693   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
6694       GST_FOURCC_ARGS (fourcc));
6695   return TRUE;
6696
6697 /* ERRORS */
6698 not_enough_data:
6699   {
6700     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6701         (_("This file is corrupt and cannot be played.")),
6702         ("Not enough data for an atom header, got only %u bytes", length));
6703     return FALSE;
6704   }
6705 broken_atom_size:
6706   {
6707     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6708         (_("This file is corrupt and cannot be played.")),
6709         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
6710             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
6711             length));
6712     return FALSE;
6713   }
6714 }
6715
6716 static GNode *
6717 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
6718 {
6719   GNode *child;
6720   guint8 *buffer;
6721   guint32 child_fourcc;
6722
6723   for (child = g_node_first_child (node); child;
6724       child = g_node_next_sibling (child)) {
6725     buffer = (guint8 *) child->data;
6726
6727     child_fourcc = QT_FOURCC (buffer + 4);
6728
6729     if (G_UNLIKELY (child_fourcc == fourcc)) {
6730       return child;
6731     }
6732   }
6733   return NULL;
6734 }
6735
6736 static GNode *
6737 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
6738     GstByteReader * parser)
6739 {
6740   GNode *child;
6741   guint8 *buffer;
6742   guint32 child_fourcc, child_len;
6743
6744   for (child = g_node_first_child (node); child;
6745       child = g_node_next_sibling (child)) {
6746     buffer = (guint8 *) child->data;
6747
6748     child_len = QT_UINT32 (buffer);
6749     child_fourcc = QT_FOURCC (buffer + 4);
6750
6751     if (G_UNLIKELY (child_fourcc == fourcc)) {
6752       if (G_UNLIKELY (child_len < (4 + 4)))
6753         return NULL;
6754       /* FIXME: must verify if atom length < parent atom length */
6755       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6756       return child;
6757     }
6758   }
6759   return NULL;
6760 }
6761
6762 static GNode *
6763 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
6764     GstByteReader * parser)
6765 {
6766   GNode *child;
6767   guint8 *buffer;
6768   guint32 child_fourcc, child_len;
6769
6770   for (child = g_node_next_sibling (node); child;
6771       child = g_node_next_sibling (child)) {
6772     buffer = (guint8 *) child->data;
6773
6774     child_fourcc = QT_FOURCC (buffer + 4);
6775
6776     if (child_fourcc == fourcc) {
6777       if (parser) {
6778         child_len = QT_UINT32 (buffer);
6779         if (G_UNLIKELY (child_len < (4 + 4)))
6780           return NULL;
6781         /* FIXME: must verify if atom length < parent atom length */
6782         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6783       }
6784       return child;
6785     }
6786   }
6787   return NULL;
6788 }
6789
6790 static GNode *
6791 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
6792 {
6793   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
6794 }
6795
6796 static void
6797 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
6798 {
6799 /* FIXME: This can only reliably work if demuxers have a
6800  * separate streaming thread per srcpad. This should be
6801  * done in a demuxer base class, which integrates parts
6802  * of multiqueue
6803  *
6804  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
6805  */
6806 #if 0
6807   GstQuery *query;
6808
6809   query = gst_query_new_allocation (stream->caps, FALSE);
6810
6811   if (!gst_pad_peer_query (stream->pad, query)) {
6812     /* not a problem, just debug a little */
6813     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
6814   }
6815
6816   if (stream->allocator)
6817     gst_object_unref (stream->allocator);
6818
6819   if (gst_query_get_n_allocation_params (query) > 0) {
6820     /* try the allocator */
6821     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
6822         &stream->params);
6823     stream->use_allocator = TRUE;
6824   } else {
6825     stream->allocator = NULL;
6826     gst_allocation_params_init (&stream->params);
6827     stream->use_allocator = FALSE;
6828   }
6829   gst_query_unref (query);
6830 #endif
6831 }
6832
6833 static gboolean
6834 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
6835     QtDemuxStream * stream)
6836 {
6837   GstStructure *s;
6838   const gchar *selected_system;
6839
6840   g_return_val_if_fail (qtdemux != NULL, FALSE);
6841   g_return_val_if_fail (stream != NULL, FALSE);
6842   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
6843
6844   if (stream->protection_scheme_type != FOURCC_cenc) {
6845     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
6846     return FALSE;
6847   }
6848   if (qtdemux->protection_system_ids == NULL) {
6849     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
6850         "cenc protection system information has been found");
6851     return FALSE;
6852   }
6853   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
6854   selected_system = gst_protection_select_system ((const gchar **)
6855       qtdemux->protection_system_ids->pdata);
6856   g_ptr_array_remove_index (qtdemux->protection_system_ids,
6857       qtdemux->protection_system_ids->len - 1);
6858   if (!selected_system) {
6859     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
6860         "suitable decryptor element has been found");
6861     return FALSE;
6862   }
6863
6864   s = gst_caps_get_structure (stream->caps, 0);
6865   gst_structure_set (s,
6866       "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
6867       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
6868       NULL);
6869   gst_structure_set_name (s, "application/x-cenc");
6870   return TRUE;
6871 }
6872
6873 static gboolean
6874 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
6875 {
6876   if (stream->subtype == FOURCC_vide) {
6877     /* fps is calculated base on the duration of the average framerate since
6878      * qt does not have a fixed framerate. */
6879     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
6880       /* still frame */
6881       stream->fps_n = 0;
6882       stream->fps_d = 1;
6883     } else {
6884       if (stream->duration == 0 || stream->n_samples < 2) {
6885         stream->fps_n = stream->timescale;
6886         stream->fps_d = 1;
6887       } else {
6888         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
6889         /* stream->duration is guint64, timescale, n_samples are guint32 */
6890         GstClockTime avg_duration =
6891             gst_util_uint64_scale_round (stream->duration -
6892             stream->first_duration, GST_SECOND,
6893             (guint64) (stream->timescale) * (stream->n_samples - 1));
6894
6895         GST_LOG_OBJECT (qtdemux,
6896             "Calculating avg sample duration based on stream duration %"
6897             G_GUINT64_FORMAT
6898             " minus first sample %u, leaving %d samples gives %"
6899             GST_TIME_FORMAT, stream->duration, stream->first_duration,
6900             stream->n_samples - 1, GST_TIME_ARGS (avg_duration));
6901
6902         gst_video_guess_framerate (avg_duration, &stream->fps_n,
6903             &stream->fps_d);
6904       }
6905       GST_DEBUG_OBJECT (qtdemux,
6906           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
6907           stream->timescale, stream->fps_n, stream->fps_d);
6908     }
6909
6910     if (stream->caps) {
6911       stream->caps = gst_caps_make_writable (stream->caps);
6912
6913       gst_caps_set_simple (stream->caps,
6914           "width", G_TYPE_INT, stream->width,
6915           "height", G_TYPE_INT, stream->height,
6916           "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
6917
6918       /* calculate pixel-aspect-ratio using display width and height */
6919       GST_DEBUG_OBJECT (qtdemux,
6920           "video size %dx%d, target display size %dx%d", stream->width,
6921           stream->height, stream->display_width, stream->display_height);
6922       /* qt file might have pasp atom */
6923       if (stream->par_w > 0 && stream->par_h > 0) {
6924         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
6925         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
6926             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
6927       } else if (stream->display_width > 0 && stream->display_height > 0 &&
6928           stream->width > 0 && stream->height > 0) {
6929         gint n, d;
6930
6931         /* calculate the pixel aspect ratio using the display and pixel w/h */
6932         n = stream->display_width * stream->height;
6933         d = stream->display_height * stream->width;
6934         if (n == d)
6935           n = d = 1;
6936         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
6937         stream->par_w = n;
6938         stream->par_h = d;
6939         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
6940             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
6941       }
6942
6943       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
6944         guint par_w = 1, par_h = 1;
6945
6946         if (stream->par_w > 0 && stream->par_h > 0) {
6947           par_w = stream->par_w;
6948           par_h = stream->par_h;
6949         }
6950
6951         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
6952                 stream->width, stream->height, par_w, par_h)) {
6953           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
6954         }
6955
6956         gst_caps_set_simple (stream->caps,
6957             "multiview-mode", G_TYPE_STRING,
6958             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
6959             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
6960             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
6961       }
6962     }
6963   }
6964
6965   else if (stream->subtype == FOURCC_soun) {
6966     if (stream->caps) {
6967       stream->caps = gst_caps_make_writable (stream->caps);
6968       if (stream->rate > 0)
6969         gst_caps_set_simple (stream->caps,
6970             "rate", G_TYPE_INT, (int) stream->rate, NULL);
6971       if (stream->n_channels > 0)
6972         gst_caps_set_simple (stream->caps,
6973             "channels", G_TYPE_INT, stream->n_channels, NULL);
6974       if (stream->n_channels > 2) {
6975         /* FIXME: Need to parse the 'chan' atom to get channel layouts
6976          * correctly; this is just the minimum we can do - assume
6977          * we don't actually have any channel positions. */
6978         gst_caps_set_simple (stream->caps,
6979             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
6980       }
6981     }
6982   }
6983
6984   if (stream->pad) {
6985     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
6986     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
6987     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
6988     gst_pad_set_active (stream->pad, TRUE);
6989
6990     gst_pad_use_fixed_caps (stream->pad);
6991
6992     if (stream->protected) {
6993       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
6994         GST_ERROR_OBJECT (qtdemux,
6995             "Failed to configure protected stream caps.");
6996         return FALSE;
6997       }
6998     }
6999
7000     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7001     if (stream->new_stream) {
7002       gchar *stream_id;
7003       GstEvent *event;
7004       GstStreamFlags stream_flags;
7005
7006       event =
7007           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7008           0);
7009       if (event) {
7010         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7011           qtdemux->have_group_id = TRUE;
7012         else
7013           qtdemux->have_group_id = FALSE;
7014         gst_event_unref (event);
7015       } else if (!qtdemux->have_group_id) {
7016         qtdemux->have_group_id = TRUE;
7017         qtdemux->group_id = gst_util_group_id_next ();
7018       }
7019
7020       stream->new_stream = FALSE;
7021       stream_id =
7022           gst_pad_create_stream_id_printf (stream->pad,
7023           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7024       event = gst_event_new_stream_start (stream_id);
7025       if (qtdemux->have_group_id)
7026         gst_event_set_group_id (event, qtdemux->group_id);
7027       stream_flags = GST_STREAM_FLAG_NONE;
7028       if (stream->disabled)
7029         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7030       if (stream->sparse)
7031         stream_flags |= GST_STREAM_FLAG_SPARSE;
7032       gst_event_set_stream_flags (event, stream_flags);
7033       gst_pad_push_event (stream->pad, event);
7034       g_free (stream_id);
7035     }
7036     gst_pad_set_caps (stream->pad, stream->caps);
7037     stream->new_caps = FALSE;
7038   }
7039   return TRUE;
7040 }
7041
7042 static gboolean
7043 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7044     QtDemuxStream * stream, GstTagList * list)
7045 {
7046   /* consistent default for push based mode */
7047   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7048
7049   if (stream->subtype == FOURCC_vide) {
7050     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7051
7052     stream->pad =
7053         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7054     g_free (name);
7055
7056     gst_qtdemux_configure_stream (qtdemux, stream);
7057     qtdemux->n_video_streams++;
7058   } else if (stream->subtype == FOURCC_soun) {
7059     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7060
7061     stream->pad =
7062         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7063     g_free (name);
7064     gst_qtdemux_configure_stream (qtdemux, stream);
7065     qtdemux->n_audio_streams++;
7066   } else if (stream->subtype == FOURCC_strm) {
7067     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7068   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7069       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7070     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7071
7072     stream->pad =
7073         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7074     g_free (name);
7075     gst_qtdemux_configure_stream (qtdemux, stream);
7076     qtdemux->n_sub_streams++;
7077   } else if (stream->caps) {
7078     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7079
7080     stream->pad =
7081         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7082     g_free (name);
7083     gst_qtdemux_configure_stream (qtdemux, stream);
7084     qtdemux->n_video_streams++;
7085   } else {
7086     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7087     goto done;
7088   }
7089
7090   if (stream->pad) {
7091     GList *l;
7092
7093     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7094         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7095     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7096     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7097
7098     if (stream->pending_tags)
7099       gst_tag_list_unref (stream->pending_tags);
7100     stream->pending_tags = list;
7101     list = NULL;
7102     /* global tags go on each pad anyway */
7103     stream->send_global_tags = TRUE;
7104     /* send upstream GST_EVENT_PROTECTION events that were received before
7105        this source pad was created */
7106     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7107       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7108   }
7109 done:
7110   if (list)
7111     gst_tag_list_unref (list);
7112   return TRUE;
7113 }
7114
7115 /* find next atom with @fourcc starting at @offset */
7116 static GstFlowReturn
7117 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7118     guint64 * length, guint32 fourcc)
7119 {
7120   GstFlowReturn ret;
7121   guint32 lfourcc;
7122   GstBuffer *buf;
7123
7124   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7125       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7126
7127   while (TRUE) {
7128     GstMapInfo map;
7129
7130     buf = NULL;
7131     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7132     if (G_UNLIKELY (ret != GST_FLOW_OK))
7133       goto locate_failed;
7134     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7135       /* likely EOF */
7136       ret = GST_FLOW_EOS;
7137       gst_buffer_unref (buf);
7138       goto locate_failed;
7139     }
7140     gst_buffer_map (buf, &map, GST_MAP_READ);
7141     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7142     gst_buffer_unmap (buf, &map);
7143     gst_buffer_unref (buf);
7144
7145     if (G_UNLIKELY (*length == 0)) {
7146       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7147       ret = GST_FLOW_ERROR;
7148       goto locate_failed;
7149     }
7150
7151     if (lfourcc == fourcc) {
7152       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7153           *offset);
7154       break;
7155     } else {
7156       GST_LOG_OBJECT (qtdemux,
7157           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7158           GST_FOURCC_ARGS (fourcc), *offset);
7159       *offset += *length;
7160     }
7161   }
7162
7163   return GST_FLOW_OK;
7164
7165 locate_failed:
7166   {
7167     /* might simply have had last one */
7168     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7169     return ret;
7170   }
7171 }
7172
7173 /* should only do something in pull mode */
7174 /* call with OBJECT lock */
7175 static GstFlowReturn
7176 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7177 {
7178   guint64 length, offset;
7179   GstBuffer *buf = NULL;
7180   GstFlowReturn ret = GST_FLOW_OK;
7181   GstFlowReturn res = GST_FLOW_OK;
7182   GstMapInfo map;
7183
7184   offset = qtdemux->moof_offset;
7185   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7186
7187   if (!offset) {
7188     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7189     return GST_FLOW_EOS;
7190   }
7191
7192   /* best not do pull etc with lock held */
7193   GST_OBJECT_UNLOCK (qtdemux);
7194
7195   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7196   if (ret != GST_FLOW_OK)
7197     goto flow_failed;
7198
7199   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7200   if (G_UNLIKELY (ret != GST_FLOW_OK))
7201     goto flow_failed;
7202   gst_buffer_map (buf, &map, GST_MAP_READ);
7203   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7204     gst_buffer_unmap (buf, &map);
7205     gst_buffer_unref (buf);
7206     buf = NULL;
7207     goto parse_failed;
7208   }
7209
7210   gst_buffer_unmap (buf, &map);
7211   gst_buffer_unref (buf);
7212   buf = NULL;
7213
7214   offset += length;
7215   /* look for next moof */
7216   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7217   if (G_UNLIKELY (ret != GST_FLOW_OK))
7218     goto flow_failed;
7219
7220 exit:
7221   GST_OBJECT_LOCK (qtdemux);
7222
7223   qtdemux->moof_offset = offset;
7224
7225   return res;
7226
7227 parse_failed:
7228   {
7229     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7230     offset = 0;
7231     res = GST_FLOW_ERROR;
7232     goto exit;
7233   }
7234 flow_failed:
7235   {
7236     /* maybe upstream temporarily flushing */
7237     if (ret != GST_FLOW_FLUSHING) {
7238       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7239       offset = 0;
7240     } else {
7241       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7242       /* resume at current position next time */
7243     }
7244     res = ret;
7245     goto exit;
7246   }
7247 }
7248
7249 /* initialise bytereaders for stbl sub-atoms */
7250 static gboolean
7251 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7252 {
7253   stream->stbl_index = -1;      /* no samples have yet been parsed */
7254   stream->sample_index = -1;
7255
7256   /* time-to-sample atom */
7257   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7258     goto corrupt_file;
7259
7260   /* copy atom data into a new buffer for later use */
7261   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7262
7263   /* skip version + flags */
7264   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7265       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7266     goto corrupt_file;
7267   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7268
7269   /* make sure there's enough data */
7270   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7271     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7272     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7273         stream->n_sample_times);
7274     if (!stream->n_sample_times)
7275       goto corrupt_file;
7276   }
7277
7278   /* sync sample atom */
7279   stream->stps_present = FALSE;
7280   if ((stream->stss_present =
7281           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7282               &stream->stss) ? TRUE : FALSE) == TRUE) {
7283     /* copy atom data into a new buffer for later use */
7284     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7285
7286     /* skip version + flags */
7287     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7288         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7289       goto corrupt_file;
7290
7291     if (stream->n_sample_syncs) {
7292       /* make sure there's enough data */
7293       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7294         goto corrupt_file;
7295     }
7296
7297     /* partial sync sample atom */
7298     if ((stream->stps_present =
7299             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7300                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7301       /* copy atom data into a new buffer for later use */
7302       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7303
7304       /* skip version + flags */
7305       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7306           !gst_byte_reader_get_uint32_be (&stream->stps,
7307               &stream->n_sample_partial_syncs))
7308         goto corrupt_file;
7309
7310       /* if there are no entries, the stss table contains the real
7311        * sync samples */
7312       if (stream->n_sample_partial_syncs) {
7313         /* make sure there's enough data */
7314         if (!qt_atom_parser_has_chunks (&stream->stps,
7315                 stream->n_sample_partial_syncs, 4))
7316           goto corrupt_file;
7317       }
7318     }
7319   }
7320
7321   /* sample size */
7322   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7323     goto no_samples;
7324
7325   /* copy atom data into a new buffer for later use */
7326   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7327
7328   /* skip version + flags */
7329   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7330       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7331     goto corrupt_file;
7332
7333   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7334     goto corrupt_file;
7335
7336   if (!stream->n_samples)
7337     goto no_samples;
7338
7339   /* sample-to-chunk atom */
7340   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7341     goto corrupt_file;
7342
7343   /* copy atom data into a new buffer for later use */
7344   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7345
7346   /* skip version + flags */
7347   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7348       !gst_byte_reader_get_uint32_be (&stream->stsc,
7349           &stream->n_samples_per_chunk))
7350     goto corrupt_file;
7351
7352   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7353       stream->n_samples_per_chunk);
7354
7355   /* make sure there's enough data */
7356   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7357           12))
7358     goto corrupt_file;
7359
7360
7361   /* chunk offset */
7362   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7363     stream->co_size = sizeof (guint32);
7364   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7365           &stream->stco))
7366     stream->co_size = sizeof (guint64);
7367   else
7368     goto corrupt_file;
7369
7370   /* copy atom data into a new buffer for later use */
7371   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7372
7373   /* skip version + flags */
7374   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7375     goto corrupt_file;
7376
7377   /* chunks_are_samples == TRUE means treat chunks as samples */
7378   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7379   if (stream->chunks_are_samples) {
7380     /* treat chunks as samples */
7381     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7382       goto corrupt_file;
7383   } else {
7384     /* skip number of entries */
7385     if (!gst_byte_reader_skip (&stream->stco, 4))
7386       goto corrupt_file;
7387
7388     /* make sure there are enough data in the stsz atom */
7389     if (!stream->sample_size) {
7390       /* different sizes for each sample */
7391       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7392         goto corrupt_file;
7393     }
7394   }
7395
7396   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7397       stream->n_samples, (guint) sizeof (QtDemuxSample),
7398       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7399
7400   if (stream->n_samples >=
7401       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7402     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7403         "be larger than %uMB (broken file?)", stream->n_samples,
7404         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7405     return FALSE;
7406   }
7407
7408   g_assert (stream->samples == NULL);
7409   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7410   if (!stream->samples) {
7411     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7412         stream->n_samples);
7413     return FALSE;
7414   }
7415
7416   /* composition time-to-sample */
7417   if ((stream->ctts_present =
7418           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7419               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7420     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7421
7422     /* copy atom data into a new buffer for later use */
7423     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7424
7425     /* skip version + flags */
7426     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7427         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7428             &stream->n_composition_times))
7429       goto corrupt_file;
7430
7431     /* make sure there's enough data */
7432     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7433             4 + 4))
7434       goto corrupt_file;
7435
7436     /* This is optional, if missing we iterate the ctts */
7437     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7438       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7439           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7440         g_free ((gpointer) cslg.data);
7441         goto corrupt_file;
7442       }
7443     } else {
7444       gint32 cslg_least = 0;
7445       guint num_entries, pos;
7446       gint i;
7447
7448       pos = gst_byte_reader_get_pos (&stream->ctts);
7449       num_entries = stream->n_composition_times;
7450
7451       stream->cslg_shift = 0;
7452
7453       for (i = 0; i < num_entries; i++) {
7454         gint32 offset;
7455
7456         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7457         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7458
7459         if (offset < cslg_least)
7460           cslg_least = offset;
7461       }
7462
7463       if (cslg_least < 0)
7464         stream->cslg_shift = ABS (cslg_least);
7465       else
7466         stream->cslg_shift = 0;
7467
7468       /* reset the reader so we can generate sample table */
7469       gst_byte_reader_set_pos (&stream->ctts, pos);
7470     }
7471   } else {
7472     /* Ensure the cslg_shift value is consistent so we can use it
7473      * unconditionnally to produce TS and Segment */
7474     stream->cslg_shift = 0;
7475   }
7476
7477   return TRUE;
7478
7479 corrupt_file:
7480   {
7481     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7482         (_("This file is corrupt and cannot be played.")), (NULL));
7483     return FALSE;
7484   }
7485 no_samples:
7486   {
7487     gst_qtdemux_stbl_free (stream);
7488     if (!qtdemux->fragmented) {
7489       /* not quite good */
7490       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
7491       return FALSE;
7492     } else {
7493       /* may pick up samples elsewhere */
7494       return TRUE;
7495     }
7496   }
7497 }
7498
7499 /* collect samples from the next sample to be parsed up to sample @n for @stream
7500  * by reading the info from @stbl
7501  *
7502  * This code can be executed from both the streaming thread and the seeking
7503  * thread so it takes the object lock to protect itself
7504  */
7505 static gboolean
7506 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
7507 {
7508   gint i, j, k;
7509   QtDemuxSample *samples, *first, *cur, *last;
7510   guint32 n_samples_per_chunk;
7511   guint32 n_samples;
7512
7513   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
7514       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
7515       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
7516
7517   n_samples = stream->n_samples;
7518
7519   if (n >= n_samples)
7520     goto out_of_samples;
7521
7522   GST_OBJECT_LOCK (qtdemux);
7523   if (n <= stream->stbl_index)
7524     goto already_parsed;
7525
7526   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
7527
7528   if (!stream->stsz.data) {
7529     /* so we already parsed and passed all the moov samples;
7530      * onto fragmented ones */
7531     g_assert (qtdemux->fragmented);
7532     goto done;
7533   }
7534
7535   /* pointer to the sample table */
7536   samples = stream->samples;
7537
7538   /* starts from -1, moves to the next sample index to parse */
7539   stream->stbl_index++;
7540
7541   /* keep track of the first and last sample to fill */
7542   first = &samples[stream->stbl_index];
7543   last = &samples[n];
7544
7545   if (!stream->chunks_are_samples) {
7546     /* set the sample sizes */
7547     if (stream->sample_size == 0) {
7548       /* different sizes for each sample */
7549       for (cur = first; cur <= last; cur++) {
7550         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
7551         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
7552             (guint) (cur - samples), cur->size);
7553       }
7554     } else {
7555       /* samples have the same size */
7556       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
7557       for (cur = first; cur <= last; cur++)
7558         cur->size = stream->sample_size;
7559     }
7560   }
7561
7562   n_samples_per_chunk = stream->n_samples_per_chunk;
7563   cur = first;
7564
7565   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
7566     guint32 last_chunk;
7567
7568     if (stream->stsc_chunk_index >= stream->last_chunk
7569         || stream->stsc_chunk_index < stream->first_chunk) {
7570       stream->first_chunk =
7571           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7572       stream->samples_per_chunk =
7573           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7574       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
7575
7576       /* chunk numbers are counted from 1 it seems */
7577       if (G_UNLIKELY (stream->first_chunk == 0))
7578         goto corrupt_file;
7579
7580       --stream->first_chunk;
7581
7582       /* the last chunk of each entry is calculated by taking the first chunk
7583        * of the next entry; except if there is no next, where we fake it with
7584        * INT_MAX */
7585       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
7586         stream->last_chunk = G_MAXUINT32;
7587       } else {
7588         stream->last_chunk =
7589             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
7590         if (G_UNLIKELY (stream->last_chunk == 0))
7591           goto corrupt_file;
7592
7593         --stream->last_chunk;
7594       }
7595
7596       GST_LOG_OBJECT (qtdemux,
7597           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
7598           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
7599
7600       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
7601         goto corrupt_file;
7602
7603       if (stream->last_chunk != G_MAXUINT32) {
7604         if (!qt_atom_parser_peek_sub (&stream->stco,
7605                 stream->first_chunk * stream->co_size,
7606                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
7607                 &stream->co_chunk))
7608           goto corrupt_file;
7609
7610       } else {
7611         stream->co_chunk = stream->stco;
7612         if (!gst_byte_reader_skip (&stream->co_chunk,
7613                 stream->first_chunk * stream->co_size))
7614           goto corrupt_file;
7615       }
7616
7617       stream->stsc_chunk_index = stream->first_chunk;
7618     }
7619
7620     last_chunk = stream->last_chunk;
7621
7622     if (stream->chunks_are_samples) {
7623       cur = &samples[stream->stsc_chunk_index];
7624
7625       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7626         if (j > n) {
7627           /* save state */
7628           stream->stsc_chunk_index = j;
7629           goto done;
7630         }
7631
7632         cur->offset =
7633             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
7634             stream->co_size);
7635
7636         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
7637             "%" G_GUINT64_FORMAT, j, cur->offset);
7638
7639         if (stream->samples_per_frame * stream->bytes_per_frame) {
7640           cur->size =
7641               (stream->samples_per_chunk * stream->n_channels) /
7642               stream->samples_per_frame * stream->bytes_per_frame;
7643         } else {
7644           cur->size = stream->samples_per_chunk;
7645         }
7646
7647         GST_DEBUG_OBJECT (qtdemux,
7648             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
7649             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
7650                     stream->stco_sample_index)), cur->size);
7651
7652         cur->timestamp = stream->stco_sample_index;
7653         cur->duration = stream->samples_per_chunk;
7654         cur->keyframe = TRUE;
7655         cur++;
7656
7657         stream->stco_sample_index += stream->samples_per_chunk;
7658       }
7659       stream->stsc_chunk_index = j;
7660     } else {
7661       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7662         guint32 samples_per_chunk;
7663         guint64 chunk_offset;
7664
7665         if (!stream->stsc_sample_index
7666             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
7667                 &stream->chunk_offset))
7668           goto corrupt_file;
7669
7670         samples_per_chunk = stream->samples_per_chunk;
7671         chunk_offset = stream->chunk_offset;
7672
7673         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
7674           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
7675               G_GUINT64_FORMAT " and size %d",
7676               (guint) (cur - samples), chunk_offset, cur->size);
7677
7678           cur->offset = chunk_offset;
7679           chunk_offset += cur->size;
7680           cur++;
7681
7682           if (G_UNLIKELY (cur > last)) {
7683             /* save state */
7684             stream->stsc_sample_index = k + 1;
7685             stream->chunk_offset = chunk_offset;
7686             stream->stsc_chunk_index = j;
7687             goto done2;
7688           }
7689         }
7690         stream->stsc_sample_index = 0;
7691       }
7692       stream->stsc_chunk_index = j;
7693     }
7694     stream->stsc_index++;
7695   }
7696
7697   if (stream->chunks_are_samples)
7698     goto ctts;
7699 done2:
7700   {
7701     guint32 n_sample_times;
7702
7703     n_sample_times = stream->n_sample_times;
7704     cur = first;
7705
7706     for (i = stream->stts_index; i < n_sample_times; i++) {
7707       guint32 stts_samples;
7708       gint32 stts_duration;
7709       gint64 stts_time;
7710
7711       if (stream->stts_sample_index >= stream->stts_samples
7712           || !stream->stts_sample_index) {
7713
7714         stream->stts_samples =
7715             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7716         stream->stts_duration =
7717             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7718
7719         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
7720             i, stream->stts_samples, stream->stts_duration);
7721
7722         stream->stts_sample_index = 0;
7723       }
7724
7725       stts_samples = stream->stts_samples;
7726       stts_duration = stream->stts_duration;
7727       stts_time = stream->stts_time;
7728
7729       for (j = stream->stts_sample_index; j < stts_samples; j++) {
7730         GST_DEBUG_OBJECT (qtdemux,
7731             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
7732             (guint) (cur - samples), j,
7733             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
7734
7735         cur->timestamp = stts_time;
7736         cur->duration = stts_duration;
7737
7738         /* avoid 32-bit wrap-around,
7739          * but still mind possible 'negative' duration */
7740         stts_time += (gint64) stts_duration;
7741         cur++;
7742
7743         if (G_UNLIKELY (cur > last)) {
7744           /* save values */
7745           stream->stts_time = stts_time;
7746           stream->stts_sample_index = j + 1;
7747           goto done3;
7748         }
7749       }
7750       stream->stts_sample_index = 0;
7751       stream->stts_time = stts_time;
7752       stream->stts_index++;
7753     }
7754     /* fill up empty timestamps with the last timestamp, this can happen when
7755      * the last samples do not decode and so we don't have timestamps for them.
7756      * We however look at the last timestamp to estimate the track length so we
7757      * need something in here. */
7758     for (; cur < last; cur++) {
7759       GST_DEBUG_OBJECT (qtdemux,
7760           "fill sample %d: timestamp %" GST_TIME_FORMAT,
7761           (guint) (cur - samples),
7762           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
7763       cur->timestamp = stream->stts_time;
7764       cur->duration = -1;
7765     }
7766   }
7767 done3:
7768   {
7769     /* sample sync, can be NULL */
7770     if (stream->stss_present == TRUE) {
7771       guint32 n_sample_syncs;
7772
7773       n_sample_syncs = stream->n_sample_syncs;
7774
7775       if (!n_sample_syncs) {
7776         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
7777         stream->all_keyframe = TRUE;
7778       } else {
7779         for (i = stream->stss_index; i < n_sample_syncs; i++) {
7780           /* note that the first sample is index 1, not 0 */
7781           guint32 index;
7782
7783           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
7784
7785           if (G_LIKELY (index > 0 && index <= n_samples)) {
7786             index -= 1;
7787             samples[index].keyframe = TRUE;
7788             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7789             /* and exit if we have enough samples */
7790             if (G_UNLIKELY (index >= n)) {
7791               i++;
7792               break;
7793             }
7794           }
7795         }
7796         /* save state */
7797         stream->stss_index = i;
7798       }
7799
7800       /* stps marks partial sync frames like open GOP I-Frames */
7801       if (stream->stps_present == TRUE) {
7802         guint32 n_sample_partial_syncs;
7803
7804         n_sample_partial_syncs = stream->n_sample_partial_syncs;
7805
7806         /* if there are no entries, the stss table contains the real
7807          * sync samples */
7808         if (n_sample_partial_syncs) {
7809           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
7810             /* note that the first sample is index 1, not 0 */
7811             guint32 index;
7812
7813             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
7814
7815             if (G_LIKELY (index > 0 && index <= n_samples)) {
7816               index -= 1;
7817               samples[index].keyframe = TRUE;
7818               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7819               /* and exit if we have enough samples */
7820               if (G_UNLIKELY (index >= n)) {
7821                 i++;
7822                 break;
7823               }
7824             }
7825           }
7826           /* save state */
7827           stream->stps_index = i;
7828         }
7829       }
7830     } else {
7831       /* no stss, all samples are keyframes */
7832       stream->all_keyframe = TRUE;
7833       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
7834     }
7835   }
7836
7837 ctts:
7838   /* composition time to sample */
7839   if (stream->ctts_present == TRUE) {
7840     guint32 n_composition_times;
7841     guint32 ctts_count;
7842     gint32 ctts_soffset;
7843
7844     /* Fill in the pts_offsets */
7845     cur = first;
7846     n_composition_times = stream->n_composition_times;
7847
7848     for (i = stream->ctts_index; i < n_composition_times; i++) {
7849       if (stream->ctts_sample_index >= stream->ctts_count
7850           || !stream->ctts_sample_index) {
7851         stream->ctts_count =
7852             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
7853         stream->ctts_soffset =
7854             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7855         stream->ctts_sample_index = 0;
7856       }
7857
7858       ctts_count = stream->ctts_count;
7859       ctts_soffset = stream->ctts_soffset;
7860
7861       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
7862         cur->pts_offset = ctts_soffset;
7863         cur++;
7864
7865         if (G_UNLIKELY (cur > last)) {
7866           /* save state */
7867           stream->ctts_sample_index = j + 1;
7868           goto done;
7869         }
7870       }
7871       stream->ctts_sample_index = 0;
7872       stream->ctts_index++;
7873     }
7874   }
7875 done:
7876   stream->stbl_index = n;
7877   /* if index has been completely parsed, free data that is no-longer needed */
7878   if (n + 1 == stream->n_samples) {
7879     gst_qtdemux_stbl_free (stream);
7880     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
7881     if (qtdemux->pullbased) {
7882       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
7883       while (n + 1 == stream->n_samples)
7884         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
7885           break;
7886     }
7887   }
7888   GST_OBJECT_UNLOCK (qtdemux);
7889
7890   return TRUE;
7891
7892   /* SUCCESS */
7893 already_parsed:
7894   {
7895     GST_LOG_OBJECT (qtdemux,
7896         "Tried to parse up to sample %u but this sample has already been parsed",
7897         n);
7898     /* if fragmented, there may be more */
7899     if (qtdemux->fragmented && n == stream->stbl_index)
7900       goto done;
7901     GST_OBJECT_UNLOCK (qtdemux);
7902     return TRUE;
7903   }
7904   /* ERRORS */
7905 out_of_samples:
7906   {
7907     GST_LOG_OBJECT (qtdemux,
7908         "Tried to parse up to sample %u but there are only %u samples", n + 1,
7909         stream->n_samples);
7910     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7911         (_("This file is corrupt and cannot be played.")), (NULL));
7912     return FALSE;
7913   }
7914 corrupt_file:
7915   {
7916     GST_OBJECT_UNLOCK (qtdemux);
7917     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7918         (_("This file is corrupt and cannot be played.")), (NULL));
7919     return FALSE;
7920   }
7921 }
7922
7923 /* collect all segment info for @stream.
7924  */
7925 static gboolean
7926 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
7927     GNode * trak)
7928 {
7929   GNode *edts;
7930   /* accept edts if they contain gaps at start and there is only
7931    * one media segment */
7932   gboolean allow_pushbased_edts = TRUE;
7933   gint media_segments_count = 0;
7934
7935   /* parse and prepare segment info from the edit list */
7936   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
7937   stream->n_segments = 0;
7938   stream->segments = NULL;
7939   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
7940     GNode *elst;
7941     gint n_segments;
7942     gint i, count;
7943     guint64 time;
7944     GstClockTime stime;
7945     guint8 *buffer;
7946
7947     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
7948     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
7949       goto done;
7950
7951     buffer = elst->data;
7952
7953     n_segments = QT_UINT32 (buffer + 12);
7954
7955     /* we might allocate a bit too much, at least allocate 1 segment */
7956     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
7957
7958     /* segments always start from 0 */
7959     time = 0;
7960     stime = 0;
7961     count = 0;
7962     for (i = 0; i < n_segments; i++) {
7963       guint64 duration;
7964       guint64 media_time;
7965       QtDemuxSegment *segment;
7966       guint32 rate_int;
7967
7968       media_time = QT_UINT32 (buffer + 20 + i * 12);
7969       duration = QT_UINT32 (buffer + 16 + i * 12);
7970
7971       segment = &stream->segments[count++];
7972
7973       /* time and duration expressed in global timescale */
7974       segment->time = stime;
7975       /* add non scaled values so we don't cause roundoff errors */
7976       time += duration;
7977       stime = QTTIME_TO_GSTTIME (qtdemux, time);
7978       segment->stop_time = stime;
7979       segment->duration = stime - segment->time;
7980
7981       segment->trak_media_start = media_time;
7982       /* media_time expressed in stream timescale */
7983       if (media_time != G_MAXUINT32) {
7984         segment->media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
7985         segment->media_stop = segment->media_start + segment->duration;
7986         media_segments_count++;
7987       } else {
7988         segment->media_start = GST_CLOCK_TIME_NONE;
7989         segment->media_stop = GST_CLOCK_TIME_NONE;
7990       }
7991       rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
7992
7993       if (rate_int <= 1) {
7994         /* 0 is not allowed, some programs write 1 instead of the floating point
7995          * value */
7996         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
7997             rate_int);
7998         segment->rate = 1;
7999       } else {
8000         segment->rate = rate_int / 65536.0;
8001       }
8002
8003       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8004           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8005           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8006           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8007           i, GST_TIME_ARGS (segment->time),
8008           GST_TIME_ARGS (segment->duration),
8009           GST_TIME_ARGS (segment->media_start), media_time,
8010           GST_TIME_ARGS (segment->media_stop),
8011           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8012           stream->timescale);
8013       if (segment->stop_time > qtdemux->segment.stop) {
8014         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8015             " extends to %" GST_TIME_FORMAT
8016             " past the end of the file duration %" GST_TIME_FORMAT
8017             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8018             GST_TIME_ARGS (qtdemux->segment.stop));
8019         qtdemux->segment.stop = segment->stop_time;
8020       }
8021     }
8022     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8023     stream->n_segments = count;
8024     if (media_segments_count != 1)
8025       allow_pushbased_edts = FALSE;
8026   }
8027 done:
8028
8029   /* push based does not handle segments, so act accordingly here,
8030    * and warn if applicable */
8031   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8032     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8033     /* remove and use default one below, we stream like it anyway */
8034     g_free (stream->segments);
8035     stream->segments = NULL;
8036     stream->n_segments = 0;
8037   }
8038
8039   /* no segments, create one to play the complete trak */
8040   if (stream->n_segments == 0) {
8041     GstClockTime stream_duration =
8042         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8043
8044     if (stream->segments == NULL)
8045       stream->segments = g_new (QtDemuxSegment, 1);
8046
8047     /* represent unknown our way */
8048     if (stream_duration == 0)
8049       stream_duration = GST_CLOCK_TIME_NONE;
8050
8051     stream->segments[0].time = 0;
8052     stream->segments[0].stop_time = stream_duration;
8053     stream->segments[0].duration = stream_duration;
8054     stream->segments[0].media_start = 0;
8055     stream->segments[0].media_stop = stream_duration;
8056     stream->segments[0].rate = 1.0;
8057     stream->segments[0].trak_media_start = 0;
8058
8059     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8060         GST_TIME_ARGS (stream_duration));
8061     stream->n_segments = 1;
8062     stream->dummy_segment = TRUE;
8063   }
8064   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8065
8066   return TRUE;
8067 }
8068
8069 /*
8070  * Parses the stsd atom of a svq3 trak looking for
8071  * the SMI and gama atoms.
8072  */
8073 static void
8074 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8075     guint8 ** gamma, GstBuffer ** seqh)
8076 {
8077   guint8 *_gamma = NULL;
8078   GstBuffer *_seqh = NULL;
8079   guint8 *stsd_data = stsd->data;
8080   guint32 length = QT_UINT32 (stsd_data);
8081   guint16 version;
8082
8083   if (length < 32) {
8084     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8085     goto end;
8086   }
8087
8088   stsd_data += 32;
8089   length -= 32;
8090   version = QT_UINT16 (stsd_data);
8091   if (version == 3) {
8092     if (length >= 70) {
8093       length -= 70;
8094       stsd_data += 70;
8095       while (length > 8) {
8096         guint32 fourcc, size;
8097         guint8 *data;
8098         size = QT_UINT32 (stsd_data);
8099         fourcc = QT_FOURCC (stsd_data + 4);
8100         data = stsd_data + 8;
8101
8102         if (size == 0) {
8103           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8104               "svq3 atom parsing");
8105           goto end;
8106         }
8107
8108         switch (fourcc) {
8109           case FOURCC_gama:{
8110             if (size == 12) {
8111               _gamma = data;
8112             } else {
8113               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8114                   " for gama atom, expected 12", size);
8115             }
8116             break;
8117           }
8118           case FOURCC_SMI_:{
8119             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8120               guint32 seqh_size;
8121               if (_seqh != NULL) {
8122                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8123                     " found, ignoring");
8124               } else {
8125                 seqh_size = QT_UINT32 (data + 4);
8126                 if (seqh_size > 0) {
8127                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8128                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8129                 }
8130               }
8131             }
8132             break;
8133           }
8134           default:{
8135             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8136                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8137           }
8138         }
8139
8140         if (size <= length) {
8141           length -= size;
8142           stsd_data += size;
8143         }
8144       }
8145     } else {
8146       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8147     }
8148   } else {
8149     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8150         G_GUINT16_FORMAT, version);
8151     goto end;
8152   }
8153
8154 end:
8155   if (gamma) {
8156     *gamma = _gamma;
8157   }
8158   if (seqh) {
8159     *seqh = _seqh;
8160   } else if (_seqh) {
8161     gst_buffer_unref (_seqh);
8162   }
8163 }
8164
8165 static gchar *
8166 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8167 {
8168   GNode *dinf;
8169   GstByteReader dref;
8170   gchar *uri = NULL;
8171
8172   /*
8173    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8174    * atom that might contain a 'data' atom with the rtsp uri.
8175    * This case was reported in bug #597497, some info about
8176    * the hndl atom can be found in TN1195
8177    */
8178   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8179   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8180
8181   if (dinf) {
8182     guint32 dref_num_entries = 0;
8183     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8184         gst_byte_reader_skip (&dref, 4) &&
8185         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8186       gint i;
8187
8188       /* search dref entries for hndl atom */
8189       for (i = 0; i < dref_num_entries; i++) {
8190         guint32 size = 0, type;
8191         guint8 string_len = 0;
8192         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8193             qt_atom_parser_get_fourcc (&dref, &type)) {
8194           if (type == FOURCC_hndl) {
8195             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8196
8197             /* skip data reference handle bytes and the
8198              * following pascal string and some extra 4
8199              * bytes I have no idea what are */
8200             if (!gst_byte_reader_skip (&dref, 4) ||
8201                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8202                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8203               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8204               break;
8205             }
8206
8207             /* iterate over the atoms to find the data atom */
8208             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8209               guint32 atom_size;
8210               guint32 atom_type;
8211
8212               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8213                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8214                 if (atom_type == FOURCC_data) {
8215                   const guint8 *uri_aux = NULL;
8216
8217                   /* found the data atom that might contain the rtsp uri */
8218                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8219                       "hndl atom, interpreting it as an URI");
8220                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8221                           &uri_aux)) {
8222                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8223                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8224                     else
8225                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8226                           "didn't contain a rtsp address");
8227                   } else {
8228                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8229                         "atom contents");
8230                   }
8231                   break;
8232                 }
8233                 /* skipping to the next entry */
8234                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8235                   break;
8236               } else {
8237                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8238                     "atom header");
8239                 break;
8240               }
8241             }
8242             break;
8243           }
8244           /* skip to the next entry */
8245           if (!gst_byte_reader_skip (&dref, size - 8))
8246             break;
8247         } else {
8248           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8249         }
8250       }
8251       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8252     }
8253   }
8254   return uri;
8255 }
8256
8257 #define AMR_NB_ALL_MODES        0x81ff
8258 #define AMR_WB_ALL_MODES        0x83ff
8259 static guint
8260 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8261 {
8262   /* The 'damr' atom is of the form:
8263    *
8264    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8265    *    32 b       8 b          16 b           8 b                 8 b
8266    *
8267    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8268    * represents the highest mode used in the stream (and thus the maximum
8269    * bitrate), with a couple of special cases as seen below.
8270    */
8271
8272   /* Map of frame type ID -> bitrate */
8273   static const guint nb_bitrates[] = {
8274     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8275   };
8276   static const guint wb_bitrates[] = {
8277     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8278   };
8279   GstMapInfo map;
8280   gsize max_mode;
8281   guint16 mode_set;
8282
8283   gst_buffer_map (buf, &map, GST_MAP_READ);
8284
8285   if (map.size != 0x11) {
8286     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8287     goto bad_data;
8288   }
8289
8290   if (QT_FOURCC (map.data + 4) != GST_MAKE_FOURCC ('d', 'a', 'm', 'r')) {
8291     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8292         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8293     goto bad_data;
8294   }
8295
8296   mode_set = QT_UINT16 (map.data + 13);
8297
8298   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8299     max_mode = 7 + (wb ? 1 : 0);
8300   else
8301     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8302     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8303
8304   if (max_mode == -1) {
8305     GST_DEBUG ("No mode indication was found (mode set) = %x",
8306         (guint) mode_set);
8307     goto bad_data;
8308   }
8309
8310   gst_buffer_unmap (buf, &map);
8311   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8312
8313 bad_data:
8314   gst_buffer_unmap (buf, &map);
8315   return 0;
8316 }
8317
8318 static gboolean
8319 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8320     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8321 {
8322   /*
8323    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8324    * [0 1 2]
8325    * [3 4 5]
8326    * [6 7 8]
8327    */
8328
8329   if (gst_byte_reader_get_remaining (reader) < 36)
8330     return FALSE;
8331
8332   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8333   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8334   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8335   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8336   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8337   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8338   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8339   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8340   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8341
8342   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8343   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8344       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8345       matrix[2] & 0xFF);
8346   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8347       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8348       matrix[5] & 0xFF);
8349   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8350       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8351       matrix[8] & 0xFF);
8352
8353   return TRUE;
8354 }
8355
8356 static void
8357 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8358     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8359 {
8360
8361 /* [a b c]
8362  * [d e f]
8363  * [g h i]
8364  *
8365  * This macro will only compare value abdegh, it expects cfi to have already
8366  * been checked
8367  */
8368 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8369                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8370
8371   /* only handle the cases where the last column has standard values */
8372   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8373     const gchar *rotation_tag = NULL;
8374
8375     /* no rotation needed */
8376     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8377       /* NOP */
8378     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8379       rotation_tag = "rotate-90";
8380     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8381       rotation_tag = "rotate-180";
8382     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8383       rotation_tag = "rotate-270";
8384     } else {
8385       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8386     }
8387
8388     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8389         rotation_tag);
8390     if (rotation_tag != NULL) {
8391       if (*taglist == NULL)
8392         *taglist = gst_tag_list_new_empty ();
8393       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8394           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8395     }
8396   } else {
8397     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8398   }
8399 }
8400
8401 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8402  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8403  * Common Encryption (cenc), the function will also parse the tenc box (defined
8404  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8405  * (typically an enc[v|a|t|s] sample entry); the function will set
8406  * @original_fmt to the fourcc of the original unencrypted stream format.
8407  * Returns TRUE if successful; FALSE otherwise. */
8408 static gboolean
8409 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8410     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8411 {
8412   GNode *sinf;
8413   GNode *frma;
8414   GNode *schm;
8415   GNode *schi;
8416
8417   g_return_val_if_fail (qtdemux != NULL, FALSE);
8418   g_return_val_if_fail (stream != NULL, FALSE);
8419   g_return_val_if_fail (container != NULL, FALSE);
8420   g_return_val_if_fail (original_fmt != NULL, FALSE);
8421
8422   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8423   if (G_UNLIKELY (!sinf)) {
8424     if (stream->protection_scheme_type == FOURCC_cenc) {
8425       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8426           "mandatory for Common Encryption");
8427       return FALSE;
8428     }
8429     return TRUE;
8430   }
8431
8432   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8433   if (G_UNLIKELY (!frma)) {
8434     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8435     return FALSE;
8436   }
8437
8438   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8439   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8440       GST_FOURCC_ARGS (*original_fmt));
8441
8442   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8443   if (!schm) {
8444     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8445     return FALSE;
8446   }
8447   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
8448   stream->protection_scheme_version =
8449       QT_UINT32 ((const guint8 *) schm->data + 16);
8450
8451   GST_DEBUG_OBJECT (qtdemux,
8452       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
8453       "protection_scheme_version: %#010x",
8454       GST_FOURCC_ARGS (stream->protection_scheme_type),
8455       stream->protection_scheme_version);
8456
8457   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
8458   if (!schi) {
8459     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
8460     return FALSE;
8461   }
8462   if (stream->protection_scheme_type == FOURCC_cenc) {
8463     QtDemuxCencSampleSetInfo *info;
8464     GNode *tenc;
8465     const guint8 *tenc_data;
8466     guint32 isEncrypted;
8467     guint8 iv_size;
8468     const guint8 *default_kid;
8469     GstBuffer *kid_buf;
8470
8471     if (G_UNLIKELY (!stream->protection_scheme_info))
8472       stream->protection_scheme_info =
8473           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
8474
8475     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
8476
8477     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
8478     if (!tenc) {
8479       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
8480           "which is mandatory for Common Encryption");
8481       return FALSE;
8482     }
8483     tenc_data = (const guint8 *) tenc->data + 12;
8484     isEncrypted = QT_UINT24 (tenc_data);
8485     iv_size = QT_UINT8 (tenc_data + 3);
8486     default_kid = (tenc_data + 4);
8487     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
8488     gst_buffer_fill (kid_buf, 0, default_kid, 16);
8489     if (info->default_properties)
8490       gst_structure_free (info->default_properties);
8491     info->default_properties =
8492         gst_structure_new ("application/x-cenc",
8493         "iv_size", G_TYPE_UINT, iv_size,
8494         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
8495         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
8496     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
8497         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
8498     gst_buffer_unref (kid_buf);
8499   }
8500   return TRUE;
8501 }
8502
8503 /* parse the traks.
8504  * With each track we associate a new QtDemuxStream that contains all the info
8505  * about the trak.
8506  * traks that do not decode to something (like strm traks) will not have a pad.
8507  */
8508 static gboolean
8509 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
8510 {
8511   GstByteReader tkhd;
8512   int offset;
8513   GNode *mdia;
8514   GNode *mdhd;
8515   GNode *hdlr;
8516   GNode *minf;
8517   GNode *stbl;
8518   GNode *stsd;
8519   GNode *mp4a;
8520   GNode *mp4v;
8521   GNode *wave;
8522   GNode *esds;
8523   GNode *pasp;
8524   GNode *tref;
8525   GNode *udta;
8526   GNode *svmi;
8527
8528   QtDemuxStream *stream = NULL;
8529   gboolean new_stream = FALSE;
8530   gchar *codec = NULL;
8531   const guint8 *stsd_data;
8532   guint16 lang_code;            /* quicktime lang code or packed iso code */
8533   guint32 version;
8534   guint32 tkhd_flags = 0;
8535   guint8 tkhd_version = 0;
8536   guint32 fourcc;
8537   guint value_size, stsd_len, len;
8538   guint32 track_id;
8539   guint32 dummy;
8540
8541   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
8542
8543   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
8544       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
8545       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
8546     goto corrupt_file;
8547
8548   /* pick between 64 or 32 bits */
8549   value_size = tkhd_version == 1 ? 8 : 4;
8550   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
8551       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
8552     goto corrupt_file;
8553
8554   if (!qtdemux->got_moov) {
8555     if (qtdemux_find_stream (qtdemux, track_id))
8556       goto existing_stream;
8557     stream = _create_stream ();
8558     stream->track_id = track_id;
8559     new_stream = TRUE;
8560   } else {
8561     stream = qtdemux_find_stream (qtdemux, track_id);
8562     if (!stream) {
8563       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
8564       goto skip_track;
8565     }
8566
8567     /* flush samples data from this track from previous moov */
8568     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
8569     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
8570   }
8571   /* need defaults for fragments */
8572   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
8573
8574   if (stream->pending_tags == NULL)
8575     stream->pending_tags = gst_tag_list_new_empty ();
8576
8577   if ((tkhd_flags & 1) == 0)
8578     stream->disabled = TRUE;
8579
8580   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
8581       tkhd_version, tkhd_flags, stream->track_id);
8582
8583   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
8584     goto corrupt_file;
8585
8586   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
8587     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
8588     if (qtdemux->major_brand != FOURCC_mjp2 ||
8589         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
8590       goto corrupt_file;
8591   }
8592
8593   len = QT_UINT32 ((guint8 *) mdhd->data);
8594   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
8595   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
8596   if (version == 0x01000000) {
8597     if (len < 38)
8598       goto corrupt_file;
8599     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
8600     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
8601     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
8602   } else {
8603     if (len < 30)
8604       goto corrupt_file;
8605     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
8606     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
8607     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
8608   }
8609
8610   if (lang_code < 0x400) {
8611     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
8612   } else if (lang_code == 0x7fff) {
8613     stream->lang_id[0] = 0;     /* unspecified */
8614   } else {
8615     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
8616     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
8617     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
8618     stream->lang_id[3] = 0;
8619   }
8620
8621   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
8622       stream->timescale);
8623   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
8624       stream->duration);
8625   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
8626       lang_code, stream->lang_id);
8627
8628   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
8629     goto corrupt_file;
8630
8631   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
8632     /* chapters track reference */
8633     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
8634     if (chap) {
8635       gsize length = GST_READ_UINT32_BE (chap->data);
8636       if (qtdemux->chapters_track_id)
8637         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
8638
8639       if (length >= 12) {
8640         qtdemux->chapters_track_id =
8641             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
8642       }
8643     }
8644   }
8645
8646   /* fragmented files may have bogus duration in moov */
8647   if (!qtdemux->fragmented &&
8648       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
8649     guint64 tdur1, tdur2;
8650
8651     /* don't overflow */
8652     tdur1 = stream->timescale * (guint64) qtdemux->duration;
8653     tdur2 = qtdemux->timescale * (guint64) stream->duration;
8654
8655     /* HACK:
8656      * some of those trailers, nowadays, have prologue images that are
8657      * themselves vide tracks as well. I haven't really found a way to
8658      * identify those yet, except for just looking at their duration. */
8659     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
8660       GST_WARNING_OBJECT (qtdemux,
8661           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
8662           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
8663           "found, assuming preview image or something; skipping track",
8664           stream->duration, stream->timescale, qtdemux->duration,
8665           qtdemux->timescale);
8666       if (new_stream)
8667         gst_qtdemux_stream_free (qtdemux, stream);
8668       return TRUE;
8669     }
8670   }
8671
8672   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
8673     goto corrupt_file;
8674
8675   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
8676       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
8677
8678   len = QT_UINT32 ((guint8 *) hdlr->data);
8679   if (len >= 20)
8680     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
8681   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
8682       GST_FOURCC_ARGS (stream->subtype));
8683
8684   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
8685     goto corrupt_file;
8686
8687   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
8688     goto corrupt_file;
8689
8690   /*parse svmi header if existing */
8691   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
8692   if (svmi) {
8693     len = QT_UINT32 ((guint8 *) svmi->data);
8694     version = QT_UINT32 ((guint8 *) svmi->data + 8);
8695     if (!version) {
8696       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
8697       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
8698       guint8 frame_type, frame_layout;
8699
8700       /* MPEG-A stereo video */
8701       if (qtdemux->major_brand == FOURCC_ss02)
8702         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
8703
8704       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
8705       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
8706       switch (frame_type) {
8707         case 0:
8708           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
8709           break;
8710         case 1:
8711           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
8712           break;
8713         case 2:
8714           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
8715           break;
8716         case 3:
8717           /* mode 3 is primary/secondary view sequence, ie
8718            * left/right views in separate tracks. See section 7.2
8719            * of ISO/IEC 23000-11:2009 */
8720           GST_FIXME_OBJECT (qtdemux,
8721               "Implement stereo video in separate streams");
8722       }
8723
8724       if ((frame_layout & 0x1) == 0)
8725         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
8726
8727       GST_LOG_OBJECT (qtdemux,
8728           "StereoVideo: composition type: %u, is_left_first: %u",
8729           frame_type, frame_layout);
8730       stream->multiview_mode = mode;
8731       stream->multiview_flags = flags;
8732     }
8733   }
8734
8735   /* parse stsd */
8736   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
8737     goto corrupt_file;
8738   stsd_data = (const guint8 *) stsd->data;
8739
8740   /* stsd should at least have one entry */
8741   stsd_len = QT_UINT32 (stsd_data);
8742   if (stsd_len < 24) {
8743     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
8744     if (stream->subtype == FOURCC_vivo) {
8745       if (new_stream)
8746         gst_qtdemux_stream_free (qtdemux, stream);
8747       return TRUE;
8748     } else {
8749       goto corrupt_file;
8750     }
8751   }
8752
8753   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
8754
8755   /* and that entry should fit within stsd */
8756   len = QT_UINT32 (stsd_data + 16);
8757   if (len > stsd_len + 16)
8758     goto corrupt_file;
8759
8760   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
8761   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
8762       GST_FOURCC_ARGS (stream->fourcc));
8763   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
8764
8765   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
8766     goto error_encrypted;
8767
8768   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
8769     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
8770     stream->protected = TRUE;
8771     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
8772       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
8773   }
8774
8775   if (stream->subtype == FOURCC_vide) {
8776     guint32 w = 0, h = 0;
8777     gboolean gray;
8778     gint depth, palette_size, palette_count;
8779     guint32 matrix[9];
8780     guint32 *palette_data = NULL;
8781
8782     stream->sampled = TRUE;
8783
8784     /* version 1 uses some 64-bit ints */
8785     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
8786       goto corrupt_file;
8787
8788     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
8789       goto corrupt_file;
8790
8791     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
8792         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
8793       goto corrupt_file;
8794
8795     stream->display_width = w >> 16;
8796     stream->display_height = h >> 16;
8797
8798     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
8799         &stream->pending_tags);
8800
8801     offset = 16;
8802     if (len < 86)
8803       goto corrupt_file;
8804
8805     stream->width = QT_UINT16 (stsd_data + offset + 32);
8806     stream->height = QT_UINT16 (stsd_data + offset + 34);
8807     stream->fps_n = 0;          /* this is filled in later */
8808     stream->fps_d = 0;          /* this is filled in later */
8809     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
8810     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
8811
8812     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
8813         stream->width, stream->height, stream->bits_per_sample,
8814         stream->color_table_id);
8815
8816     depth = stream->bits_per_sample;
8817
8818     /* more than 32 bits means grayscale */
8819     gray = (depth > 32);
8820     /* low 32 bits specify the depth  */
8821     depth &= 0x1F;
8822
8823     /* different number of palette entries is determined by depth. */
8824     palette_count = 0;
8825     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
8826       palette_count = (1 << depth);
8827     palette_size = palette_count * 4;
8828
8829     if (stream->color_table_id) {
8830       switch (palette_count) {
8831         case 0:
8832           break;
8833         case 2:
8834           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
8835           break;
8836         case 4:
8837           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
8838           break;
8839         case 16:
8840           if (gray)
8841             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
8842           else
8843             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
8844           break;
8845         case 256:
8846           if (gray)
8847             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
8848           else
8849             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
8850           break;
8851         default:
8852           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
8853               (_("The video in this file might not play correctly.")),
8854               ("unsupported palette depth %d", depth));
8855           break;
8856       }
8857     } else {
8858       gint i, j, start, end;
8859
8860       if (len < 94)
8861         goto corrupt_file;
8862
8863       /* read table */
8864       start = QT_UINT32 (stsd_data + offset + 86);
8865       palette_count = QT_UINT16 (stsd_data + offset + 90);
8866       end = QT_UINT16 (stsd_data + offset + 92);
8867
8868       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
8869           start, end, palette_count);
8870
8871       if (end > 255)
8872         end = 255;
8873       if (start > end)
8874         start = end;
8875
8876       if (len < 94 + (end - start) * 8)
8877         goto corrupt_file;
8878
8879       /* palette is always the same size */
8880       palette_data = g_malloc0 (256 * 4);
8881       palette_size = 256 * 4;
8882
8883       for (j = 0, i = start; i <= end; j++, i++) {
8884         guint32 a, r, g, b;
8885
8886         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
8887         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
8888         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
8889         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
8890
8891         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
8892             (g & 0xff00) | (b >> 8);
8893       }
8894     }
8895
8896     if (stream->caps)
8897       gst_caps_unref (stream->caps);
8898
8899     stream->caps =
8900         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
8901     if (G_UNLIKELY (!stream->caps)) {
8902       g_free (palette_data);
8903       goto unknown_stream;
8904     }
8905
8906     if (codec) {
8907       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
8908           GST_TAG_VIDEO_CODEC, codec, NULL);
8909       g_free (codec);
8910       codec = NULL;
8911     }
8912
8913
8914     if (palette_data) {
8915       GstStructure *s;
8916
8917       if (stream->rgb8_palette)
8918         gst_memory_unref (stream->rgb8_palette);
8919       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
8920           palette_data, palette_size, 0, palette_size, palette_data, g_free);
8921
8922       s = gst_caps_get_structure (stream->caps, 0);
8923
8924       /* non-raw video has a palette_data property. raw video has the palette as
8925        * an extra plane that we append to the output buffers before we push
8926        * them*/
8927       if (!gst_structure_has_name (s, "video/x-raw")) {
8928         GstBuffer *palette;
8929
8930         palette = gst_buffer_new ();
8931         gst_buffer_append_memory (palette, stream->rgb8_palette);
8932         stream->rgb8_palette = NULL;
8933
8934         gst_caps_set_simple (stream->caps, "palette_data",
8935             GST_TYPE_BUFFER, palette, NULL);
8936         gst_buffer_unref (palette);
8937       }
8938     } else if (palette_count != 0) {
8939       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
8940           (NULL), ("Unsupported palette depth %d", depth));
8941     }
8942
8943     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
8944         QT_UINT16 (stsd_data + offset + 48));
8945
8946     esds = NULL;
8947     pasp = NULL;
8948     /* pick 'the' stsd child */
8949     if (!stream->protected)
8950       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
8951     else
8952       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
8953
8954     if (mp4v) {
8955       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
8956       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
8957     }
8958
8959     if (pasp) {
8960       const guint8 *pasp_data = (const guint8 *) pasp->data;
8961
8962       stream->par_w = QT_UINT32 (pasp_data + 8);
8963       stream->par_h = QT_UINT32 (pasp_data + 12);
8964     } else {
8965       stream->par_w = 0;
8966       stream->par_h = 0;
8967     }
8968
8969     if (esds) {
8970       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
8971     } else {
8972       switch (fourcc) {
8973         case FOURCC_H264:
8974         case FOURCC_avc1:
8975         case FOURCC_avc3:
8976         {
8977           gint len = QT_UINT32 (stsd_data) - 0x66;
8978           const guint8 *avc_data = stsd_data + 0x66;
8979
8980           /* find avcC */
8981           while (len >= 0x8) {
8982             gint size;
8983
8984             if (QT_UINT32 (avc_data) <= len)
8985               size = QT_UINT32 (avc_data) - 0x8;
8986             else
8987               size = len - 0x8;
8988
8989             if (size < 1)
8990               /* No real data, so break out */
8991               break;
8992
8993             switch (QT_FOURCC (avc_data + 0x4)) {
8994               case FOURCC_avcC:
8995               {
8996                 /* parse, if found */
8997                 GstBuffer *buf;
8998
8999                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9000
9001                 /* First 4 bytes are the length of the atom, the next 4 bytes
9002                  * are the fourcc, the next 1 byte is the version, and the
9003                  * subsequent bytes are profile_tier_level structure like data. */
9004                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9005                     avc_data + 8 + 1, size - 1);
9006                 buf = gst_buffer_new_and_alloc (size);
9007                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9008                 gst_caps_set_simple (stream->caps,
9009                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9010                 gst_buffer_unref (buf);
9011
9012                 break;
9013               }
9014               case FOURCC_strf:
9015               {
9016                 GstBuffer *buf;
9017
9018                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9019
9020                 /* First 4 bytes are the length of the atom, the next 4 bytes
9021                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9022                  * next 1 byte is the version, and the
9023                  * subsequent bytes are sequence parameter set like data. */
9024
9025                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9026                 if (size > 1) {
9027                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9028                       avc_data + 8 + 40 + 1, size - 1);
9029
9030                   buf = gst_buffer_new_and_alloc (size);
9031                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9032                   gst_caps_set_simple (stream->caps,
9033                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9034                   gst_buffer_unref (buf);
9035                 }
9036                 break;
9037               }
9038               case FOURCC_btrt:
9039               {
9040                 guint avg_bitrate, max_bitrate;
9041
9042                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9043                 if (size < 12)
9044                   break;
9045
9046                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9047                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9048
9049                 if (!max_bitrate && !avg_bitrate)
9050                   break;
9051
9052                 /* Some muxers seem to swap the average and maximum bitrates
9053                  * (I'm looking at you, YouTube), so we swap for sanity. */
9054                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9055                   guint temp = avg_bitrate;
9056
9057                   avg_bitrate = max_bitrate;
9058                   max_bitrate = temp;
9059                 }
9060
9061                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9062                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9063                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9064                 }
9065                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9066                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9067                       GST_TAG_BITRATE, avg_bitrate, NULL);
9068                 }
9069
9070                 break;
9071               }
9072
9073               default:
9074                 break;
9075             }
9076
9077             len -= size + 8;
9078             avc_data += size + 8;
9079           }
9080
9081           break;
9082         }
9083         case FOURCC_H265:
9084         case FOURCC_hvc1:
9085         case FOURCC_hev1:
9086         {
9087           gint len = QT_UINT32 (stsd_data) - 0x66;
9088           const guint8 *hevc_data = stsd_data + 0x66;
9089
9090           /* find hevc */
9091           while (len >= 0x8) {
9092             gint size;
9093
9094             if (QT_UINT32 (hevc_data) <= len)
9095               size = QT_UINT32 (hevc_data) - 0x8;
9096             else
9097               size = len - 0x8;
9098
9099             if (size < 1)
9100               /* No real data, so break out */
9101               break;
9102
9103             switch (QT_FOURCC (hevc_data + 0x4)) {
9104               case FOURCC_hvcC:
9105               {
9106                 /* parse, if found */
9107                 GstBuffer *buf;
9108
9109                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9110
9111                 /* First 4 bytes are the length of the atom, the next 4 bytes
9112                  * are the fourcc, the next 1 byte is the version, and the
9113                  * subsequent bytes are sequence parameter set like data. */
9114                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9115                     (stream->caps, hevc_data + 8 + 1, size - 1);
9116
9117                 buf = gst_buffer_new_and_alloc (size);
9118                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9119                 gst_caps_set_simple (stream->caps,
9120                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9121                 gst_buffer_unref (buf);
9122                 break;
9123               }
9124               default:
9125                 break;
9126             }
9127             len -= size + 8;
9128             hevc_data += size + 8;
9129           }
9130           break;
9131         }
9132         case FOURCC_mp4v:
9133         case FOURCC_MP4V:
9134         case FOURCC_fmp4:
9135         case FOURCC_FMP4:
9136         {
9137           GNode *glbl;
9138
9139           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9140               GST_FOURCC_ARGS (fourcc));
9141
9142           /* codec data might be in glbl extension atom */
9143           glbl = mp4v ?
9144               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9145           if (glbl) {
9146             guint8 *data;
9147             GstBuffer *buf;
9148             gint len;
9149
9150             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9151             data = glbl->data;
9152             len = QT_UINT32 (data);
9153             if (len > 0x8) {
9154               len -= 0x8;
9155               buf = gst_buffer_new_and_alloc (len);
9156               gst_buffer_fill (buf, 0, data + 8, len);
9157               gst_caps_set_simple (stream->caps,
9158                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9159               gst_buffer_unref (buf);
9160             }
9161           }
9162           break;
9163         }
9164         case FOURCC_mjp2:
9165         {
9166           /* see annex I of the jpeg2000 spec */
9167           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9168           const guint8 *data;
9169           const gchar *colorspace = NULL;
9170           gint ncomp = 0;
9171           guint32 ncomp_map = 0;
9172           gint32 *comp_map = NULL;
9173           guint32 nchan_def = 0;
9174           gint32 *chan_def = NULL;
9175
9176           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9177           /* some required atoms */
9178           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9179           if (!mjp2)
9180             break;
9181           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9182           if (!jp2h)
9183             break;
9184
9185           /* number of components; redundant with info in codestream, but useful
9186              to a muxer */
9187           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9188           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9189             break;
9190           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9191
9192           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9193           if (!colr)
9194             break;
9195           GST_DEBUG_OBJECT (qtdemux, "found colr");
9196           /* extract colour space info */
9197           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9198             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9199               case 16:
9200                 colorspace = "sRGB";
9201                 break;
9202               case 17:
9203                 colorspace = "GRAY";
9204                 break;
9205               case 18:
9206                 colorspace = "sYUV";
9207                 break;
9208               default:
9209                 colorspace = NULL;
9210                 break;
9211             }
9212           }
9213           if (!colorspace)
9214             /* colr is required, and only values 16, 17, and 18 are specified,
9215                so error if we have no colorspace */
9216             break;
9217
9218           /* extract component mapping */
9219           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9220           if (cmap) {
9221             guint32 cmap_len = 0;
9222             int i;
9223             cmap_len = QT_UINT32 (cmap->data);
9224             if (cmap_len >= 8) {
9225               /* normal box, subtract off header */
9226               cmap_len -= 8;
9227               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9228               if (cmap_len % 4 == 0) {
9229                 ncomp_map = (cmap_len / 4);
9230                 comp_map = g_new0 (gint32, ncomp_map);
9231                 for (i = 0; i < ncomp_map; i++) {
9232                   guint16 cmp;
9233                   guint8 mtyp, pcol;
9234                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9235                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9236                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9237                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9238                 }
9239               }
9240             }
9241           }
9242           /* extract channel definitions */
9243           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9244           if (cdef) {
9245             guint32 cdef_len = 0;
9246             int i;
9247             cdef_len = QT_UINT32 (cdef->data);
9248             if (cdef_len >= 10) {
9249               /* normal box, subtract off header and len */
9250               cdef_len -= 10;
9251               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9252               if (cdef_len % 6 == 0) {
9253                 nchan_def = (cdef_len / 6);
9254                 chan_def = g_new0 (gint32, nchan_def);
9255                 for (i = 0; i < nchan_def; i++)
9256                   chan_def[i] = -1;
9257                 for (i = 0; i < nchan_def; i++) {
9258                   guint16 cn, typ, asoc;
9259                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9260                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9261                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9262                   if (cn < nchan_def) {
9263                     switch (typ) {
9264                       case 0:
9265                         chan_def[cn] = asoc;
9266                         break;
9267                       case 1:
9268                         chan_def[cn] = 0;       /* alpha */
9269                         break;
9270                       default:
9271                         chan_def[cn] = -typ;
9272                     }
9273                   }
9274                 }
9275               }
9276             }
9277           }
9278
9279           gst_caps_set_simple (stream->caps,
9280               "num-components", G_TYPE_INT, ncomp, NULL);
9281           gst_caps_set_simple (stream->caps,
9282               "colorspace", G_TYPE_STRING, colorspace, NULL);
9283
9284           if (comp_map) {
9285             GValue arr = { 0, };
9286             GValue elt = { 0, };
9287             int i;
9288             g_value_init (&arr, GST_TYPE_ARRAY);
9289             g_value_init (&elt, G_TYPE_INT);
9290             for (i = 0; i < ncomp_map; i++) {
9291               g_value_set_int (&elt, comp_map[i]);
9292               gst_value_array_append_value (&arr, &elt);
9293             }
9294             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9295                 "component-map", &arr);
9296             g_value_unset (&elt);
9297             g_value_unset (&arr);
9298             g_free (comp_map);
9299           }
9300
9301           if (chan_def) {
9302             GValue arr = { 0, };
9303             GValue elt = { 0, };
9304             int i;
9305             g_value_init (&arr, GST_TYPE_ARRAY);
9306             g_value_init (&elt, G_TYPE_INT);
9307             for (i = 0; i < nchan_def; i++) {
9308               g_value_set_int (&elt, chan_def[i]);
9309               gst_value_array_append_value (&arr, &elt);
9310             }
9311             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9312                 "channel-definitions", &arr);
9313             g_value_unset (&elt);
9314             g_value_unset (&arr);
9315             g_free (chan_def);
9316           }
9317
9318           /* some optional atoms */
9319           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9320           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9321
9322           /* indicate possible fields in caps */
9323           if (field) {
9324             data = (guint8 *) field->data + 8;
9325             if (*data != 1)
9326               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9327                   (gint) * data, NULL);
9328           }
9329           /* add codec_data if provided */
9330           if (prefix) {
9331             GstBuffer *buf;
9332             gint len;
9333
9334             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9335             data = prefix->data;
9336             len = QT_UINT32 (data);
9337             if (len > 0x8) {
9338               len -= 0x8;
9339               buf = gst_buffer_new_and_alloc (len);
9340               gst_buffer_fill (buf, 0, data + 8, len);
9341               gst_caps_set_simple (stream->caps,
9342                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9343               gst_buffer_unref (buf);
9344             }
9345           }
9346           break;
9347         }
9348         case FOURCC_SVQ3:
9349         case FOURCC_VP31:
9350         {
9351           GstBuffer *buf;
9352           GstBuffer *seqh = NULL;
9353           guint8 *gamma_data = NULL;
9354           gint len = QT_UINT32 (stsd_data);
9355
9356           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9357           if (gamma_data) {
9358             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9359                 QT_FP32 (gamma_data), NULL);
9360           }
9361           if (seqh) {
9362             /* sorry for the bad name, but we don't know what this is, other
9363              * than its own fourcc */
9364             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9365                 NULL);
9366           }
9367
9368           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9369           buf = gst_buffer_new_and_alloc (len);
9370           gst_buffer_fill (buf, 0, stsd_data, len);
9371           gst_caps_set_simple (stream->caps,
9372               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9373           gst_buffer_unref (buf);
9374           break;
9375         }
9376         case FOURCC_rle_:
9377         case FOURCC_WRLE:
9378         {
9379           gst_caps_set_simple (stream->caps,
9380               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9381           break;
9382         }
9383         case FOURCC_XiTh:
9384         {
9385           GNode *xith, *xdxt;
9386
9387           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9388           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9389           if (!xith)
9390             break;
9391
9392           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9393           if (!xdxt)
9394             break;
9395
9396           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9397           /* collect the headers and store them in a stream list so that we can
9398            * send them out first */
9399           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9400           break;
9401         }
9402         case FOURCC_ovc1:
9403         {
9404           GNode *ovc1;
9405           guint8 *ovc1_data;
9406           guint ovc1_len;
9407           GstBuffer *buf;
9408
9409           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9410           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9411           if (!ovc1)
9412             break;
9413           ovc1_data = ovc1->data;
9414           ovc1_len = QT_UINT32 (ovc1_data);
9415           if (ovc1_len <= 198) {
9416             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9417             break;
9418           }
9419           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9420           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9421           gst_caps_set_simple (stream->caps,
9422               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9423           gst_buffer_unref (buf);
9424           break;
9425         }
9426         case GST_MAKE_FOURCC ('v', 'c', '-', '1'):
9427         {
9428           gint len = QT_UINT32 (stsd_data) - 0x66;
9429           const guint8 *vc1_data = stsd_data + 0x66;
9430
9431           /* find dvc1 */
9432           while (len >= 8) {
9433             gint size;
9434
9435             if (QT_UINT32 (vc1_data) <= len)
9436               size = QT_UINT32 (vc1_data) - 8;
9437             else
9438               size = len - 8;
9439
9440             if (size < 1)
9441               /* No real data, so break out */
9442               break;
9443
9444             switch (QT_FOURCC (vc1_data + 0x4)) {
9445               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
9446               {
9447                 GstBuffer *buf;
9448
9449                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
9450                 buf = gst_buffer_new_and_alloc (size);
9451                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
9452                 gst_caps_set_simple (stream->caps,
9453                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9454                 gst_buffer_unref (buf);
9455                 break;
9456               }
9457               default:
9458                 break;
9459             }
9460             len -= size + 8;
9461             vc1_data += size + 8;
9462           }
9463           break;
9464         }
9465         default:
9466           break;
9467       }
9468     }
9469
9470     GST_INFO_OBJECT (qtdemux,
9471         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
9472         GST_FOURCC_ARGS (fourcc), stream->caps);
9473
9474   } else if (stream->subtype == FOURCC_soun) {
9475     int version, samplesize;
9476     guint16 compression_id;
9477     gboolean amrwb = FALSE;
9478
9479     offset = 32;
9480     /* sample description entry (16) + sound sample description v0 (20) */
9481     if (len < 36)
9482       goto corrupt_file;
9483
9484     version = QT_UINT32 (stsd_data + offset);
9485     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
9486     samplesize = QT_UINT16 (stsd_data + offset + 10);
9487     compression_id = QT_UINT16 (stsd_data + offset + 12);
9488     stream->rate = QT_FP32 (stsd_data + offset + 16);
9489
9490     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
9491     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
9492         QT_UINT32 (stsd_data + offset + 4));
9493     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
9494     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
9495     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
9496     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
9497         QT_UINT16 (stsd_data + offset + 14));
9498     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
9499
9500     if (compression_id == 0xfffe)
9501       stream->sampled = TRUE;
9502
9503     /* first assume uncompressed audio */
9504     stream->bytes_per_sample = samplesize / 8;
9505     stream->samples_per_frame = stream->n_channels;
9506     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
9507     stream->samples_per_packet = stream->samples_per_frame;
9508     stream->bytes_per_packet = stream->bytes_per_sample;
9509
9510     offset = 52;
9511     switch (fourcc) {
9512         /* Yes, these have to be hard-coded */
9513       case FOURCC_MAC6:
9514       {
9515         stream->samples_per_packet = 6;
9516         stream->bytes_per_packet = 1;
9517         stream->bytes_per_frame = 1 * stream->n_channels;
9518         stream->bytes_per_sample = 1;
9519         stream->samples_per_frame = 6 * stream->n_channels;
9520         break;
9521       }
9522       case FOURCC_MAC3:
9523       {
9524         stream->samples_per_packet = 3;
9525         stream->bytes_per_packet = 1;
9526         stream->bytes_per_frame = 1 * stream->n_channels;
9527         stream->bytes_per_sample = 1;
9528         stream->samples_per_frame = 3 * stream->n_channels;
9529         break;
9530       }
9531       case FOURCC_ima4:
9532       {
9533         stream->samples_per_packet = 64;
9534         stream->bytes_per_packet = 34;
9535         stream->bytes_per_frame = 34 * stream->n_channels;
9536         stream->bytes_per_sample = 2;
9537         stream->samples_per_frame = 64 * stream->n_channels;
9538         break;
9539       }
9540       case FOURCC_ulaw:
9541       case FOURCC_alaw:
9542       {
9543         stream->samples_per_packet = 1;
9544         stream->bytes_per_packet = 1;
9545         stream->bytes_per_frame = 1 * stream->n_channels;
9546         stream->bytes_per_sample = 1;
9547         stream->samples_per_frame = 1 * stream->n_channels;
9548         break;
9549       }
9550       case FOURCC_agsm:
9551       {
9552         stream->samples_per_packet = 160;
9553         stream->bytes_per_packet = 33;
9554         stream->bytes_per_frame = 33 * stream->n_channels;
9555         stream->bytes_per_sample = 2;
9556         stream->samples_per_frame = 160 * stream->n_channels;
9557         break;
9558       }
9559       default:
9560         break;
9561     }
9562
9563     if (version == 0x00010000) {
9564       /* sample description entry (16) + sound sample description v1 (20+16) */
9565       if (len < 52)
9566         goto corrupt_file;
9567
9568       switch (fourcc) {
9569         case FOURCC_twos:
9570         case FOURCC_sowt:
9571         case FOURCC_raw_:
9572           break;
9573         default:
9574         {
9575           /* only parse extra decoding config for non-pcm audio */
9576           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
9577           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
9578           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
9579           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
9580
9581           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
9582               stream->samples_per_packet);
9583           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
9584               stream->bytes_per_packet);
9585           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
9586               stream->bytes_per_frame);
9587           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
9588               stream->bytes_per_sample);
9589
9590           if (!stream->sampled && stream->bytes_per_packet) {
9591             stream->samples_per_frame = (stream->bytes_per_frame /
9592                 stream->bytes_per_packet) * stream->samples_per_packet;
9593             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
9594                 stream->samples_per_frame);
9595           }
9596           break;
9597         }
9598       }
9599     } else if (version == 0x00020000) {
9600       union
9601       {
9602         gdouble fp;
9603         guint64 val;
9604       } qtfp;
9605
9606       /* sample description entry (16) + sound sample description v2 (56) */
9607       if (len < 72)
9608         goto corrupt_file;
9609
9610       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
9611       stream->rate = qtfp.fp;
9612       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
9613
9614       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
9615       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
9616       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
9617       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
9618           QT_UINT32 (stsd_data + offset + 20));
9619       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
9620           QT_UINT32 (stsd_data + offset + 24));
9621       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
9622           QT_UINT32 (stsd_data + offset + 28));
9623       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
9624           QT_UINT32 (stsd_data + offset + 32));
9625     } else if (version != 0x00000) {
9626       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
9627     }
9628
9629     if (stream->caps)
9630       gst_caps_unref (stream->caps);
9631
9632     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
9633         stsd_data + 32, len - 16, &codec);
9634
9635     switch (fourcc) {
9636       case FOURCC_in24:
9637       {
9638         GNode *enda;
9639         GNode *in24;
9640
9641         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
9642
9643         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
9644         if (!enda) {
9645           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
9646           if (wave)
9647             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
9648         }
9649         if (enda) {
9650           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
9651           gst_caps_set_simple (stream->caps,
9652               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
9653         }
9654         break;
9655       }
9656       case FOURCC_owma:
9657       {
9658         GNode *owma;
9659         const guint8 *owma_data;
9660         const gchar *codec_name = NULL;
9661         guint owma_len;
9662         GstBuffer *buf;
9663         gint version = 1;
9664         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9665         /* FIXME this should also be gst_riff_strf_auds,
9666          * but the latter one is actually missing bits-per-sample :( */
9667         typedef struct
9668         {
9669           gint16 wFormatTag;
9670           gint16 nChannels;
9671           gint32 nSamplesPerSec;
9672           gint32 nAvgBytesPerSec;
9673           gint16 nBlockAlign;
9674           gint16 wBitsPerSample;
9675           gint16 cbSize;
9676         } WAVEFORMATEX;
9677         WAVEFORMATEX *wfex;
9678
9679         GST_DEBUG_OBJECT (qtdemux, "parse owma");
9680         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
9681         if (!owma)
9682           break;
9683         owma_data = owma->data;
9684         owma_len = QT_UINT32 (owma_data);
9685         if (owma_len <= 54) {
9686           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
9687           break;
9688         }
9689         wfex = (WAVEFORMATEX *) (owma_data + 36);
9690         buf = gst_buffer_new_and_alloc (owma_len - 54);
9691         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
9692         if (wfex->wFormatTag == 0x0161) {
9693           codec_name = "Windows Media Audio";
9694           version = 2;
9695         } else if (wfex->wFormatTag == 0x0162) {
9696           codec_name = "Windows Media Audio 9 Pro";
9697           version = 3;
9698         } else if (wfex->wFormatTag == 0x0163) {
9699           codec_name = "Windows Media Audio 9 Lossless";
9700           /* is that correct? gstffmpegcodecmap.c is missing it, but
9701            * fluendo codec seems to support it */
9702           version = 4;
9703         }
9704
9705         gst_caps_set_simple (stream->caps,
9706             "codec_data", GST_TYPE_BUFFER, buf,
9707             "wmaversion", G_TYPE_INT, version,
9708             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
9709             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
9710             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9711             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9712             NULL);
9713         gst_buffer_unref (buf);
9714
9715         if (codec_name) {
9716           g_free (codec);
9717           codec = g_strdup (codec_name);
9718         }
9719         break;
9720       }
9721       case GST_MAKE_FOURCC ('w', 'm', 'a', ' '):
9722       {
9723         gint len = QT_UINT32 (stsd_data) - offset;
9724         const guint8 *wfex_data = stsd_data + offset;
9725         const gchar *codec_name = NULL;
9726         gint version = 1;
9727         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9728         /* FIXME this should also be gst_riff_strf_auds,
9729          * but the latter one is actually missing bits-per-sample :( */
9730         typedef struct
9731         {
9732           gint16 wFormatTag;
9733           gint16 nChannels;
9734           gint32 nSamplesPerSec;
9735           gint32 nAvgBytesPerSec;
9736           gint16 nBlockAlign;
9737           gint16 wBitsPerSample;
9738           gint16 cbSize;
9739         } WAVEFORMATEX;
9740         WAVEFORMATEX wfex;
9741
9742         /* FIXME: unify with similar wavformatex parsing code above */
9743         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
9744
9745         /* find wfex */
9746         while (len >= 8) {
9747           gint size;
9748
9749           if (QT_UINT32 (wfex_data) <= len)
9750             size = QT_UINT32 (wfex_data) - 8;
9751           else
9752             size = len - 8;
9753
9754           if (size < 1)
9755             /* No real data, so break out */
9756             break;
9757
9758           switch (QT_FOURCC (wfex_data + 4)) {
9759             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
9760             {
9761               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
9762
9763               if (size < 8 + 18)
9764                 break;
9765
9766               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
9767               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
9768               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
9769               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
9770               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
9771               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
9772               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
9773
9774               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
9775               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
9776                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
9777                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
9778                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
9779                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
9780
9781               if (wfex.wFormatTag == 0x0161) {
9782                 codec_name = "Windows Media Audio";
9783                 version = 2;
9784               } else if (wfex.wFormatTag == 0x0162) {
9785                 codec_name = "Windows Media Audio 9 Pro";
9786                 version = 3;
9787               } else if (wfex.wFormatTag == 0x0163) {
9788                 codec_name = "Windows Media Audio 9 Lossless";
9789                 /* is that correct? gstffmpegcodecmap.c is missing it, but
9790                  * fluendo codec seems to support it */
9791                 version = 4;
9792               }
9793
9794               gst_caps_set_simple (stream->caps,
9795                   "wmaversion", G_TYPE_INT, version,
9796                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
9797                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
9798                   "width", G_TYPE_INT, wfex.wBitsPerSample,
9799                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
9800
9801               if (size > wfex.cbSize) {
9802                 GstBuffer *buf;
9803
9804                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
9805                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
9806                     size - wfex.cbSize);
9807                 gst_caps_set_simple (stream->caps,
9808                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9809                 gst_buffer_unref (buf);
9810               } else {
9811                 GST_WARNING_OBJECT (qtdemux, "no codec data");
9812               }
9813
9814               if (codec_name) {
9815                 g_free (codec);
9816                 codec = g_strdup (codec_name);
9817               }
9818               break;
9819             }
9820             default:
9821               break;
9822           }
9823           len -= size + 8;
9824           wfex_data += size + 8;
9825         }
9826         break;
9827       }
9828       default:
9829         break;
9830     }
9831
9832     if (codec) {
9833       GstStructure *s;
9834       gint bitrate = 0;
9835
9836       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9837           GST_TAG_AUDIO_CODEC, codec, NULL);
9838       g_free (codec);
9839       codec = NULL;
9840
9841       /* some bitrate info may have ended up in caps */
9842       s = gst_caps_get_structure (stream->caps, 0);
9843       gst_structure_get_int (s, "bitrate", &bitrate);
9844       if (bitrate > 0)
9845         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9846             GST_TAG_BITRATE, bitrate, NULL);
9847     }
9848
9849     if (stream->protected && fourcc == FOURCC_mp4a)
9850       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
9851     else
9852       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
9853
9854     wave = NULL;
9855     esds = NULL;
9856     if (mp4a) {
9857       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
9858       if (wave)
9859         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
9860       if (!esds)
9861         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
9862     }
9863
9864
9865     /* If the fourcc's bottom 16 bits gives 'sm', then the top
9866        16 bits is a byte-swapped wave-style codec identifier,
9867        and we can find a WAVE header internally to a 'wave' atom here.
9868        This can more clearly be thought of as 'ms' as the top 16 bits, and a
9869        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
9870        is big-endian).
9871      */
9872     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
9873       if (len < offset + 20) {
9874         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
9875       } else {
9876         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
9877         const guint8 *data = stsd_data + offset + 16;
9878         GNode *wavenode;
9879         GNode *waveheadernode;
9880
9881         wavenode = g_node_new ((guint8 *) data);
9882         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
9883           const guint8 *waveheader;
9884           guint32 headerlen;
9885
9886           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
9887           if (waveheadernode) {
9888             waveheader = (const guint8 *) waveheadernode->data;
9889             headerlen = QT_UINT32 (waveheader);
9890
9891             if (headerlen > 8) {
9892               gst_riff_strf_auds *header = NULL;
9893               GstBuffer *headerbuf;
9894               GstBuffer *extra;
9895
9896               waveheader += 8;
9897               headerlen -= 8;
9898
9899               headerbuf = gst_buffer_new_and_alloc (headerlen);
9900               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
9901
9902               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
9903                       headerbuf, &header, &extra)) {
9904                 gst_caps_unref (stream->caps);
9905                 /* FIXME: Need to do something with the channel reorder map */
9906                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
9907                     header, extra, NULL, NULL, NULL);
9908
9909                 if (extra)
9910                   gst_buffer_unref (extra);
9911                 g_free (header);
9912               }
9913             }
9914           } else
9915             GST_DEBUG ("Didn't find waveheadernode for this codec");
9916         }
9917         g_node_destroy (wavenode);
9918       }
9919     } else if (esds) {
9920       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9921     } else {
9922       switch (fourcc) {
9923 #if 0
9924           /* FIXME: what is in the chunk? */
9925         case FOURCC_QDMC:
9926         {
9927           gint len = QT_UINT32 (stsd_data);
9928
9929           /* seems to be always = 116 = 0x74 */
9930           break;
9931         }
9932 #endif
9933         case FOURCC_QDM2:
9934         {
9935           gint len = QT_UINT32 (stsd_data);
9936
9937           if (len > 0x4C) {
9938             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
9939
9940             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
9941             gst_caps_set_simple (stream->caps,
9942                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
9943             gst_buffer_unref (buf);
9944           }
9945           gst_caps_set_simple (stream->caps,
9946               "samplesize", G_TYPE_INT, samplesize, NULL);
9947           break;
9948         }
9949         case FOURCC_alac:
9950         {
9951           GNode *alac, *wave = NULL;
9952
9953           /* apparently, m4a has this atom appended directly in the stsd entry,
9954            * while mov has it in a wave atom */
9955           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
9956           if (alac) {
9957             /* alac now refers to stsd entry atom */
9958             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
9959             if (wave)
9960               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
9961             else
9962               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
9963           }
9964           if (alac) {
9965             const guint8 *alac_data = alac->data;
9966             gint len = QT_UINT32 (alac->data);
9967             GstBuffer *buf;
9968
9969             if (len < 36) {
9970               GST_DEBUG_OBJECT (qtdemux,
9971                   "discarding alac atom with unexpected len %d", len);
9972             } else {
9973               /* codec-data contains alac atom size and prefix,
9974                * ffmpeg likes it that way, not quite gst-ish though ...*/
9975               buf = gst_buffer_new_and_alloc (len);
9976               gst_buffer_fill (buf, 0, alac->data, len);
9977               gst_caps_set_simple (stream->caps,
9978                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9979               gst_buffer_unref (buf);
9980
9981               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
9982               stream->n_channels = QT_UINT8 (alac_data + 21);
9983               stream->rate = QT_UINT32 (alac_data + 32);
9984             }
9985           }
9986           gst_caps_set_simple (stream->caps,
9987               "samplesize", G_TYPE_INT, samplesize, NULL);
9988           break;
9989         }
9990         case FOURCC_sawb:
9991           /* Fallthrough! */
9992           amrwb = TRUE;
9993         case FOURCC_samr:
9994         {
9995           gint len = QT_UINT32 (stsd_data);
9996
9997           if (len > 0x34) {
9998             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
9999             guint bitrate;
10000
10001             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10002
10003             /* If we have enough data, let's try to get the 'damr' atom. See
10004              * the 3GPP container spec (26.244) for more details. */
10005             if ((len - 0x34) > 8 &&
10006                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10007               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10008                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10009             }
10010
10011             gst_caps_set_simple (stream->caps,
10012                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10013             gst_buffer_unref (buf);
10014           }
10015           break;
10016         }
10017         case FOURCC_mp4a:
10018         {
10019           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10020           gint len = QT_UINT32 (stsd_data);
10021
10022           if (len >= 50) {
10023             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10024
10025             if (sound_version == 1) {
10026               guint16 channels = QT_UINT16 (stsd_data + 40);
10027               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10028               guint8 codec_data[2];
10029               GstBuffer *buf;
10030               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10031
10032               gint sample_rate_index =
10033                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10034
10035               /* build AAC codec data */
10036               codec_data[0] = profile << 3;
10037               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10038               codec_data[1] = (sample_rate_index & 0x01) << 7;
10039               codec_data[1] |= (channels & 0xF) << 3;
10040
10041               buf = gst_buffer_new_and_alloc (2);
10042               gst_buffer_fill (buf, 0, codec_data, 2);
10043               gst_caps_set_simple (stream->caps,
10044                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10045               gst_buffer_unref (buf);
10046             }
10047           }
10048           break;
10049         }
10050         default:
10051           GST_INFO_OBJECT (qtdemux,
10052               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10053           break;
10054       }
10055     }
10056     GST_INFO_OBJECT (qtdemux,
10057         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10058         GST_FOURCC_ARGS (fourcc), stream->caps);
10059
10060   } else if (stream->subtype == FOURCC_strm) {
10061     if (fourcc == FOURCC_rtsp) {
10062       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10063     } else {
10064       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10065           GST_FOURCC_ARGS (fourcc));
10066       goto unknown_stream;
10067     }
10068     stream->sampled = TRUE;
10069   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10070       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10071
10072     stream->sampled = TRUE;
10073     stream->sparse = TRUE;
10074
10075     stream->caps =
10076         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10077     if (codec) {
10078       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10079           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10080       g_free (codec);
10081       codec = NULL;
10082     }
10083
10084     /* hunt for sort-of codec data */
10085     switch (fourcc) {
10086       case FOURCC_mp4s:
10087       {
10088         GNode *mp4s = NULL;
10089         GNode *esds = NULL;
10090
10091         /* look for palette in a stsd->mp4s->esds sub-atom */
10092         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10093         if (mp4s)
10094           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10095         if (esds == NULL) {
10096           /* Invalid STSD */
10097           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10098           break;
10099         }
10100
10101         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10102         break;
10103       }
10104       default:
10105         GST_INFO_OBJECT (qtdemux,
10106             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10107         break;
10108     }
10109     GST_INFO_OBJECT (qtdemux,
10110         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10111         GST_FOURCC_ARGS (fourcc), stream->caps);
10112   } else {
10113     /* everything in 1 sample */
10114     stream->sampled = TRUE;
10115
10116     stream->caps =
10117         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10118
10119     if (stream->caps == NULL)
10120       goto unknown_stream;
10121
10122     if (codec) {
10123       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10124           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10125       g_free (codec);
10126       codec = NULL;
10127     }
10128   }
10129
10130   /* promote to sampled format */
10131   if (stream->fourcc == FOURCC_samr) {
10132     /* force mono 8000 Hz for AMR */
10133     stream->sampled = TRUE;
10134     stream->n_channels = 1;
10135     stream->rate = 8000;
10136   } else if (stream->fourcc == FOURCC_sawb) {
10137     /* force mono 16000 Hz for AMR-WB */
10138     stream->sampled = TRUE;
10139     stream->n_channels = 1;
10140     stream->rate = 16000;
10141   } else if (stream->fourcc == FOURCC_mp4a) {
10142     stream->sampled = TRUE;
10143   }
10144
10145   /* collect sample information */
10146   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10147     goto samples_failed;
10148
10149   if (qtdemux->fragmented) {
10150     guint64 offset;
10151
10152     /* need all moov samples as basis; probably not many if any at all */
10153     /* prevent moof parsing taking of at this time */
10154     offset = qtdemux->moof_offset;
10155     qtdemux->moof_offset = 0;
10156     if (stream->n_samples &&
10157         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10158       qtdemux->moof_offset = offset;
10159       goto samples_failed;
10160     }
10161     qtdemux->moof_offset = 0;
10162     /* movie duration more reliable in this case (e.g. mehd) */
10163     if (qtdemux->segment.duration &&
10164         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10165       stream->duration =
10166           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10167   }
10168
10169   /* configure segments */
10170   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10171     goto segments_failed;
10172
10173   /* add some language tag, if useful */
10174   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10175       strcmp (stream->lang_id, "und")) {
10176     const gchar *lang_code;
10177
10178     /* convert ISO 639-2 code to ISO 639-1 */
10179     lang_code = gst_tag_get_language_code (stream->lang_id);
10180     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10181         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10182   }
10183
10184   /* Check for UDTA tags */
10185   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10186     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10187   }
10188
10189   /* now we are ready to add the stream */
10190   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10191     goto too_many_streams;
10192
10193   if (!qtdemux->got_moov) {
10194     qtdemux->streams[qtdemux->n_streams] = stream;
10195     qtdemux->n_streams++;
10196     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10197   }
10198
10199   return TRUE;
10200
10201 /* ERRORS */
10202 skip_track:
10203   {
10204     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10205     if (new_stream)
10206       gst_qtdemux_stream_free (qtdemux, stream);
10207     return TRUE;
10208   }
10209 corrupt_file:
10210   {
10211     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10212         (_("This file is corrupt and cannot be played.")), (NULL));
10213     if (new_stream)
10214       gst_qtdemux_stream_free (qtdemux, stream);
10215     return FALSE;
10216   }
10217 error_encrypted:
10218   {
10219     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10220     if (new_stream)
10221       gst_qtdemux_stream_free (qtdemux, stream);
10222     return FALSE;
10223   }
10224 samples_failed:
10225 segments_failed:
10226   {
10227     /* we posted an error already */
10228     /* free stbl sub-atoms */
10229     gst_qtdemux_stbl_free (stream);
10230     if (new_stream)
10231       gst_qtdemux_stream_free (qtdemux, stream);
10232     return FALSE;
10233   }
10234 existing_stream:
10235   {
10236     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10237         track_id);
10238     if (new_stream)
10239       gst_qtdemux_stream_free (qtdemux, stream);
10240     return TRUE;
10241   }
10242 unknown_stream:
10243   {
10244     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10245         GST_FOURCC_ARGS (stream->subtype));
10246     if (new_stream)
10247       gst_qtdemux_stream_free (qtdemux, stream);
10248     return TRUE;
10249   }
10250 too_many_streams:
10251   {
10252     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10253         (_("This file contains too many streams. Only playing first %d"),
10254             GST_QTDEMUX_MAX_STREAMS), (NULL));
10255     return TRUE;
10256   }
10257 }
10258
10259 /* If we can estimate the overall bitrate, and don't have information about the
10260  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10261  * the overall bitrate minus the sum of the bitrates of all other streams. This
10262  * should be useful for the common case where we have one audio and one video
10263  * stream and can estimate the bitrate of one, but not the other. */
10264 static void
10265 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10266 {
10267   QtDemuxStream *stream = NULL;
10268   gint64 size, sys_bitrate, sum_bitrate = 0;
10269   GstClockTime duration;
10270   gint i;
10271   guint bitrate;
10272
10273   if (qtdemux->fragmented)
10274     return;
10275
10276   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10277
10278   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10279       || size <= 0) {
10280     GST_DEBUG_OBJECT (qtdemux,
10281         "Size in bytes of the stream not known - bailing");
10282     return;
10283   }
10284
10285   /* Subtract the header size */
10286   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10287       size, qtdemux->header_size);
10288
10289   if (size < qtdemux->header_size)
10290     return;
10291
10292   size = size - qtdemux->header_size;
10293
10294   if (!gst_qtdemux_get_duration (qtdemux, &duration) ||
10295       duration == GST_CLOCK_TIME_NONE) {
10296     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10297     return;
10298   }
10299
10300   for (i = 0; i < qtdemux->n_streams; i++) {
10301     switch (qtdemux->streams[i]->subtype) {
10302       case FOURCC_soun:
10303       case FOURCC_vide:
10304         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10305             qtdemux->streams[i]->caps);
10306         /* retrieve bitrate, prefer avg then max */
10307         bitrate = 0;
10308         if (qtdemux->streams[i]->pending_tags) {
10309           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10310               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10311           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10312           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10313               GST_TAG_NOMINAL_BITRATE, &bitrate);
10314           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10315           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10316               GST_TAG_BITRATE, &bitrate);
10317           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10318         }
10319         if (bitrate)
10320           sum_bitrate += bitrate;
10321         else {
10322           if (stream) {
10323             GST_DEBUG_OBJECT (qtdemux,
10324                 ">1 stream with unknown bitrate - bailing");
10325             return;
10326           } else
10327             stream = qtdemux->streams[i];
10328         }
10329
10330       default:
10331         /* For other subtypes, we assume no significant impact on bitrate */
10332         break;
10333     }
10334   }
10335
10336   if (!stream) {
10337     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10338     return;
10339   }
10340
10341   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10342
10343   if (sys_bitrate < sum_bitrate) {
10344     /* This can happen, since sum_bitrate might be derived from maximum
10345      * bitrates and not average bitrates */
10346     GST_DEBUG_OBJECT (qtdemux,
10347         "System bitrate less than sum bitrate - bailing");
10348     return;
10349   }
10350
10351   bitrate = sys_bitrate - sum_bitrate;
10352   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10353       ", Stream bitrate = %u", sys_bitrate, bitrate);
10354
10355   if (!stream->pending_tags)
10356     stream->pending_tags = gst_tag_list_new_empty ();
10357
10358   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10359       GST_TAG_BITRATE, bitrate, NULL);
10360 }
10361
10362 static GstFlowReturn
10363 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10364 {
10365   gint i;
10366   GstFlowReturn ret = GST_FLOW_OK;
10367
10368   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10369
10370   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10371     QtDemuxStream *stream = qtdemux->streams[i];
10372     guint32 sample_num = 0;
10373
10374     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10375         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10376
10377     if (qtdemux->fragmented) {
10378       /* need all moov samples first */
10379       GST_OBJECT_LOCK (qtdemux);
10380       while (stream->n_samples == 0)
10381         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10382           break;
10383       GST_OBJECT_UNLOCK (qtdemux);
10384     } else {
10385       /* discard any stray moof */
10386       qtdemux->moof_offset = 0;
10387     }
10388
10389     /* prepare braking */
10390     if (ret != GST_FLOW_ERROR)
10391       ret = GST_FLOW_OK;
10392
10393     /* in pull mode, we should have parsed some sample info by now;
10394      * and quite some code will not handle no samples.
10395      * in push mode, we'll just have to deal with it */
10396     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10397       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10398       gst_qtdemux_remove_stream (qtdemux, i);
10399       i--;
10400       continue;
10401     }
10402
10403     /* parse the initial sample for use in setting the frame rate cap */
10404     while (sample_num == 0 && sample_num < stream->n_samples) {
10405       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10406         break;
10407       ++sample_num;
10408     }
10409     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
10410       stream->first_duration = stream->samples[0].duration;
10411       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
10412           stream->track_id, stream->first_duration);
10413     }
10414   }
10415
10416   return ret;
10417 }
10418
10419 static GstFlowReturn
10420 qtdemux_expose_streams (GstQTDemux * qtdemux)
10421 {
10422   gint i;
10423   GstFlowReturn ret = GST_FLOW_OK;
10424   GSList *oldpads = NULL;
10425   GSList *iter;
10426
10427   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
10428
10429   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10430     QtDemuxStream *stream = qtdemux->streams[i];
10431     GstPad *oldpad = stream->pad;
10432     GstTagList *list;
10433
10434     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10435         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10436
10437     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
10438         stream->track_id == qtdemux->chapters_track_id) {
10439       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
10440          so that it doesn't look like a subtitle track */
10441       gst_qtdemux_remove_stream (qtdemux, i);
10442       i--;
10443       continue;
10444     }
10445
10446     /* now we have all info and can expose */
10447     list = stream->pending_tags;
10448     stream->pending_tags = NULL;
10449     if (oldpad)
10450       oldpads = g_slist_prepend (oldpads, oldpad);
10451     gst_qtdemux_add_stream (qtdemux, stream, list);
10452   }
10453
10454   gst_qtdemux_guess_bitrate (qtdemux);
10455
10456   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
10457
10458   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
10459     GstPad *oldpad = iter->data;
10460
10461     gst_pad_push_event (oldpad, gst_event_new_eos ());
10462     gst_pad_set_active (oldpad, FALSE);
10463     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
10464     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
10465     gst_object_unref (oldpad);
10466   }
10467
10468   /* check if we should post a redirect in case there is a single trak
10469    * and it is a redirecting trak */
10470   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
10471     GstMessage *m;
10472
10473     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
10474         "an external content");
10475     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
10476         gst_structure_new ("redirect",
10477             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
10478             NULL));
10479     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
10480     qtdemux->posted_redirect = TRUE;
10481   }
10482
10483   for (i = 0; i < qtdemux->n_streams; i++) {
10484     QtDemuxStream *stream = qtdemux->streams[i];
10485
10486     qtdemux_do_allocation (qtdemux, stream);
10487   }
10488
10489   qtdemux->exposed = TRUE;
10490   return ret;
10491 }
10492
10493 /* check if major or compatible brand is 3GP */
10494 static inline gboolean
10495 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
10496 {
10497   if (major) {
10498     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10499         GST_MAKE_FOURCC ('3', 'g', 0, 0));
10500   } else if (qtdemux->comp_brands != NULL) {
10501     GstMapInfo map;
10502     guint8 *data;
10503     gsize size;
10504     gboolean res = FALSE;
10505
10506     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
10507     data = map.data;
10508     size = map.size;
10509     while (size >= 4) {
10510       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10511           GST_MAKE_FOURCC ('3', 'g', 0, 0));
10512       data += 4;
10513       size -= 4;
10514     }
10515     gst_buffer_unmap (qtdemux->comp_brands, &map);
10516     return res;
10517   } else {
10518     return FALSE;
10519   }
10520 }
10521
10522 /* check if tag is a spec'ed 3GP tag keyword storing a string */
10523 static inline gboolean
10524 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
10525 {
10526   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
10527       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
10528       || fourcc == FOURCC_albm;
10529 }
10530
10531 static void
10532 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
10533     const char *tag, const char *dummy, GNode * node)
10534 {
10535   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10536   int offset;
10537   char *name;
10538   gchar *data;
10539   gdouble longitude, latitude, altitude;
10540   gint len;
10541
10542   len = QT_UINT32 (node->data);
10543   if (len <= 14)
10544     goto short_read;
10545
10546   data = node->data;
10547   offset = 14;
10548
10549   /* TODO: language code skipped */
10550
10551   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
10552
10553   if (!name) {
10554     /* do not alarm in trivial case, but bail out otherwise */
10555     if (*(data + offset) != 0) {
10556       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
10557           "giving up", tag);
10558     }
10559   } else {
10560     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10561         GST_TAG_GEO_LOCATION_NAME, name, NULL);
10562     offset += strlen (name);
10563     g_free (name);
10564   }
10565
10566   if (len < offset + 2 + 4 + 4 + 4)
10567     goto short_read;
10568
10569   /* +1 +1 = skip null-terminator and location role byte */
10570   offset += 1 + 1;
10571   /* table in spec says unsigned, semantics say negative has meaning ... */
10572   longitude = QT_SFP32 (data + offset);
10573
10574   offset += 4;
10575   latitude = QT_SFP32 (data + offset);
10576
10577   offset += 4;
10578   altitude = QT_SFP32 (data + offset);
10579
10580   /* one invalid means all are invalid */
10581   if (longitude >= -180.0 && longitude <= 180.0 &&
10582       latitude >= -90.0 && latitude <= 90.0) {
10583     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10584         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
10585         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
10586         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
10587   }
10588
10589   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
10590
10591   return;
10592
10593   /* ERRORS */
10594 short_read:
10595   {
10596     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
10597     return;
10598   }
10599 }
10600
10601
10602 static void
10603 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
10604     const char *tag, const char *dummy, GNode * node)
10605 {
10606   guint16 y;
10607   GDate *date;
10608   gint len;
10609
10610   len = QT_UINT32 (node->data);
10611   if (len < 14)
10612     return;
10613
10614   y = QT_UINT16 ((guint8 *) node->data + 12);
10615   if (y == 0) {
10616     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
10617     return;
10618   }
10619   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
10620
10621   date = g_date_new_dmy (1, 1, y);
10622   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
10623   g_date_free (date);
10624 }
10625
10626 static void
10627 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
10628     const char *tag, const char *dummy, GNode * node)
10629 {
10630   int offset;
10631   char *tag_str = NULL;
10632   guint8 *entity;
10633   guint16 table;
10634   gint len;
10635
10636   len = QT_UINT32 (node->data);
10637   if (len <= 20)
10638     goto short_read;
10639
10640   offset = 12;
10641   entity = (guint8 *) node->data + offset;
10642   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
10643     GST_DEBUG_OBJECT (qtdemux,
10644         "classification info: %c%c%c%c invalid classification entity",
10645         entity[0], entity[1], entity[2], entity[3]);
10646     return;
10647   }
10648
10649   offset += 4;
10650   table = QT_UINT16 ((guint8 *) node->data + offset);
10651
10652   /* Language code skipped */
10653
10654   offset += 4;
10655
10656   /* Tag format: "XXXX://Y[YYYY]/classification info string"
10657    * XXXX: classification entity, fixed length 4 chars.
10658    * Y[YYYY]: classification table, max 5 chars.
10659    */
10660   tag_str = g_strdup_printf ("----://%u/%s",
10661       table, (char *) node->data + offset);
10662
10663   /* memcpy To be sure we're preserving byte order */
10664   memcpy (tag_str, entity, 4);
10665   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
10666
10667   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
10668
10669   g_free (tag_str);
10670
10671   return;
10672
10673   /* ERRORS */
10674 short_read:
10675   {
10676     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
10677     return;
10678   }
10679 }
10680
10681 static gboolean
10682 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
10683     const char *tag, const char *dummy, GNode * node)
10684 {
10685   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10686   GNode *data;
10687   char *s;
10688   int len;
10689   guint32 type;
10690   int offset;
10691   gboolean ret = TRUE;
10692   const gchar *charset = NULL;
10693
10694   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10695   if (data) {
10696     len = QT_UINT32 (data->data);
10697     type = QT_UINT32 ((guint8 *) data->data + 8);
10698     if (type == 0x00000001 && len > 16) {
10699       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
10700           env_vars);
10701       if (s) {
10702         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10703         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10704         g_free (s);
10705       } else {
10706         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10707       }
10708     }
10709   } else {
10710     len = QT_UINT32 (node->data);
10711     type = QT_UINT32 ((guint8 *) node->data + 4);
10712     if ((type >> 24) == 0xa9) {
10713       gint str_len;
10714       gint lang_code;
10715
10716       /* Type starts with the (C) symbol, so the next data is a list
10717        * of (string size(16), language code(16), string) */
10718
10719       str_len = QT_UINT16 ((guint8 *) node->data + 8);
10720       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
10721
10722       /* the string + fourcc + size + 2 16bit fields,
10723        * means that there are more tags in this atom */
10724       if (len > str_len + 8 + 4) {
10725         /* TODO how to represent the same tag in different languages? */
10726         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
10727             "text alternatives, reading only first one");
10728       }
10729
10730       offset = 12;
10731       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
10732       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
10733
10734       if (lang_code < 0x800) {  /* MAC encoded string */
10735         charset = "mac";
10736       }
10737     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
10738             QT_FOURCC ((guint8 *) node->data + 4))) {
10739       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
10740
10741       /* we go for 3GP style encoding if major brands claims so,
10742        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
10743       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
10744           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
10745               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
10746         offset = 14;
10747         /* 16-bit Language code is ignored here as well */
10748         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
10749       } else {
10750         goto normal;
10751       }
10752     } else {
10753     normal:
10754       offset = 8;
10755       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
10756       ret = FALSE;              /* may have to fallback */
10757     }
10758     if (charset) {
10759       GError *err = NULL;
10760
10761       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
10762           charset, NULL, NULL, &err);
10763       if (err) {
10764         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
10765             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
10766             err->message);
10767         g_error_free (err);
10768       }
10769     } else {
10770       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10771           len - offset, env_vars);
10772     }
10773     if (s) {
10774       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10775       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10776       g_free (s);
10777       ret = TRUE;
10778     } else {
10779       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10780     }
10781   }
10782   return ret;
10783 }
10784
10785 static void
10786 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
10787     const char *tag, const char *dummy, GNode * node)
10788 {
10789   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
10790 }
10791
10792 static void
10793 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
10794     const char *tag, const char *dummy, GNode * node)
10795 {
10796   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10797   guint8 *data;
10798   char *s, *t, *k = NULL;
10799   int len;
10800   int offset;
10801   int count;
10802
10803   /* first try normal string tag if major brand not 3GP */
10804   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
10805     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
10806       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
10807        * let's try it 3gpp way after minor safety check */
10808       data = node->data;
10809       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
10810         return;
10811     } else
10812       return;
10813   }
10814
10815   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
10816
10817   data = node->data;
10818
10819   len = QT_UINT32 (data);
10820   if (len < 15)
10821     goto short_read;
10822
10823   count = QT_UINT8 (data + 14);
10824   offset = 15;
10825   for (; count; count--) {
10826     gint slen;
10827
10828     if (offset + 1 > len)
10829       goto short_read;
10830     slen = QT_UINT8 (data + offset);
10831     offset += 1;
10832     if (offset + slen > len)
10833       goto short_read;
10834     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10835         slen, env_vars);
10836     if (s) {
10837       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
10838       if (k) {
10839         t = g_strjoin (",", k, s, NULL);
10840         g_free (s);
10841         g_free (k);
10842         k = t;
10843       } else {
10844         k = s;
10845       }
10846     } else {
10847       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
10848     }
10849     offset += slen;
10850   }
10851
10852 done:
10853   if (k) {
10854     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
10855     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
10856   }
10857   g_free (k);
10858
10859   return;
10860
10861   /* ERRORS */
10862 short_read:
10863   {
10864     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
10865     goto done;
10866   }
10867 }
10868
10869 static void
10870 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
10871     const char *tag1, const char *tag2, GNode * node)
10872 {
10873   GNode *data;
10874   int len;
10875   int type;
10876   int n1, n2;
10877
10878   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10879   if (data) {
10880     len = QT_UINT32 (data->data);
10881     type = QT_UINT32 ((guint8 *) data->data + 8);
10882     if (type == 0x00000000 && len >= 22) {
10883       n1 = QT_UINT16 ((guint8 *) data->data + 18);
10884       n2 = QT_UINT16 ((guint8 *) data->data + 20);
10885       if (n1 > 0) {
10886         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
10887         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
10888       }
10889       if (n2 > 0) {
10890         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
10891         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
10892       }
10893     }
10894   }
10895 }
10896
10897 static void
10898 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
10899     const char *tag1, const char *dummy, GNode * node)
10900 {
10901   GNode *data;
10902   int len;
10903   int type;
10904   int n1;
10905
10906   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10907   if (data) {
10908     len = QT_UINT32 (data->data);
10909     type = QT_UINT32 ((guint8 *) data->data + 8);
10910     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
10911     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
10912     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
10913       n1 = QT_UINT16 ((guint8 *) data->data + 16);
10914       if (n1) {
10915         /* do not add bpm=0 */
10916         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
10917         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
10918             NULL);
10919       }
10920     }
10921   }
10922 }
10923
10924 static void
10925 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
10926     const char *tag1, const char *dummy, GNode * node)
10927 {
10928   GNode *data;
10929   int len;
10930   int type;
10931   guint32 num;
10932
10933   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10934   if (data) {
10935     len = QT_UINT32 (data->data);
10936     type = QT_UINT32 ((guint8 *) data->data + 8);
10937     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
10938     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
10939     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
10940       num = QT_UINT32 ((guint8 *) data->data + 16);
10941       if (num) {
10942         /* do not add num=0 */
10943         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
10944         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
10945       }
10946     }
10947   }
10948 }
10949
10950 static void
10951 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
10952     const char *tag1, const char *dummy, GNode * node)
10953 {
10954   GNode *data;
10955   int len;
10956   int type;
10957   GstSample *sample;
10958
10959   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10960   if (data) {
10961     len = QT_UINT32 (data->data);
10962     type = QT_UINT32 ((guint8 *) data->data + 8);
10963     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
10964     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
10965       if ((sample =
10966               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
10967                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
10968         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
10969         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
10970         gst_sample_unref (sample);
10971       }
10972     }
10973   }
10974 }
10975
10976 static void
10977 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
10978     const char *tag, const char *dummy, GNode * node)
10979 {
10980   GNode *data;
10981   char *s;
10982   int len;
10983   int type;
10984
10985   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10986   if (data) {
10987     len = QT_UINT32 (data->data);
10988     type = QT_UINT32 ((guint8 *) data->data + 8);
10989     if (type == 0x00000001 && len > 16) {
10990       guint y, m = 1, d = 1;
10991       gint ret;
10992
10993       s = g_strndup ((char *) data->data + 16, len - 16);
10994       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
10995       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
10996       if (ret >= 1 && y > 1500 && y < 3000) {
10997         GDate *date;
10998
10999         date = g_date_new_dmy (d, m, y);
11000         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11001         g_date_free (date);
11002       } else {
11003         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11004       }
11005       g_free (s);
11006     }
11007   }
11008 }
11009
11010 static void
11011 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11012     const char *tag, const char *dummy, GNode * node)
11013 {
11014   GNode *data;
11015
11016   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11017
11018   /* re-route to normal string tag if major brand says so
11019    * or no data atom and compatible brand suggests so */
11020   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11021       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11022     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11023     return;
11024   }
11025
11026   if (data) {
11027     guint len, type, n;
11028
11029     len = QT_UINT32 (data->data);
11030     type = QT_UINT32 ((guint8 *) data->data + 8);
11031     if (type == 0x00000000 && len >= 18) {
11032       n = QT_UINT16 ((guint8 *) data->data + 16);
11033       if (n > 0) {
11034         const gchar *genre;
11035
11036         genre = gst_tag_id3_genre_get (n - 1);
11037         if (genre != NULL) {
11038           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11039           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11040         }
11041       }
11042     }
11043   }
11044 }
11045
11046 static void
11047 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11048     const gchar * tag, guint8 * data, guint32 datasize)
11049 {
11050   gdouble value;
11051   gchar *datacopy;
11052
11053   /* make a copy to have \0 at the end */
11054   datacopy = g_strndup ((gchar *) data, datasize);
11055
11056   /* convert the str to double */
11057   if (sscanf (datacopy, "%lf", &value) == 1) {
11058     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11059     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11060   } else {
11061     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11062         datacopy);
11063   }
11064   g_free (datacopy);
11065 }
11066
11067
11068 static void
11069 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11070     const char *tag, const char *tag_bis, GNode * node)
11071 {
11072   GNode *mean;
11073   GNode *name;
11074   GNode *data;
11075   guint32 meansize;
11076   guint32 namesize;
11077   guint32 datatype;
11078   guint32 datasize;
11079   const gchar *meanstr;
11080   const gchar *namestr;
11081
11082   /* checking the whole ---- atom size for consistency */
11083   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11084     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11085     return;
11086   }
11087
11088   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11089   if (!mean) {
11090     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11091     return;
11092   }
11093
11094   meansize = QT_UINT32 (mean->data);
11095   if (meansize <= 12) {
11096     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11097     return;
11098   }
11099   meanstr = ((gchar *) mean->data) + 12;
11100   meansize -= 12;
11101
11102   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11103   if (!name) {
11104     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11105     return;
11106   }
11107
11108   namesize = QT_UINT32 (name->data);
11109   if (namesize <= 12) {
11110     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11111     return;
11112   }
11113   namestr = ((gchar *) name->data) + 12;
11114   namesize -= 12;
11115
11116   /*
11117    * Data atom is:
11118    * uint32 - size
11119    * uint32 - name
11120    * uint8  - version
11121    * uint24 - data type
11122    * uint32 - all 0
11123    * rest   - the data
11124    */
11125   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11126   if (!data) {
11127     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11128     return;
11129   }
11130   datasize = QT_UINT32 (data->data);
11131   if (datasize <= 16) {
11132     GST_WARNING_OBJECT (demux, "Data atom too small");
11133     return;
11134   }
11135   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11136
11137   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11138       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11139     static const struct
11140     {
11141       const gchar name[28];
11142       const gchar tag[28];
11143     } tags[] = {
11144       {
11145       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11146       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11147       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11148       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11149       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11150       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11151       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11152       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11153     };
11154     int i;
11155
11156     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11157       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11158         switch (gst_tag_get_type (tags[i].tag)) {
11159           case G_TYPE_DOUBLE:
11160             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11161                 ((guint8 *) data->data) + 16, datasize - 16);
11162             break;
11163           case G_TYPE_STRING:
11164             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11165             break;
11166           default:
11167             /* not reached */
11168             break;
11169         }
11170         break;
11171       }
11172     }
11173     if (i == G_N_ELEMENTS (tags))
11174       goto unknown_tag;
11175   } else {
11176     goto unknown_tag;
11177   }
11178
11179   return;
11180
11181 /* errors */
11182 unknown_tag:
11183 #ifndef GST_DISABLE_GST_DEBUG
11184   {
11185     gchar *namestr_dbg;
11186     gchar *meanstr_dbg;
11187
11188     meanstr_dbg = g_strndup (meanstr, meansize);
11189     namestr_dbg = g_strndup (namestr, namesize);
11190
11191     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11192         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11193
11194     g_free (namestr_dbg);
11195     g_free (meanstr_dbg);
11196   }
11197 #endif
11198   return;
11199 }
11200
11201 static void
11202 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11203     const char *tag_bis, GNode * node)
11204 {
11205   guint8 *data;
11206   GstBuffer *buf;
11207   guint len;
11208   GstTagList *id32_taglist = NULL;
11209
11210   GST_LOG_OBJECT (demux, "parsing ID32");
11211
11212   data = node->data;
11213   len = GST_READ_UINT32_BE (data);
11214
11215   /* need at least full box and language tag */
11216   if (len < 12 + 2)
11217     return;
11218
11219   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11220   gst_buffer_fill (buf, 0, data + 14, len - 14);
11221
11222   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11223   if (id32_taglist) {
11224     GST_LOG_OBJECT (demux, "parsing ok");
11225     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11226     gst_tag_list_unref (id32_taglist);
11227   } else {
11228     GST_LOG_OBJECT (demux, "parsing failed");
11229   }
11230
11231   gst_buffer_unref (buf);
11232 }
11233
11234 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11235     const char *tag, const char *tag_bis, GNode * node);
11236
11237 /* unmapped tags
11238 FOURCC_pcst -> if media is a podcast -> bool
11239 FOURCC_cpil -> if media is part of a compilation -> bool
11240 FOURCC_pgap -> if media is part of a gapless context -> bool
11241 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11242 */
11243
11244 static const struct
11245 {
11246   guint32 fourcc;
11247   const gchar *gst_tag;
11248   const gchar *gst_tag_bis;
11249   const GstQTDemuxAddTagFunc func;
11250 } add_funcs[] = {
11251   {
11252   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11253   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11254   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11255   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11256   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11257   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11258   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11259   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11260   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11261   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11262   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11263   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11264   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11265   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11266   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11267   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11268   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11269   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11270   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11271   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11272   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11273   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11274   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11275         qtdemux_tag_add_num}, {
11276   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11277         qtdemux_tag_add_num}, {
11278   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11279   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11280   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11281   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11282   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11283   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11284   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11285   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11286   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11287   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11288   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11289   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11290   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11291   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11292   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11293   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11294   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11295   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11296         qtdemux_tag_add_classification}, {
11297   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11298   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11299   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11300
11301     /* This is a special case, some tags are stored in this
11302      * 'reverse dns naming', according to:
11303      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11304      * bug #614471
11305      */
11306   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11307     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11308   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11309 };
11310
11311 struct _GstQtDemuxTagList
11312 {
11313   GstQTDemux *demux;
11314   GstTagList *taglist;
11315 };
11316 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11317
11318 static void
11319 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11320 {
11321   gint len;
11322   guint8 *data;
11323   GstBuffer *buf;
11324   gchar *media_type;
11325   const gchar *style;
11326   GstSample *sample;
11327   GstStructure *s;
11328   guint i;
11329   guint8 ndata[4];
11330   GstQTDemux *demux = qtdemuxtaglist->demux;
11331   GstTagList *taglist = qtdemuxtaglist->taglist;
11332
11333   data = node->data;
11334   len = QT_UINT32 (data);
11335   buf = gst_buffer_new_and_alloc (len);
11336   gst_buffer_fill (buf, 0, data, len);
11337
11338   /* heuristic to determine style of tag */
11339   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11340       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11341     style = "itunes";
11342   else if (demux->major_brand == FOURCC_qt__)
11343     style = "quicktime";
11344   /* fall back to assuming iso/3gp tag style */
11345   else
11346     style = "iso";
11347
11348   /* santize the name for the caps. */
11349   for (i = 0; i < 4; i++) {
11350     guint8 d = data[4 + i];
11351     if (g_ascii_isalnum (d))
11352       ndata[i] = g_ascii_tolower (d);
11353     else
11354       ndata[i] = '_';
11355   }
11356
11357   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11358       ndata[0], ndata[1], ndata[2], ndata[3]);
11359   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11360
11361   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11362   sample = gst_sample_new (buf, NULL, NULL, s);
11363   gst_buffer_unref (buf);
11364   g_free (media_type);
11365
11366   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11367       len, s);
11368
11369   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11370       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11371
11372   gst_sample_unref (sample);
11373 }
11374
11375 static void
11376 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11377 {
11378   GNode *meta;
11379   GNode *ilst;
11380   GNode *xmp_;
11381   GNode *node;
11382   gint i;
11383   GstQtDemuxTagList demuxtaglist;
11384
11385   demuxtaglist.demux = qtdemux;
11386   demuxtaglist.taglist = taglist;
11387
11388   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11389   if (meta != NULL) {
11390     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11391     if (ilst == NULL) {
11392       GST_LOG_OBJECT (qtdemux, "no ilst");
11393       return;
11394     }
11395   } else {
11396     ilst = udta;
11397     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11398   }
11399
11400   i = 0;
11401   while (i < G_N_ELEMENTS (add_funcs)) {
11402     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
11403     if (node) {
11404       gint len;
11405
11406       len = QT_UINT32 (node->data);
11407       if (len < 12) {
11408         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
11409             GST_FOURCC_ARGS (add_funcs[i].fourcc));
11410       } else {
11411         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
11412             add_funcs[i].gst_tag_bis, node);
11413       }
11414       g_node_destroy (node);
11415     } else {
11416       i++;
11417     }
11418   }
11419
11420   /* parsed nodes have been removed, pass along remainder as blob */
11421   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
11422       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
11423
11424   /* parse up XMP_ node if existing */
11425   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
11426   if (xmp_ != NULL) {
11427     GstBuffer *buf;
11428     GstTagList *xmptaglist;
11429
11430     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
11431         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
11432     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
11433     gst_buffer_unref (buf);
11434
11435     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
11436   } else {
11437     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
11438   }
11439 }
11440
11441 typedef struct
11442 {
11443   GstStructure *structure;      /* helper for sort function */
11444   gchar *location;
11445   guint min_req_bitrate;
11446   guint min_req_qt_version;
11447 } GstQtReference;
11448
11449 static gint
11450 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
11451 {
11452   GstQtReference *ref_a = (GstQtReference *) a;
11453   GstQtReference *ref_b = (GstQtReference *) b;
11454
11455   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
11456     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
11457
11458   /* known bitrates go before unknown; higher bitrates go first */
11459   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
11460 }
11461
11462 /* sort the redirects and post a message for the application.
11463  */
11464 static void
11465 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
11466 {
11467   GstQtReference *best;
11468   GstStructure *s;
11469   GstMessage *msg;
11470   GValue list_val = { 0, };
11471   GList *l;
11472
11473   g_assert (references != NULL);
11474
11475   references = g_list_sort (references, qtdemux_redirects_sort_func);
11476
11477   best = (GstQtReference *) references->data;
11478
11479   g_value_init (&list_val, GST_TYPE_LIST);
11480
11481   for (l = references; l != NULL; l = l->next) {
11482     GstQtReference *ref = (GstQtReference *) l->data;
11483     GValue struct_val = { 0, };
11484
11485     ref->structure = gst_structure_new ("redirect",
11486         "new-location", G_TYPE_STRING, ref->location, NULL);
11487
11488     if (ref->min_req_bitrate > 0) {
11489       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
11490           ref->min_req_bitrate, NULL);
11491     }
11492
11493     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
11494     g_value_set_boxed (&struct_val, ref->structure);
11495     gst_value_list_append_value (&list_val, &struct_val);
11496     g_value_unset (&struct_val);
11497     /* don't free anything here yet, since we need best->structure below */
11498   }
11499
11500   g_assert (best != NULL);
11501   s = gst_structure_copy (best->structure);
11502
11503   if (g_list_length (references) > 1) {
11504     gst_structure_set_value (s, "locations", &list_val);
11505   }
11506
11507   g_value_unset (&list_val);
11508
11509   for (l = references; l != NULL; l = l->next) {
11510     GstQtReference *ref = (GstQtReference *) l->data;
11511
11512     gst_structure_free (ref->structure);
11513     g_free (ref->location);
11514     g_free (ref);
11515   }
11516   g_list_free (references);
11517
11518   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
11519   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
11520   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
11521   qtdemux->posted_redirect = TRUE;
11522 }
11523
11524 /* look for redirect nodes, collect all redirect information and
11525  * process it.
11526  */
11527 static gboolean
11528 qtdemux_parse_redirects (GstQTDemux * qtdemux)
11529 {
11530   GNode *rmra, *rmda, *rdrf;
11531
11532   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
11533   if (rmra) {
11534     GList *redirects = NULL;
11535
11536     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
11537     while (rmda) {
11538       GstQtReference ref = { NULL, NULL, 0, 0 };
11539       GNode *rmdr, *rmvc;
11540
11541       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
11542         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
11543         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
11544             ref.min_req_bitrate);
11545       }
11546
11547       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
11548         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
11549         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
11550
11551 #ifndef GST_DISABLE_GST_DEBUG
11552         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
11553 #endif
11554         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
11555
11556         GST_LOG_OBJECT (qtdemux,
11557             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
11558             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
11559             bitmask, check_type);
11560         if (package == FOURCC_qtim && check_type == 0) {
11561           ref.min_req_qt_version = version;
11562         }
11563       }
11564
11565       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
11566       if (rdrf) {
11567         guint32 ref_type;
11568         guint8 *ref_data;
11569         guint ref_len;
11570
11571         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
11572         if (ref_len > 20) {
11573           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
11574           ref_data = (guint8 *) rdrf->data + 20;
11575           if (ref_type == FOURCC_alis) {
11576             guint record_len, record_version, fn_len;
11577
11578             if (ref_len > 70) {
11579               /* MacOSX alias record, google for alias-layout.txt */
11580               record_len = QT_UINT16 (ref_data + 4);
11581               record_version = QT_UINT16 (ref_data + 4 + 2);
11582               fn_len = QT_UINT8 (ref_data + 50);
11583               if (record_len > 50 && record_version == 2 && fn_len > 0) {
11584                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
11585               }
11586             } else {
11587               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
11588                   ref_len);
11589             }
11590           } else if (ref_type == FOURCC_url_) {
11591             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
11592           } else {
11593             GST_DEBUG_OBJECT (qtdemux,
11594                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
11595                 GST_FOURCC_ARGS (ref_type));
11596           }
11597           if (ref.location != NULL) {
11598             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
11599             redirects =
11600                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
11601           } else {
11602             GST_WARNING_OBJECT (qtdemux,
11603                 "Failed to extract redirect location from rdrf atom");
11604           }
11605         } else {
11606           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
11607         }
11608       }
11609
11610       /* look for others */
11611       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
11612     }
11613
11614     if (redirects != NULL) {
11615       qtdemux_process_redirects (qtdemux, redirects);
11616     }
11617   }
11618   return TRUE;
11619 }
11620
11621 static GstTagList *
11622 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
11623 {
11624   const gchar *fmt;
11625
11626   if (tags == NULL) {
11627     tags = gst_tag_list_new_empty ();
11628     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
11629   }
11630
11631   if (qtdemux->major_brand == FOURCC_mjp2)
11632     fmt = "Motion JPEG 2000";
11633   else if ((qtdemux->major_brand & 0xffff) == GST_MAKE_FOURCC ('3', 'g', 0, 0))
11634     fmt = "3GP";
11635   else if (qtdemux->major_brand == FOURCC_qt__)
11636     fmt = "Quicktime";
11637   else if (qtdemux->fragmented)
11638     fmt = "ISO fMP4";
11639   else
11640     fmt = "ISO MP4/M4A";
11641
11642   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
11643       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
11644
11645   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
11646       fmt, NULL);
11647
11648   return tags;
11649 }
11650
11651 /* we have read th complete moov node now.
11652  * This function parses all of the relevant info, creates the traks and
11653  * prepares all data structures for playback
11654  */
11655 static gboolean
11656 qtdemux_parse_tree (GstQTDemux * qtdemux)
11657 {
11658   GNode *mvhd;
11659   GNode *trak;
11660   GNode *udta;
11661   GNode *mvex;
11662   GstClockTime duration;
11663   GNode *pssh;
11664   guint64 creation_time;
11665   GstDateTime *datetime = NULL;
11666   gint version;
11667
11668   /* make sure we have a usable taglist */
11669   if (!qtdemux->tag_list) {
11670     qtdemux->tag_list = gst_tag_list_new_empty ();
11671     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11672   } else {
11673     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11674   }
11675
11676   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
11677   if (mvhd == NULL) {
11678     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
11679     return qtdemux_parse_redirects (qtdemux);
11680   }
11681
11682   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
11683   if (version == 1) {
11684     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
11685     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
11686     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
11687   } else if (version == 0) {
11688     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
11689     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
11690     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
11691   } else {
11692     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
11693     return FALSE;
11694   }
11695
11696   /* Moving qt creation time (secs since 1904) to unix time */
11697   if (creation_time != 0) {
11698     /* Try to use epoch first as it should be faster and more commonly found */
11699     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
11700       GTimeVal now;
11701
11702       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
11703       /* some data cleansing sanity */
11704       g_get_current_time (&now);
11705       if (now.tv_sec + 24 * 3600 < creation_time) {
11706         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
11707       } else {
11708         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
11709       }
11710     } else {
11711       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
11712       GDateTime *dt, *dt_local;
11713
11714       dt = g_date_time_add_seconds (base_dt, creation_time);
11715       dt_local = g_date_time_to_local (dt);
11716       datetime = gst_date_time_new_from_g_date_time (dt_local);
11717
11718       g_date_time_unref (base_dt);
11719       g_date_time_unref (dt);
11720     }
11721   }
11722   if (datetime) {
11723     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
11724     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
11725         datetime, NULL);
11726     gst_date_time_unref (datetime);
11727   }
11728
11729   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
11730   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
11731
11732   /* check for fragmented file and get some (default) data */
11733   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
11734   if (mvex) {
11735     GNode *mehd;
11736     GstByteReader mehd_data;
11737
11738     /* let track parsing or anyone know weird stuff might happen ... */
11739     qtdemux->fragmented = TRUE;
11740
11741     /* compensate for total duration */
11742     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
11743     if (mehd)
11744       qtdemux_parse_mehd (qtdemux, &mehd_data);
11745   }
11746
11747   /* set duration in the segment info */
11748   gst_qtdemux_get_duration (qtdemux, &duration);
11749   if (duration) {
11750     qtdemux->segment.duration = duration;
11751     /* also do not exceed duration; stop is set that way post seek anyway,
11752      * and segment activation falls back to duration,
11753      * whereas loop only checks stop, so let's align this here as well */
11754     qtdemux->segment.stop = duration;
11755   }
11756
11757   /* parse all traks */
11758   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
11759   while (trak) {
11760     qtdemux_parse_trak (qtdemux, trak);
11761     /* iterate all siblings */
11762     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
11763   }
11764
11765   if (!qtdemux->tag_list) {
11766     GST_DEBUG_OBJECT (qtdemux, "new tag list");
11767     qtdemux->tag_list = gst_tag_list_new_empty ();
11768     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11769   } else {
11770     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11771   }
11772
11773   /* find tags */
11774   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
11775   if (udta) {
11776     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11777   } else {
11778     GST_LOG_OBJECT (qtdemux, "No udta node found.");
11779   }
11780
11781   /* maybe also some tags in meta box */
11782   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
11783   if (udta) {
11784     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
11785     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11786   } else {
11787     GST_LOG_OBJECT (qtdemux, "No meta node found.");
11788   }
11789
11790   /* parse any protection system info */
11791   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
11792   while (pssh) {
11793     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
11794     qtdemux_parse_pssh (qtdemux, pssh);
11795     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
11796   }
11797
11798   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
11799
11800   return TRUE;
11801 }
11802
11803 /* taken from ffmpeg */
11804 static int
11805 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
11806 {
11807   int count = 4;
11808   int len = 0;
11809
11810   while (count--) {
11811     int c;
11812
11813     if (ptr >= end)
11814       return -1;
11815
11816     c = *ptr++;
11817     len = (len << 7) | (c & 0x7f);
11818     if (!(c & 0x80))
11819       break;
11820   }
11821   *end_out = ptr;
11822   return len;
11823 }
11824
11825 /* this can change the codec originally present in @list */
11826 static void
11827 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
11828     GNode * esds, GstTagList * list)
11829 {
11830   int len = QT_UINT32 (esds->data);
11831   guint8 *ptr = esds->data;
11832   guint8 *end = ptr + len;
11833   int tag;
11834   guint8 *data_ptr = NULL;
11835   int data_len = 0;
11836   guint8 object_type_id = 0;
11837   const char *codec_name = NULL;
11838   GstCaps *caps = NULL;
11839
11840   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
11841   ptr += 8;
11842   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
11843   ptr += 4;
11844   while (ptr + 1 < end) {
11845     tag = QT_UINT8 (ptr);
11846     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
11847     ptr++;
11848     len = read_descr_size (ptr, end, &ptr);
11849     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
11850
11851     /* Check the stated amount of data is available for reading */
11852     if (len < 0 || ptr + len > end)
11853       break;
11854
11855     switch (tag) {
11856       case ES_DESCRIPTOR_TAG:
11857         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
11858         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
11859         ptr += 3;
11860         break;
11861       case DECODER_CONFIG_DESC_TAG:{
11862         guint max_bitrate, avg_bitrate;
11863
11864         object_type_id = QT_UINT8 (ptr);
11865         max_bitrate = QT_UINT32 (ptr + 5);
11866         avg_bitrate = QT_UINT32 (ptr + 9);
11867         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
11868         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
11869         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
11870         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
11871         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
11872         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11873           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
11874               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
11875         }
11876         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11877           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
11878               avg_bitrate, NULL);
11879         }
11880         ptr += 13;
11881         break;
11882       }
11883       case DECODER_SPECIFIC_INFO_TAG:
11884         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
11885         if (object_type_id == 0xe0 && len == 0x40) {
11886           guint8 *data;
11887           GstStructure *s;
11888           guint32 clut[16];
11889           gint i;
11890
11891           GST_DEBUG_OBJECT (qtdemux,
11892               "Have VOBSUB palette. Creating palette event");
11893           /* move to decConfigDescr data and read palette */
11894           data = ptr;
11895           for (i = 0; i < 16; i++) {
11896             clut[i] = QT_UINT32 (data);
11897             data += 4;
11898           }
11899
11900           s = gst_structure_new ("application/x-gst-dvd", "event",
11901               G_TYPE_STRING, "dvd-spu-clut-change",
11902               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
11903               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
11904               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
11905               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
11906               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
11907               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
11908               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
11909               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
11910               NULL);
11911
11912           /* store event and trigger custom processing */
11913           stream->pending_event =
11914               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
11915         } else {
11916           /* Generic codec_data handler puts it on the caps */
11917           data_ptr = ptr;
11918           data_len = len;
11919         }
11920
11921         ptr += len;
11922         break;
11923       case SL_CONFIG_DESC_TAG:
11924         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
11925         ptr += 1;
11926         break;
11927       default:
11928         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
11929             tag);
11930         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
11931         ptr += len;
11932         break;
11933     }
11934   }
11935
11936   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
11937    * in use, and should also be used to override some other parameters for some
11938    * codecs. */
11939   switch (object_type_id) {
11940     case 0x20:                 /* MPEG-4 */
11941       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
11942        * profile_and_level_indication */
11943       if (data_ptr != NULL && data_len >= 5 &&
11944           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
11945         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
11946             data_ptr + 4, data_len - 4);
11947       }
11948       break;                    /* Nothing special needed here */
11949     case 0x21:                 /* H.264 */
11950       codec_name = "H.264 / AVC";
11951       caps = gst_caps_new_simple ("video/x-h264",
11952           "stream-format", G_TYPE_STRING, "avc",
11953           "alignment", G_TYPE_STRING, "au", NULL);
11954       break;
11955     case 0x40:                 /* AAC (any) */
11956     case 0x66:                 /* AAC Main */
11957     case 0x67:                 /* AAC LC */
11958     case 0x68:                 /* AAC SSR */
11959       /* Override channels and rate based on the codec_data, as it's often
11960        * wrong. */
11961       /* Only do so for basic setup without HE-AAC extension */
11962       if (data_ptr && data_len == 2) {
11963         guint channels, rateindex, rate;
11964
11965         /* FIXME: add gst_codec_utils_aac_get_{channels|sample_rate}()? */
11966         channels = (data_ptr[1] & 0x7f) >> 3;
11967         if (channels > 0 && channels < 7) {
11968           stream->n_channels = channels;
11969         } else if (channels == 7) {
11970           stream->n_channels = 8;
11971         }
11972
11973         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
11974         rate = gst_codec_utils_aac_get_sample_rate_from_index (rateindex);
11975         if (rate > 0)
11976           stream->rate = rate;
11977       }
11978
11979       /* Set level and profile if possible */
11980       if (data_ptr != NULL && data_len >= 2) {
11981         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
11982             data_ptr, data_len);
11983       }
11984       break;
11985     case 0x60:                 /* MPEG-2, various profiles */
11986     case 0x61:
11987     case 0x62:
11988     case 0x63:
11989     case 0x64:
11990     case 0x65:
11991       codec_name = "MPEG-2 video";
11992       caps = gst_caps_new_simple ("video/mpeg",
11993           "mpegversion", G_TYPE_INT, 2,
11994           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11995       break;
11996     case 0x69:                 /* MPEG-2 BC audio */
11997     case 0x6B:                 /* MPEG-1 audio */
11998       caps = gst_caps_new_simple ("audio/mpeg",
11999           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12000       codec_name = "MPEG-1 audio";
12001       break;
12002     case 0x6A:                 /* MPEG-1 */
12003       codec_name = "MPEG-1 video";
12004       caps = gst_caps_new_simple ("video/mpeg",
12005           "mpegversion", G_TYPE_INT, 1,
12006           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12007       break;
12008     case 0x6C:                 /* MJPEG */
12009       caps =
12010           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12011           NULL);
12012       codec_name = "Motion-JPEG";
12013       break;
12014     case 0x6D:                 /* PNG */
12015       caps =
12016           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12017           NULL);
12018       codec_name = "PNG still images";
12019       break;
12020     case 0x6E:                 /* JPEG2000 */
12021       codec_name = "JPEG-2000";
12022       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12023       break;
12024     case 0xA4:                 /* Dirac */
12025       codec_name = "Dirac";
12026       caps = gst_caps_new_empty_simple ("video/x-dirac");
12027       break;
12028     case 0xA5:                 /* AC3 */
12029       codec_name = "AC-3 audio";
12030       caps = gst_caps_new_simple ("audio/x-ac3",
12031           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12032       break;
12033     case 0xA9:                 /* AC3 */
12034       codec_name = "DTS audio";
12035       caps = gst_caps_new_simple ("audio/x-dts",
12036           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12037       break;
12038     case 0xE1:                 /* QCELP */
12039       /* QCELP, the codec_data is a riff tag (little endian) with
12040        * 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). */
12041       caps = gst_caps_new_empty_simple ("audio/qcelp");
12042       codec_name = "QCELP";
12043       break;
12044     default:
12045       break;
12046   }
12047
12048   /* If we have a replacement caps, then change our caps for this stream */
12049   if (caps) {
12050     gst_caps_unref (stream->caps);
12051     stream->caps = caps;
12052   }
12053
12054   if (codec_name && list)
12055     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12056         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12057
12058   /* Add the codec_data attribute to caps, if we have it */
12059   if (data_ptr) {
12060     GstBuffer *buffer;
12061
12062     buffer = gst_buffer_new_and_alloc (data_len);
12063     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12064
12065     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12066     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12067
12068     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12069         buffer, NULL);
12070     gst_buffer_unref (buffer);
12071   }
12072
12073 }
12074
12075 #define _codec(name) \
12076   do { \
12077     if (codec_name) { \
12078       *codec_name = g_strdup (name); \
12079     } \
12080   } while (0)
12081
12082 static GstCaps *
12083 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12084     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12085 {
12086   GstCaps *caps = NULL;
12087   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12088
12089   switch (fourcc) {
12090     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12091       _codec ("PNG still images");
12092       caps = gst_caps_new_empty_simple ("image/png");
12093       break;
12094     case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'):
12095       _codec ("JPEG still images");
12096       caps =
12097           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12098           NULL);
12099       break;
12100     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12101     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12102     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12103     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12104       _codec ("Motion-JPEG");
12105       caps =
12106           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12107           NULL);
12108       break;
12109     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12110       _codec ("Motion-JPEG format B");
12111       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12112       break;
12113     case GST_MAKE_FOURCC ('m', 'j', 'p', '2'):
12114       _codec ("JPEG-2000");
12115       /* override to what it should be according to spec, avoid palette_data */
12116       stream->bits_per_sample = 24;
12117       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12118       break;
12119     case GST_MAKE_FOURCC ('S', 'V', 'Q', '3'):
12120       _codec ("Sorensen video v.3");
12121       caps = gst_caps_new_simple ("video/x-svq",
12122           "svqversion", G_TYPE_INT, 3, NULL);
12123       break;
12124     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12125     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12126       _codec ("Sorensen video v.1");
12127       caps = gst_caps_new_simple ("video/x-svq",
12128           "svqversion", G_TYPE_INT, 1, NULL);
12129       break;
12130     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12131       caps = gst_caps_new_empty_simple ("video/x-raw");
12132       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12133       _codec ("Windows Raw RGB");
12134       break;
12135     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
12136     {
12137       guint16 bps;
12138
12139       bps = QT_UINT16 (stsd_data + 98);
12140       switch (bps) {
12141         case 15:
12142           format = GST_VIDEO_FORMAT_RGB15;
12143           break;
12144         case 16:
12145           format = GST_VIDEO_FORMAT_RGB16;
12146           break;
12147         case 24:
12148           format = GST_VIDEO_FORMAT_RGB;
12149           break;
12150         case 32:
12151           format = GST_VIDEO_FORMAT_ARGB;
12152           break;
12153         default:
12154           /* unknown */
12155           break;
12156       }
12157       break;
12158     }
12159     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12160       format = GST_VIDEO_FORMAT_I420;
12161       break;
12162     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12163     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12164       format = GST_VIDEO_FORMAT_I420;
12165       break;
12166     case GST_MAKE_FOURCC ('2', 'v', 'u', 'y'):
12167     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12168       format = GST_VIDEO_FORMAT_UYVY;
12169       break;
12170     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12171       format = GST_VIDEO_FORMAT_v308;
12172       break;
12173     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12174       format = GST_VIDEO_FORMAT_v216;
12175       break;
12176     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
12177       format = GST_VIDEO_FORMAT_v210;
12178       break;
12179     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12180       format = GST_VIDEO_FORMAT_r210;
12181       break;
12182       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12183          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12184          format = GST_VIDEO_FORMAT_v410;
12185          break;
12186        */
12187       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12188        * but different order than AYUV
12189        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12190        format = GST_VIDEO_FORMAT_v408;
12191        break;
12192        */
12193     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12194     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12195       _codec ("MPEG-1 video");
12196       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12197           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12198       break;
12199     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12200     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12201     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12202     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12203     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12204     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12205     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12206     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12207     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12208     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12209     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12210     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12211     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12212     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12213     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12214     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12215     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12216     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12217     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12218     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12219     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12220     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12221     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12222     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12223     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12224     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12225     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12226     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12227     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12228     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12229     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12230     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12231     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12232     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12233     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12234     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12235     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12236     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12237     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12238     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12239     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12240     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12241     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12242     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12243     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12244     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12245       _codec ("MPEG-2 video");
12246       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12247           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12248       break;
12249     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12250       _codec ("GIF still images");
12251       caps = gst_caps_new_empty_simple ("image/gif");
12252       break;
12253     case GST_MAKE_FOURCC ('h', '2', '6', '3'):
12254     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12255     case GST_MAKE_FOURCC ('s', '2', '6', '3'):
12256     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12257       _codec ("H.263");
12258       /* ffmpeg uses the height/width props, don't know why */
12259       caps = gst_caps_new_simple ("video/x-h263",
12260           "variant", G_TYPE_STRING, "itu", NULL);
12261       break;
12262     case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
12263     case GST_MAKE_FOURCC ('M', 'P', '4', 'V'):
12264       _codec ("MPEG-4 video");
12265       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12266           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12267       break;
12268     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12269     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12270       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12271       caps = gst_caps_new_simple ("video/x-msmpeg",
12272           "msmpegversion", G_TYPE_INT, 43, NULL);
12273       break;
12274     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12275       _codec ("DivX 3");
12276       caps = gst_caps_new_simple ("video/x-divx",
12277           "divxversion", G_TYPE_INT, 3, NULL);
12278       break;
12279     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12280     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12281       _codec ("DivX 4");
12282       caps = gst_caps_new_simple ("video/x-divx",
12283           "divxversion", G_TYPE_INT, 4, NULL);
12284       break;
12285     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12286       _codec ("DivX 5");
12287       caps = gst_caps_new_simple ("video/x-divx",
12288           "divxversion", G_TYPE_INT, 5, NULL);
12289       break;
12290
12291     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
12292       _codec ("FFV1");
12293       caps = gst_caps_new_simple ("video/x-ffv",
12294           "ffvversion", G_TYPE_INT, 1, NULL);
12295       break;
12296
12297     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12298     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12299     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12300     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12301     case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
12302     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12303       caps = gst_caps_new_simple ("video/mpeg",
12304           "mpegversion", G_TYPE_INT, 4, NULL);
12305       if (codec_name)
12306         *codec_name = g_strdup ("MPEG-4");
12307       break;
12308
12309     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12310       _codec ("Cinepak");
12311       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12312       break;
12313     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12314       _codec ("Apple QuickDraw");
12315       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12316       break;
12317     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12318       _codec ("Apple video");
12319       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12320       break;
12321     case GST_MAKE_FOURCC ('H', '2', '6', '4'):
12322     case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
12323       _codec ("H.264 / AVC");
12324       caps = gst_caps_new_simple ("video/x-h264",
12325           "stream-format", G_TYPE_STRING, "avc",
12326           "alignment", G_TYPE_STRING, "au", NULL);
12327       break;
12328     case GST_MAKE_FOURCC ('a', 'v', 'c', '3'):
12329       _codec ("H.264 / AVC");
12330       caps = gst_caps_new_simple ("video/x-h264",
12331           "stream-format", G_TYPE_STRING, "avc3",
12332           "alignment", G_TYPE_STRING, "au", NULL);
12333       break;
12334     case GST_MAKE_FOURCC ('H', '2', '6', '5'):
12335     case GST_MAKE_FOURCC ('h', 'v', 'c', '1'):
12336       _codec ("H.265 / HEVC");
12337       caps = gst_caps_new_simple ("video/x-h265",
12338           "stream-format", G_TYPE_STRING, "hvc1",
12339           "alignment", G_TYPE_STRING, "au", NULL);
12340       break;
12341     case GST_MAKE_FOURCC ('h', 'e', 'v', '1'):
12342       _codec ("H.265 / HEVC");
12343       caps = gst_caps_new_simple ("video/x-h265",
12344           "stream-format", G_TYPE_STRING, "hev1",
12345           "alignment", G_TYPE_STRING, "au", NULL);
12346       break;
12347     case GST_MAKE_FOURCC ('r', 'l', 'e', ' '):
12348       _codec ("Run-length encoding");
12349       caps = gst_caps_new_simple ("video/x-rle",
12350           "layout", G_TYPE_STRING, "quicktime", NULL);
12351       break;
12352     case GST_MAKE_FOURCC ('W', 'R', 'L', 'E'):
12353       _codec ("Run-length encoding");
12354       caps = gst_caps_new_simple ("video/x-rle",
12355           "layout", G_TYPE_STRING, "microsoft", NULL);
12356       break;
12357     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12358     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12359       _codec ("Indeo Video 3");
12360       caps = gst_caps_new_simple ("video/x-indeo",
12361           "indeoversion", G_TYPE_INT, 3, NULL);
12362       break;
12363     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12364     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12365       _codec ("Intel Video 4");
12366       caps = gst_caps_new_simple ("video/x-indeo",
12367           "indeoversion", G_TYPE_INT, 4, NULL);
12368       break;
12369     case GST_MAKE_FOURCC ('d', 'v', 'c', 'p'):
12370     case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
12371     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12372     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12373     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12374     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12375     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12376     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12377       _codec ("DV Video");
12378       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12379           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12380       break;
12381     case GST_MAKE_FOURCC ('d', 'v', '5', 'n'): /* DVCPRO50 NTSC */
12382     case GST_MAKE_FOURCC ('d', 'v', '5', 'p'): /* DVCPRO50 PAL */
12383       _codec ("DVCPro50 Video");
12384       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12385           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12386       break;
12387     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12388     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12389       _codec ("DVCProHD Video");
12390       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12391           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12392       break;
12393     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12394       _codec ("Apple Graphics (SMC)");
12395       caps = gst_caps_new_empty_simple ("video/x-smc");
12396       break;
12397     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12398       _codec ("VP3");
12399       caps = gst_caps_new_empty_simple ("video/x-vp3");
12400       break;
12401     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12402       _codec ("VP6 Flash");
12403       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12404       break;
12405     case GST_MAKE_FOURCC ('X', 'i', 'T', 'h'):
12406       _codec ("Theora");
12407       caps = gst_caps_new_empty_simple ("video/x-theora");
12408       /* theora uses one byte of padding in the data stream because it does not
12409        * allow 0 sized packets while theora does */
12410       stream->padding = 1;
12411       break;
12412     case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'):
12413       _codec ("Dirac");
12414       caps = gst_caps_new_empty_simple ("video/x-dirac");
12415       break;
12416     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
12417       _codec ("TIFF still images");
12418       caps = gst_caps_new_empty_simple ("image/tiff");
12419       break;
12420     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
12421       _codec ("Apple Intermediate Codec");
12422       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
12423       break;
12424     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
12425       _codec ("AVID DNxHD");
12426       caps = gst_caps_from_string ("video/x-dnxhd");
12427       break;
12428     case GST_MAKE_FOURCC ('V', 'P', '8', '0'):
12429       _codec ("On2 VP8");
12430       caps = gst_caps_from_string ("video/x-vp8");
12431       break;
12432     case GST_MAKE_FOURCC ('a', 'p', 'c', 's'):
12433       _codec ("Apple ProRes LT");
12434       caps =
12435           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
12436           NULL);
12437       break;
12438     case GST_MAKE_FOURCC ('a', 'p', 'c', 'h'):
12439       _codec ("Apple ProRes HQ");
12440       caps =
12441           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
12442           NULL);
12443       break;
12444     case GST_MAKE_FOURCC ('a', 'p', 'c', 'n'):
12445       _codec ("Apple ProRes");
12446       caps =
12447           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12448           "standard", NULL);
12449       break;
12450     case GST_MAKE_FOURCC ('a', 'p', 'c', 'o'):
12451       _codec ("Apple ProRes Proxy");
12452       caps =
12453           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12454           "proxy", NULL);
12455       break;
12456     case GST_MAKE_FOURCC ('a', 'p', '4', 'h'):
12457       _codec ("Apple ProRes 4444");
12458       caps =
12459           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12460           "4444", NULL);
12461       break;
12462     case GST_MAKE_FOURCC ('v', 'c', '-', '1'):
12463     case FOURCC_ovc1:
12464       _codec ("VC-1");
12465       caps = gst_caps_new_simple ("video/x-wmv",
12466           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
12467       break;
12468     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
12469     default:
12470     {
12471       char *s, fourstr[5];
12472
12473       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12474       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
12475       caps = gst_caps_new_empty_simple (s);
12476       g_free (s);
12477       break;
12478     }
12479   }
12480
12481   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
12482     GstVideoInfo info;
12483
12484     gst_video_info_init (&info);
12485     gst_video_info_set_format (&info, format, stream->width, stream->height);
12486
12487     caps = gst_video_info_to_caps (&info);
12488     *codec_name = gst_pb_utils_get_codec_description (caps);
12489
12490     /* enable clipping for raw video streams */
12491     stream->need_clip = TRUE;
12492   }
12493
12494   return caps;
12495 }
12496
12497 static GstCaps *
12498 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12499     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
12500 {
12501   GstCaps *caps;
12502   const GstStructure *s;
12503   const gchar *name;
12504   gint endian = 0;
12505   GstAudioFormat format = 0;
12506   gint depth;
12507
12508   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12509
12510   depth = stream->bytes_per_packet * 8;
12511
12512   switch (fourcc) {
12513     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
12514     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
12515       /* 8-bit audio is unsigned */
12516       if (depth == 8)
12517         format = GST_AUDIO_FORMAT_U8;
12518       /* otherwise it's signed and big-endian just like 'twos' */
12519     case GST_MAKE_FOURCC ('t', 'w', 'o', 's'):
12520       endian = G_BIG_ENDIAN;
12521       /* fall-through */
12522     case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
12523     {
12524       gchar *str;
12525
12526       if (!endian)
12527         endian = G_LITTLE_ENDIAN;
12528
12529       if (!format)
12530         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
12531
12532       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
12533       _codec (str);
12534       g_free (str);
12535
12536       caps = gst_caps_new_simple ("audio/x-raw",
12537           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12538           "layout", G_TYPE_STRING, "interleaved", NULL);
12539       break;
12540     }
12541     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
12542       _codec ("Raw 64-bit floating-point audio");
12543       caps = gst_caps_new_simple ("audio/x-raw",
12544           "format", G_TYPE_STRING, "F64BE",
12545           "layout", G_TYPE_STRING, "interleaved", NULL);
12546       break;
12547     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
12548       _codec ("Raw 32-bit floating-point audio");
12549       caps = gst_caps_new_simple ("audio/x-raw",
12550           "format", G_TYPE_STRING, "F32BE",
12551           "layout", G_TYPE_STRING, "interleaved", NULL);
12552       break;
12553     case FOURCC_in24:
12554       _codec ("Raw 24-bit PCM audio");
12555       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
12556        * endian later */
12557       caps = gst_caps_new_simple ("audio/x-raw",
12558           "format", G_TYPE_STRING, "S24BE",
12559           "layout", G_TYPE_STRING, "interleaved", NULL);
12560       break;
12561     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
12562       _codec ("Raw 32-bit PCM audio");
12563       caps = gst_caps_new_simple ("audio/x-raw",
12564           "format", G_TYPE_STRING, "S32BE",
12565           "layout", G_TYPE_STRING, "interleaved", NULL);
12566       break;
12567     case GST_MAKE_FOURCC ('u', 'l', 'a', 'w'):
12568       _codec ("Mu-law audio");
12569       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
12570       break;
12571     case GST_MAKE_FOURCC ('a', 'l', 'a', 'w'):
12572       _codec ("A-law audio");
12573       caps = gst_caps_new_empty_simple ("audio/x-alaw");
12574       break;
12575     case 0x0200736d:
12576     case 0x6d730002:
12577       _codec ("Microsoft ADPCM");
12578       /* Microsoft ADPCM-ACM code 2 */
12579       caps = gst_caps_new_simple ("audio/x-adpcm",
12580           "layout", G_TYPE_STRING, "microsoft", NULL);
12581       break;
12582     case 0x1100736d:
12583     case 0x6d730011:
12584       _codec ("DVI/IMA ADPCM");
12585       caps = gst_caps_new_simple ("audio/x-adpcm",
12586           "layout", G_TYPE_STRING, "dvi", NULL);
12587       break;
12588     case 0x1700736d:
12589     case 0x6d730017:
12590       _codec ("DVI/Intel IMA ADPCM");
12591       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
12592       caps = gst_caps_new_simple ("audio/x-adpcm",
12593           "layout", G_TYPE_STRING, "quicktime", NULL);
12594       break;
12595     case 0x5500736d:
12596     case 0x6d730055:
12597       /* MPEG layer 3, CBR only (pre QT4.1) */
12598     case GST_MAKE_FOURCC ('.', 'm', 'p', '3'):
12599       _codec ("MPEG-1 layer 3");
12600       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
12601       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
12602           "mpegversion", G_TYPE_INT, 1, NULL);
12603       break;
12604     case 0x20736d:
12605     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
12606       _codec ("EAC-3 audio");
12607       caps = gst_caps_new_simple ("audio/x-eac3",
12608           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12609       stream->sampled = TRUE;
12610       break;
12611     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
12612     case GST_MAKE_FOURCC ('a', 'c', '-', '3'):
12613       _codec ("AC-3 audio");
12614       caps = gst_caps_new_simple ("audio/x-ac3",
12615           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12616       stream->sampled = TRUE;
12617       break;
12618     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
12619     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
12620       _codec ("DTS audio");
12621       caps = gst_caps_new_simple ("audio/x-dts",
12622           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12623       stream->sampled = TRUE;
12624       break;
12625     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
12626     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
12627       _codec ("DTS-HD audio");
12628       caps = gst_caps_new_simple ("audio/x-dts",
12629           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12630       stream->sampled = TRUE;
12631       break;
12632     case GST_MAKE_FOURCC ('M', 'A', 'C', '3'):
12633       _codec ("MACE-3");
12634       caps = gst_caps_new_simple ("audio/x-mace",
12635           "maceversion", G_TYPE_INT, 3, NULL);
12636       break;
12637     case GST_MAKE_FOURCC ('M', 'A', 'C', '6'):
12638       _codec ("MACE-6");
12639       caps = gst_caps_new_simple ("audio/x-mace",
12640           "maceversion", G_TYPE_INT, 6, NULL);
12641       break;
12642     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
12643       /* ogg/vorbis */
12644       caps = gst_caps_new_empty_simple ("application/ogg");
12645       break;
12646     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
12647       _codec ("DV audio");
12648       caps = gst_caps_new_empty_simple ("audio/x-dv");
12649       break;
12650     case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):
12651       _codec ("MPEG-4 AAC audio");
12652       caps = gst_caps_new_simple ("audio/mpeg",
12653           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
12654           "stream-format", G_TYPE_STRING, "raw", NULL);
12655       break;
12656     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
12657       _codec ("QDesign Music");
12658       caps = gst_caps_new_empty_simple ("audio/x-qdm");
12659       break;
12660     case GST_MAKE_FOURCC ('Q', 'D', 'M', '2'):
12661       _codec ("QDesign Music v.2");
12662       /* FIXME: QDesign music version 2 (no constant) */
12663       if (FALSE && data) {
12664         caps = gst_caps_new_simple ("audio/x-qdm2",
12665             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
12666             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
12667             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
12668       } else {
12669         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
12670       }
12671       break;
12672     case GST_MAKE_FOURCC ('a', 'g', 's', 'm'):
12673       _codec ("GSM audio");
12674       caps = gst_caps_new_empty_simple ("audio/x-gsm");
12675       break;
12676     case GST_MAKE_FOURCC ('s', 'a', 'm', 'r'):
12677       _codec ("AMR audio");
12678       caps = gst_caps_new_empty_simple ("audio/AMR");
12679       break;
12680     case GST_MAKE_FOURCC ('s', 'a', 'w', 'b'):
12681       _codec ("AMR-WB audio");
12682       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
12683       break;
12684     case GST_MAKE_FOURCC ('i', 'm', 'a', '4'):
12685       _codec ("Quicktime IMA ADPCM");
12686       caps = gst_caps_new_simple ("audio/x-adpcm",
12687           "layout", G_TYPE_STRING, "quicktime", NULL);
12688       break;
12689     case GST_MAKE_FOURCC ('a', 'l', 'a', 'c'):
12690       _codec ("Apple lossless audio");
12691       caps = gst_caps_new_empty_simple ("audio/x-alac");
12692       break;
12693     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
12694       _codec ("QualComm PureVoice");
12695       caps = gst_caps_from_string ("audio/qcelp");
12696       break;
12697     case GST_MAKE_FOURCC ('w', 'm', 'a', ' '):
12698     case FOURCC_owma:
12699       _codec ("WMA");
12700       caps = gst_caps_new_empty_simple ("audio/x-wma");
12701       break;
12702     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
12703     {
12704       guint32 flags = 0;
12705       guint32 depth = 0;
12706       guint32 width = 0;
12707       GstAudioFormat format;
12708       enum
12709       {
12710         FLAG_IS_FLOAT = 0x1,
12711         FLAG_IS_BIG_ENDIAN = 0x2,
12712         FLAG_IS_SIGNED = 0x4,
12713         FLAG_IS_PACKED = 0x8,
12714         FLAG_IS_ALIGNED_HIGH = 0x10,
12715         FLAG_IS_NON_INTERLEAVED = 0x20
12716       };
12717       _codec ("Raw LPCM audio");
12718
12719       if (data && len >= 56) {
12720         depth = QT_UINT32 (data + 40);
12721         flags = QT_UINT32 (data + 44);
12722         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
12723       }
12724       if ((flags & FLAG_IS_FLOAT) == 0) {
12725         if (depth == 0)
12726           depth = 16;
12727         if (width == 0)
12728           width = 16;
12729         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
12730             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
12731             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
12732         caps = gst_caps_new_simple ("audio/x-raw",
12733             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12734             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12735             "non-interleaved" : "interleaved", NULL);
12736       } else {
12737         if (width == 0)
12738           width = 32;
12739         if (width == 64) {
12740           if (flags & FLAG_IS_BIG_ENDIAN)
12741             format = GST_AUDIO_FORMAT_F64BE;
12742           else
12743             format = GST_AUDIO_FORMAT_F64LE;
12744         } else {
12745           if (flags & FLAG_IS_BIG_ENDIAN)
12746             format = GST_AUDIO_FORMAT_F32BE;
12747           else
12748             format = GST_AUDIO_FORMAT_F32LE;
12749         }
12750         caps = gst_caps_new_simple ("audio/x-raw",
12751             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12752             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12753             "non-interleaved" : "interleaved", NULL);
12754       }
12755       break;
12756     }
12757     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
12758       /* ? */
12759     default:
12760     {
12761       char *s, fourstr[5];
12762
12763       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12764       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
12765       caps = gst_caps_new_empty_simple (s);
12766       g_free (s);
12767       break;
12768     }
12769   }
12770
12771   if (caps) {
12772     GstCaps *templ_caps =
12773         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
12774     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
12775     gst_caps_unref (caps);
12776     gst_caps_unref (templ_caps);
12777     caps = intersection;
12778   }
12779
12780   /* enable clipping for raw audio streams */
12781   s = gst_caps_get_structure (caps, 0);
12782   name = gst_structure_get_name (s);
12783   if (g_str_has_prefix (name, "audio/x-raw")) {
12784     stream->need_clip = TRUE;
12785     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
12786     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
12787   }
12788   return caps;
12789 }
12790
12791 static GstCaps *
12792 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12793     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12794 {
12795   GstCaps *caps;
12796
12797   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12798
12799   switch (fourcc) {
12800     case GST_MAKE_FOURCC ('m', 'p', '4', 's'):
12801       _codec ("DVD subtitle");
12802       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
12803       stream->need_process = TRUE;
12804       break;
12805     case GST_MAKE_FOURCC ('t', 'e', 'x', 't'):
12806       _codec ("Quicktime timed text");
12807       goto text;
12808     case GST_MAKE_FOURCC ('t', 'x', '3', 'g'):
12809       _codec ("3GPP timed text");
12810     text:
12811       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
12812           "utf8", NULL);
12813       /* actual text piece needs to be extracted */
12814       stream->need_process = TRUE;
12815       break;
12816     case FOURCC_stpp:
12817       _codec ("XML subtitles");
12818       caps = gst_caps_new_empty_simple ("application/ttml+xml");
12819       break;
12820     default:
12821     {
12822       char *s, fourstr[5];
12823
12824       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12825       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
12826       caps = gst_caps_new_empty_simple (s);
12827       g_free (s);
12828       break;
12829     }
12830   }
12831   return caps;
12832 }
12833
12834 static GstCaps *
12835 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12836     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12837 {
12838   GstCaps *caps;
12839
12840   switch (fourcc) {
12841     case GST_MAKE_FOURCC ('m', '1', 'v', ' '):
12842       _codec ("MPEG 1 video");
12843       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12844           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12845       break;
12846     default:
12847       caps = NULL;
12848       break;
12849   }
12850   return caps;
12851 }
12852
12853 static void
12854 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
12855     const gchar * system_id)
12856 {
12857   gint i;
12858
12859   if (!qtdemux->protection_system_ids)
12860     qtdemux->protection_system_ids =
12861         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
12862   /* Check whether we already have an entry for this system ID. */
12863   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
12864     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
12865     if (g_ascii_strcasecmp (system_id, id) == 0) {
12866       return;
12867     }
12868   }
12869   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
12870   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
12871           -1));
12872 }