qtdemux: Push caps only when it was updated
[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 _QtDemuxSegment QtDemuxSegment;
101 typedef struct _QtDemuxSample QtDemuxSample;
102
103 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
104
105 struct _QtDemuxSample
106 {
107   guint32 size;
108   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
109   guint64 offset;
110   guint64 timestamp;            /* DTS In mov time */
111   guint32 duration;             /* In mov time */
112   gboolean keyframe;            /* TRUE when this packet is a keyframe */
113 };
114
115 /* Macros for converting to/from timescale */
116 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
117 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
118
119 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
120 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
121
122 /* timestamp is the DTS */
123 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
124 /* timestamp + offset is the PTS */
125 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
126 /* timestamp + duration - dts is the duration */
127 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
128
129 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
130
131 /*
132  * Quicktime has tracks and segments. A track is a continuous piece of
133  * multimedia content. The track is not always played from start to finish but
134  * instead, pieces of the track are 'cut out' and played in sequence. This is
135  * what the segments do.
136  *
137  * Inside the track we have keyframes (K) and delta frames. The track has its
138  * own timing, which starts from 0 and extends to end. The position in the track
139  * is called the media_time.
140  *
141  * The segments now describe the pieces that should be played from this track
142  * and are basically tuples of media_time/duration/rate entries. We can have
143  * multiple segments and they are all played after one another. An example:
144  *
145  * segment 1: media_time: 1 second, duration: 1 second, rate 1
146  * segment 2: media_time: 3 second, duration: 2 second, rate 2
147  *
148  * To correctly play back this track, one must play: 1 second of media starting
149  * from media_time 1 followed by 2 seconds of media starting from media_time 3
150  * at a rate of 2.
151  *
152  * Each of the segments will be played at a specific time, the first segment at
153  * time 0, the second one after the duration of the first one, etc.. Note that
154  * the time in resulting playback is not identical to the media_time of the
155  * track anymore.
156  *
157  * Visually, assuming the track has 4 second of media_time:
158  *
159  *                (a)                   (b)          (c)              (d)
160  *         .-----------------------------------------------------------.
161  * track:  | K.....K.........K........K.......K.......K...........K... |
162  *         '-----------------------------------------------------------'
163  *         0              1              2              3              4
164  *           .------------^              ^   .----------^              ^
165  *          /              .-------------'  /       .------------------'
166  *         /              /          .-----'       /
167  *         .--------------.         .--------------.
168  *         | segment 1    |         | segment 2    |
169  *         '--------------'         '--------------'
170  *
171  * The challenge here is to cut out the right pieces of the track for each of
172  * the playback segments. This fortunately can easily be done with the SEGMENT
173  * events of GStreamer.
174  *
175  * For playback of segment 1, we need to provide the decoder with the keyframe
176  * (a), in the above figure, but we must instruct it only to output the decoded
177  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
178  * position set to the time of the segment: 0.
179  *
180  * We then proceed to push data from keyframe (a) to frame (b). The decoder
181  * decodes but clips all before media_time 1.
182  *
183  * After finishing a segment, we push out a new SEGMENT event with the clipping
184  * boundaries of the new data.
185  *
186  * This is a good usecase for the GStreamer accumulated SEGMENT events.
187  */
188
189 struct _QtDemuxSegment
190 {
191   /* global time and duration, all gst time */
192   GstClockTime time;
193   GstClockTime stop_time;
194   GstClockTime duration;
195   /* media time of trak, all gst time */
196   GstClockTime media_start;
197   GstClockTime media_stop;
198   gdouble rate;
199   /* Media start time in trak timescale units */
200   guint32 trak_media_start;
201 };
202
203 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
204
205 /* Used with fragmented MP4 files (mfra atom) */
206 typedef struct
207 {
208   GstClockTime ts;
209   guint64 moof_offset;
210 } QtDemuxRandomAccessEntry;
211
212 struct _QtDemuxStream
213 {
214   GstPad *pad;
215
216   /* stream type */
217   guint32 subtype;
218   GstCaps *caps;
219   guint32 fourcc;
220   gboolean sparse;
221
222   gboolean new_caps;            /* If TRUE, caps need to be generated (by
223                                  * calling _configure_stream()) This happens
224                                  * for MSS and fragmented streams */
225
226   gboolean new_stream;          /* signals that a stream_start is required */
227   gboolean on_keyframe;         /* if this stream last pushed buffer was a
228                                  * keyframe. This is important to identify
229                                  * where to stop pushing buffers after a
230                                  * segment stop time */
231
232   /* if the stream has a redirect URI in its headers, we store it here */
233   gchar *redirect_uri;
234
235   /* track id */
236   guint track_id;
237
238   /* duration/scale */
239   guint64 duration;             /* in timescale units */
240   guint32 timescale;
241
242   /* language */
243   gchar lang_id[4];             /* ISO 639-2T language code */
244
245   /* our samples */
246   guint32 n_samples;
247   QtDemuxSample *samples;
248   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
249   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
250                                    the framerate */
251   guint32 n_samples_moof;       /* sample count in a moof */
252   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
253                                  * the framerate of fragmented format stream */
254
255   guint32 offset_in_sample;     /* Offset in the current sample, used for
256                                  * streams which have got exceedingly big
257                                  * sample size (such as 24s of raw audio).
258                                  * Only used when max_buffer_size is non-NULL */
259   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
260                                  * Currently only set for raw audio streams*/
261
262   /* if we use chunks or samples */
263   gboolean sampled;
264   guint padding;
265
266   /* video info */
267   gint width;
268   gint height;
269   /* aspect ratio */
270   gint display_width;
271   gint display_height;
272   gint par_w;
273   gint par_h;
274   /* Numerator/denominator framerate */
275   gint fps_n;
276   gint fps_d;
277   guint16 bits_per_sample;
278   guint16 color_table_id;
279   GstMemory *rgb8_palette;
280
281   /* audio info */
282   gdouble rate;
283   gint n_channels;
284   guint samples_per_packet;
285   guint samples_per_frame;
286   guint bytes_per_packet;
287   guint bytes_per_sample;
288   guint bytes_per_frame;
289   guint compression;
290
291   /* allocation */
292   gboolean use_allocator;
293   GstAllocator *allocator;
294   GstAllocationParams params;
295
296   /* when a discontinuity is pending */
297   gboolean discont;
298
299   /* list of buffers to push first */
300   GSList *buffers;
301
302   /* if we need to clip this buffer. This is only needed for uncompressed
303    * data */
304   gboolean need_clip;
305
306   /* buffer needs some custom processing, e.g. subtitles */
307   gboolean need_process;
308
309   /* current position */
310   guint32 segment_index;
311   guint32 sample_index;
312   GstClockTime time_position;   /* in gst time */
313   guint64 accumulated_base;
314
315   /* the Gst segment we are processing out, used for clipping */
316   GstSegment segment;
317
318   /* quicktime segments */
319   guint32 n_segments;
320   QtDemuxSegment *segments;
321   gboolean dummy_segment;
322   guint32 from_sample;
323   guint32 to_sample;
324
325   gboolean sent_eos;
326   GstTagList *pending_tags;
327   gboolean send_global_tags;
328
329   GstEvent *pending_event;
330
331   GstByteReader stco;
332   GstByteReader stsz;
333   GstByteReader stsc;
334   GstByteReader stts;
335   GstByteReader stss;
336   GstByteReader stps;
337   GstByteReader ctts;
338
339   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
340   gint64 stbl_index;
341   /* stco */
342   guint co_size;
343   GstByteReader co_chunk;
344   guint32 first_chunk;
345   guint32 current_chunk;
346   guint32 last_chunk;
347   guint32 samples_per_chunk;
348   guint32 stco_sample_index;
349   /* stsz */
350   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
351   /* stsc */
352   guint32 stsc_index;
353   guint32 n_samples_per_chunk;
354   guint32 stsc_chunk_index;
355   guint32 stsc_sample_index;
356   guint64 chunk_offset;
357   /* stts */
358   guint32 stts_index;
359   guint32 stts_samples;
360   guint32 n_sample_times;
361   guint32 stts_sample_index;
362   guint64 stts_time;
363   guint32 stts_duration;
364   /* stss */
365   gboolean stss_present;
366   guint32 n_sample_syncs;
367   guint32 stss_index;
368   /* stps */
369   gboolean stps_present;
370   guint32 n_sample_partial_syncs;
371   guint32 stps_index;
372   QtDemuxRandomAccessEntry *ra_entries;
373   guint n_ra_entries;
374
375   const QtDemuxRandomAccessEntry *pending_seek;
376
377   /* ctts */
378   gboolean ctts_present;
379   guint32 n_composition_times;
380   guint32 ctts_index;
381   guint32 ctts_sample_index;
382   guint32 ctts_count;
383   gint32 ctts_soffset;
384
385   /* cslg */
386   guint32 cslg_shift;
387
388   /* fragmented */
389   gboolean parsed_trex;
390   guint32 def_sample_duration;
391   guint32 def_sample_size;
392   guint32 def_sample_flags;
393
394   gboolean disabled;
395
396   /* stereoscopic video streams */
397   GstVideoMultiviewMode multiview_mode;
398   GstVideoMultiviewFlags multiview_flags;
399
400   /* protected streams */
401   gboolean protected;
402   guint32 protection_scheme_type;
403   guint32 protection_scheme_version;
404   gpointer protection_scheme_info;      /* specific to the protection scheme */
405   GQueue protection_scheme_event_queue;
406 };
407
408 /* Contains properties and cryptographic info for a set of samples from a
409  * track protected using Common Encryption (cenc) */
410 struct _QtDemuxCencSampleSetInfo
411 {
412   GstStructure *default_properties;
413
414   /* @crypto_info holds one GstStructure per sample */
415   GPtrArray *crypto_info;
416 };
417
418 static const gchar *
419 qt_demux_state_string (enum QtDemuxState state)
420 {
421   switch (state) {
422     case QTDEMUX_STATE_INITIAL:
423       return "<INITIAL>";
424     case QTDEMUX_STATE_HEADER:
425       return "<HEADER>";
426     case QTDEMUX_STATE_MOVIE:
427       return "<MOVIE>";
428     case QTDEMUX_STATE_BUFFER_MDAT:
429       return "<BUFFER_MDAT>";
430     default:
431       return "<UNKNOWN>";
432   }
433 }
434
435 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
436 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
437     guint32 fourcc, GstByteReader * parser);
438 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
439 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
440     guint32 fourcc, GstByteReader * parser);
441
442 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
443
444 static GstStaticPadTemplate gst_qtdemux_sink_template =
445     GST_STATIC_PAD_TEMPLATE ("sink",
446     GST_PAD_SINK,
447     GST_PAD_ALWAYS,
448     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
449         "application/x-3gp")
450     );
451
452 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
453 GST_STATIC_PAD_TEMPLATE ("video_%u",
454     GST_PAD_SRC,
455     GST_PAD_SOMETIMES,
456     GST_STATIC_CAPS_ANY);
457
458 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
459 GST_STATIC_PAD_TEMPLATE ("audio_%u",
460     GST_PAD_SRC,
461     GST_PAD_SOMETIMES,
462     GST_STATIC_CAPS_ANY);
463
464 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
465 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
466     GST_PAD_SRC,
467     GST_PAD_SOMETIMES,
468     GST_STATIC_CAPS_ANY);
469
470 #define gst_qtdemux_parent_class parent_class
471 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
472
473 static void gst_qtdemux_dispose (GObject * object);
474
475 static guint32
476 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
477     GstClockTime media_time);
478 static guint32
479 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
480     QtDemuxStream * str, gint64 media_offset);
481
482 #if 0
483 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
484 static GstIndex *gst_qtdemux_get_index (GstElement * element);
485 #endif
486 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
487     GstStateChange transition);
488 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
489 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
490     GstObject * parent, GstPadMode mode, gboolean active);
491
492 static void gst_qtdemux_loop (GstPad * pad);
493 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
494     GstBuffer * inbuf);
495 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
496     GstEvent * event);
497 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
498 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
499     QtDemuxStream * stream);
500 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
501     gboolean force);
502
503 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
504     const guint8 * buffer, guint length);
505 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
506     const guint8 * buffer, guint length);
507 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
508 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
509     GNode * udta);
510
511 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
512     QtDemuxStream * stream, GNode * esds, GstTagList * list);
513 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
514     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
515     gchar ** codec_name);
516 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
517     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
518     gchar ** codec_name);
519 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
520     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
521     gchar ** codec_name);
522 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
523     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
524     gchar ** codec_name);
525
526 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
527     QtDemuxStream * stream, guint32 n);
528 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
529 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
530     QtDemuxStream * stream);
531 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
532     QtDemuxStream * stream);
533 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
534 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
535 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
536     QtDemuxStream * stream);
537 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
538     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
539 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
540     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
541     GstClockTime * _start, GstClockTime * _stop);
542 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
543     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
544
545 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
546 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
547
548 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
549
550 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
551     QtDemuxStream * stream, guint sample_index);
552 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
553     const gchar * id);
554 static void qtdemux_gst_structure_free (GstStructure * gststructure);
555
556 static void
557 gst_qtdemux_class_init (GstQTDemuxClass * klass)
558 {
559   GObjectClass *gobject_class;
560   GstElementClass *gstelement_class;
561
562   gobject_class = (GObjectClass *) klass;
563   gstelement_class = (GstElementClass *) klass;
564
565   parent_class = g_type_class_peek_parent (klass);
566
567   gobject_class->dispose = gst_qtdemux_dispose;
568
569   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
570 #if 0
571   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
572   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
573 #endif
574
575   gst_tag_register_musicbrainz_tags ();
576
577   gst_element_class_add_static_pad_template (gstelement_class,
578       &gst_qtdemux_sink_template);
579   gst_element_class_add_static_pad_template (gstelement_class,
580       &gst_qtdemux_videosrc_template);
581   gst_element_class_add_static_pad_template (gstelement_class,
582       &gst_qtdemux_audiosrc_template);
583   gst_element_class_add_static_pad_template (gstelement_class,
584       &gst_qtdemux_subsrc_template);
585   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
586       "Codec/Demuxer",
587       "Demultiplex a QuickTime file into audio and video streams",
588       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
589
590   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
591
592 }
593
594 static void
595 gst_qtdemux_init (GstQTDemux * qtdemux)
596 {
597   qtdemux->sinkpad =
598       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
599   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
600   gst_pad_set_activatemode_function (qtdemux->sinkpad,
601       qtdemux_sink_activate_mode);
602   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
603   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
604   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
605
606   qtdemux->state = QTDEMUX_STATE_INITIAL;
607   qtdemux->pullbased = FALSE;
608   qtdemux->posted_redirect = FALSE;
609   qtdemux->neededbytes = 16;
610   qtdemux->todrop = 0;
611   qtdemux->adapter = gst_adapter_new ();
612   qtdemux->offset = 0;
613   qtdemux->first_mdat = -1;
614   qtdemux->got_moov = FALSE;
615   qtdemux->mdatoffset = -1;
616   qtdemux->mdatbuffer = NULL;
617   qtdemux->restoredata_buffer = NULL;
618   qtdemux->restoredata_offset = -1;
619   qtdemux->fragment_start = -1;
620   qtdemux->fragment_start_offset = -1;
621   qtdemux->media_caps = NULL;
622   qtdemux->exposed = FALSE;
623   qtdemux->mss_mode = FALSE;
624   qtdemux->pending_newsegment = NULL;
625   qtdemux->upstream_format_is_time = FALSE;
626   qtdemux->have_group_id = FALSE;
627   qtdemux->group_id = G_MAXUINT;
628   qtdemux->cenc_aux_info_offset = 0;
629   qtdemux->cenc_aux_info_sizes = NULL;
630   qtdemux->cenc_aux_sample_count = 0;
631   qtdemux->protection_system_ids = NULL;
632   g_queue_init (&qtdemux->protection_event_queue);
633   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
634   qtdemux->flowcombiner = gst_flow_combiner_new ();
635
636   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
637 }
638
639 static void
640 gst_qtdemux_dispose (GObject * object)
641 {
642   GstQTDemux *qtdemux = GST_QTDEMUX (object);
643
644   if (qtdemux->adapter) {
645     g_object_unref (G_OBJECT (qtdemux->adapter));
646     qtdemux->adapter = NULL;
647   }
648   gst_flow_combiner_free (qtdemux->flowcombiner);
649   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
650       NULL);
651   g_queue_clear (&qtdemux->protection_event_queue);
652
653   g_free (qtdemux->cenc_aux_info_sizes);
654   qtdemux->cenc_aux_info_sizes = NULL;
655
656   G_OBJECT_CLASS (parent_class)->dispose (object);
657 }
658
659 static void
660 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
661 {
662   if (qtdemux->posted_redirect) {
663     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
664         (_("This file contains no playable streams.")),
665         ("no known streams found, a redirect message has been posted"));
666   } else {
667     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
668         (_("This file contains no playable streams.")),
669         ("no known streams found"));
670   }
671 }
672
673 static GstBuffer *
674 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
675 {
676   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
677       mem, size, 0, size, mem, free_func);
678 }
679
680 static GstFlowReturn
681 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
682     GstBuffer ** buf)
683 {
684   GstFlowReturn flow;
685   GstMapInfo map;
686   gsize bsize;
687
688   if (G_UNLIKELY (size == 0)) {
689     GstFlowReturn ret;
690     GstBuffer *tmp = NULL;
691
692     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
693     if (ret != GST_FLOW_OK)
694       return ret;
695
696     gst_buffer_map (tmp, &map, GST_MAP_READ);
697     size = QT_UINT32 (map.data);
698     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
699
700     gst_buffer_unmap (tmp, &map);
701     gst_buffer_unref (tmp);
702   }
703
704   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
705   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
706     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
707       /* we're pulling header but already got most interesting bits,
708        * so never mind the rest (e.g. tags) (that much) */
709       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
710           size);
711       return GST_FLOW_EOS;
712     } else {
713       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
714           (_("This file is invalid and cannot be played.")),
715           ("atom has bogus size %" G_GUINT64_FORMAT, size));
716       return GST_FLOW_ERROR;
717     }
718   }
719
720   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
721
722   if (G_UNLIKELY (flow != GST_FLOW_OK))
723     return flow;
724
725   bsize = gst_buffer_get_size (*buf);
726   /* Catch short reads - we don't want any partial atoms */
727   if (G_UNLIKELY (bsize < size)) {
728     GST_WARNING_OBJECT (qtdemux,
729         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
730     gst_buffer_unref (*buf);
731     *buf = NULL;
732     return GST_FLOW_EOS;
733   }
734
735   return flow;
736 }
737
738 #if 1
739 static gboolean
740 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
741     GstFormat src_format, gint64 src_value, GstFormat dest_format,
742     gint64 * dest_value)
743 {
744   gboolean res = TRUE;
745   QtDemuxStream *stream = gst_pad_get_element_private (pad);
746   gint32 index;
747
748   if (stream->subtype != FOURCC_vide) {
749     res = FALSE;
750     goto done;
751   }
752
753   switch (src_format) {
754     case GST_FORMAT_TIME:
755       switch (dest_format) {
756         case GST_FORMAT_BYTES:{
757           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
758           if (-1 == index) {
759             res = FALSE;
760             goto done;
761           }
762
763           *dest_value = stream->samples[index].offset;
764
765           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
766               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
767               GST_TIME_ARGS (src_value), *dest_value);
768           break;
769         }
770         default:
771           res = FALSE;
772           break;
773       }
774       break;
775     case GST_FORMAT_BYTES:
776       switch (dest_format) {
777         case GST_FORMAT_TIME:{
778           index =
779               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
780               stream, src_value);
781
782           if (-1 == index) {
783             res = FALSE;
784             goto done;
785           }
786
787           *dest_value =
788               QTSTREAMTIME_TO_GSTTIME (stream,
789               stream->samples[index].timestamp);
790           GST_DEBUG_OBJECT (qtdemux,
791               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
792               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
793           break;
794         }
795         default:
796           res = FALSE;
797           break;
798       }
799       break;
800     default:
801       res = FALSE;
802       break;
803   }
804
805 done:
806   return res;
807 }
808 #endif
809
810 static gboolean
811 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
812 {
813   gboolean res = FALSE;
814
815   *duration = GST_CLOCK_TIME_NONE;
816
817   if (qtdemux->duration != 0 &&
818       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
819     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
820     res = TRUE;
821   } else {
822     *duration = GST_CLOCK_TIME_NONE;
823   }
824
825   return res;
826 }
827
828 static gboolean
829 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
830     GstQuery * query)
831 {
832   gboolean res = FALSE;
833   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
834
835   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
836
837   switch (GST_QUERY_TYPE (query)) {
838     case GST_QUERY_POSITION:{
839       GstFormat fmt;
840
841       gst_query_parse_position (query, &fmt, NULL);
842       if (fmt == GST_FORMAT_TIME
843           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
844         gst_query_set_position (query, GST_FORMAT_TIME,
845             qtdemux->segment.position);
846         res = TRUE;
847       }
848     }
849       break;
850     case GST_QUERY_DURATION:{
851       GstFormat fmt;
852
853       gst_query_parse_duration (query, &fmt, NULL);
854       if (fmt == GST_FORMAT_TIME) {
855         /* First try to query upstream */
856         res = gst_pad_query_default (pad, parent, query);
857         if (!res) {
858           GstClockTime duration;
859           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
860             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
861             res = TRUE;
862           }
863         }
864       }
865       break;
866     }
867     case GST_QUERY_CONVERT:{
868       GstFormat src_fmt, dest_fmt;
869       gint64 src_value, dest_value = 0;
870
871       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
872
873       res = gst_qtdemux_src_convert (qtdemux, pad,
874           src_fmt, src_value, dest_fmt, &dest_value);
875       if (res) {
876         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
877         res = TRUE;
878       }
879       break;
880     }
881     case GST_QUERY_FORMATS:
882       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
883       res = TRUE;
884       break;
885     case GST_QUERY_SEEKING:{
886       GstFormat fmt;
887       gboolean seekable;
888
889       /* try upstream first */
890       res = gst_pad_query_default (pad, parent, query);
891
892       if (!res) {
893         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
894         if (fmt == GST_FORMAT_TIME) {
895           GstClockTime duration;
896
897           gst_qtdemux_get_duration (qtdemux, &duration);
898           seekable = TRUE;
899           if (!qtdemux->pullbased) {
900             GstQuery *q;
901
902             /* we might be able with help from upstream */
903             seekable = FALSE;
904             q = gst_query_new_seeking (GST_FORMAT_BYTES);
905             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
906               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
907               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
908             }
909             gst_query_unref (q);
910           }
911           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
912           res = TRUE;
913         }
914       }
915       break;
916     }
917     case GST_QUERY_SEGMENT:
918     {
919       GstFormat format;
920       gint64 start, stop;
921
922       format = qtdemux->segment.format;
923
924       start =
925           gst_segment_to_stream_time (&qtdemux->segment, format,
926           qtdemux->segment.start);
927       if ((stop = qtdemux->segment.stop) == -1)
928         stop = qtdemux->segment.duration;
929       else
930         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
931
932       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
933       res = TRUE;
934       break;
935     }
936     default:
937       res = gst_pad_query_default (pad, parent, query);
938       break;
939   }
940
941   return res;
942 }
943
944 static void
945 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
946 {
947   if (G_LIKELY (stream->pad)) {
948     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
949         GST_DEBUG_PAD_NAME (stream->pad));
950
951     if (G_UNLIKELY (stream->pending_tags)) {
952       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
953           stream->pending_tags);
954       gst_pad_push_event (stream->pad,
955           gst_event_new_tag (stream->pending_tags));
956       stream->pending_tags = NULL;
957     }
958
959     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
960       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
961           qtdemux->tag_list);
962       gst_pad_push_event (stream->pad,
963           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
964       stream->send_global_tags = FALSE;
965     }
966   }
967 }
968
969 /* push event on all source pads; takes ownership of the event */
970 static void
971 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
972 {
973   guint n;
974   gboolean has_valid_stream = FALSE;
975   GstEventType etype = GST_EVENT_TYPE (event);
976
977   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
978       GST_EVENT_TYPE_NAME (event));
979
980   for (n = 0; n < qtdemux->n_streams; n++) {
981     GstPad *pad;
982     QtDemuxStream *stream = qtdemux->streams[n];
983     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
984
985     if ((pad = stream->pad)) {
986       has_valid_stream = TRUE;
987
988       if (etype == GST_EVENT_EOS) {
989         /* let's not send twice */
990         if (stream->sent_eos)
991           continue;
992         stream->sent_eos = TRUE;
993       }
994
995       gst_pad_push_event (pad, gst_event_ref (event));
996     }
997   }
998
999   gst_event_unref (event);
1000
1001   /* if it is EOS and there are no pads, post an error */
1002   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1003     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1004   }
1005 }
1006
1007 /* push a pending newsegment event, if any from the streaming thread */
1008 static void
1009 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1010 {
1011   if (qtdemux->pending_newsegment) {
1012     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1013     qtdemux->pending_newsegment = NULL;
1014   }
1015 }
1016
1017 typedef struct
1018 {
1019   guint64 media_time;
1020 } FindData;
1021
1022 static gint
1023 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1024 {
1025   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1026     return 1;
1027   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1028     return 0;
1029
1030   return -1;
1031 }
1032
1033 /* find the index of the sample that includes the data for @media_time using a
1034  * binary search.  Only to be called in optimized cases of linear search below.
1035  *
1036  * Returns the index of the sample.
1037  */
1038 static guint32
1039 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1040     guint64 media_time)
1041 {
1042   QtDemuxSample *result;
1043   guint32 index;
1044
1045   /* convert media_time to mov format */
1046   media_time =
1047       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1048
1049   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1050       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1051       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1052
1053   if (G_LIKELY (result))
1054     index = result - str->samples;
1055   else
1056     index = 0;
1057
1058   return index;
1059 }
1060
1061
1062
1063 /* find the index of the sample that includes the data for @media_offset using a
1064  * linear search
1065  *
1066  * Returns the index of the sample.
1067  */
1068 static guint32
1069 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1070     QtDemuxStream * str, gint64 media_offset)
1071 {
1072   QtDemuxSample *result = str->samples;
1073   guint32 index = 0;
1074
1075   if (result == NULL || str->n_samples == 0)
1076     return -1;
1077
1078   if (media_offset == result->offset)
1079     return index;
1080
1081   result++;
1082   while (index < str->n_samples - 1) {
1083     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1084       goto parse_failed;
1085
1086     if (media_offset < result->offset)
1087       break;
1088
1089     index++;
1090     result++;
1091   }
1092   return index;
1093
1094   /* ERRORS */
1095 parse_failed:
1096   {
1097     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1098     return -1;
1099   }
1100 }
1101
1102 /* find the index of the sample that includes the data for @media_time using a
1103  * linear search, and keeping in mind that not all samples may have been parsed
1104  * yet.  If possible, it will delegate to binary search.
1105  *
1106  * Returns the index of the sample.
1107  */
1108 static guint32
1109 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1110     GstClockTime media_time)
1111 {
1112   guint32 index = 0;
1113   guint64 mov_time;
1114   QtDemuxSample *sample;
1115
1116   /* convert media_time to mov format */
1117   mov_time =
1118       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1119
1120   sample = str->samples;
1121   if (mov_time == sample->timestamp + sample->pts_offset)
1122     return index;
1123
1124   /* use faster search if requested time in already parsed range */
1125   sample = str->samples + str->stbl_index;
1126   if (str->stbl_index >= 0 &&
1127       mov_time <= (sample->timestamp + sample->pts_offset))
1128     return gst_qtdemux_find_index (qtdemux, str, media_time);
1129
1130   while (index < str->n_samples - 1) {
1131     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1132       goto parse_failed;
1133
1134     sample = str->samples + index + 1;
1135     if (mov_time < (sample->timestamp + sample->pts_offset))
1136       break;
1137
1138     index++;
1139   }
1140   return index;
1141
1142   /* ERRORS */
1143 parse_failed:
1144   {
1145     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1146     return -1;
1147   }
1148 }
1149
1150 /* find the index of the keyframe needed to decode the sample at @index
1151  * of stream @str.
1152  *
1153  * Returns the index of the keyframe.
1154  */
1155 static guint32
1156 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1157     guint32 index)
1158 {
1159   guint32 new_index = index;
1160
1161   if (index >= str->n_samples) {
1162     new_index = str->n_samples;
1163     goto beach;
1164   }
1165
1166   /* all keyframes, return index */
1167   if (str->all_keyframe) {
1168     new_index = index;
1169     goto beach;
1170   }
1171
1172   /* else go back until we have a keyframe */
1173   while (TRUE) {
1174     if (str->samples[new_index].keyframe)
1175       break;
1176
1177     if (new_index == 0)
1178       break;
1179
1180     new_index--;
1181   }
1182
1183 beach:
1184   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1185       "gave %u", index, new_index);
1186
1187   return new_index;
1188 }
1189
1190 /* find the segment for @time_position for @stream
1191  *
1192  * Returns the index of the segment containing @time_position.
1193  * Returns the last segment and sets the @eos variable to TRUE
1194  * if the time is beyond the end. @eos may be NULL
1195  */
1196 static guint32
1197 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1198     GstClockTime time_position)
1199 {
1200   gint i;
1201   guint32 seg_idx;
1202
1203   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1204       GST_TIME_ARGS (time_position));
1205
1206   seg_idx = -1;
1207   for (i = 0; i < stream->n_segments; i++) {
1208     QtDemuxSegment *segment = &stream->segments[i];
1209
1210     GST_LOG_OBJECT (stream->pad,
1211         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1212         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1213
1214     /* For the last segment we include stop_time in the last segment */
1215     if (i < stream->n_segments - 1) {
1216       if (segment->time <= time_position && time_position < segment->stop_time) {
1217         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1218         seg_idx = i;
1219         break;
1220       }
1221     } else {
1222       /* Last segment always matches */
1223       seg_idx = i;
1224       break;
1225     }
1226   }
1227   return seg_idx;
1228 }
1229
1230 /* move the stream @str to the sample position @index.
1231  *
1232  * Updates @str->sample_index and marks discontinuity if needed.
1233  */
1234 static void
1235 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1236     guint32 index)
1237 {
1238   /* no change needed */
1239   if (index == str->sample_index)
1240     return;
1241
1242   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1243       str->n_samples);
1244
1245   /* position changed, we have a discont */
1246   str->sample_index = index;
1247   str->offset_in_sample = 0;
1248   /* Each time we move in the stream we store the position where we are
1249    * starting from */
1250   str->from_sample = index;
1251   str->discont = TRUE;
1252 }
1253
1254 static void
1255 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1256     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1257 {
1258   guint64 min_offset;
1259   gint64 min_byte_offset = -1;
1260   gint n;
1261
1262   min_offset = desired_time;
1263
1264   /* for each stream, find the index of the sample in the segment
1265    * and move back to the previous keyframe. */
1266   for (n = 0; n < qtdemux->n_streams; n++) {
1267     QtDemuxStream *str;
1268     guint32 index, kindex;
1269     guint32 seg_idx;
1270     GstClockTime media_start;
1271     GstClockTime media_time;
1272     GstClockTime seg_time;
1273     QtDemuxSegment *seg;
1274     gboolean empty_segment = FALSE;
1275
1276     str = qtdemux->streams[n];
1277
1278     if (str->sparse && !use_sparse)
1279       continue;
1280
1281     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1282     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1283
1284     /* get segment and time in the segment */
1285     seg = &str->segments[seg_idx];
1286     seg_time = (desired_time - seg->time) * seg->rate;
1287
1288     while (QTSEGMENT_IS_EMPTY (seg)) {
1289       seg_time = 0;
1290       empty_segment = TRUE;
1291       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1292           seg_idx);
1293       seg_idx++;
1294       if (seg_idx == str->n_segments)
1295         break;
1296       seg = &str->segments[seg_idx];
1297     }
1298
1299     if (seg_idx == str->n_segments) {
1300       /* FIXME track shouldn't have the last segment as empty, but if it
1301        * happens we better handle it */
1302       continue;
1303     }
1304
1305     /* get the media time in the segment */
1306     media_start = seg->media_start + seg_time;
1307
1308     /* get the index of the sample with media time */
1309     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1310     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1311         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1312         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1313         empty_segment);
1314
1315     if (!empty_segment) {
1316       /* find previous keyframe */
1317       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1318
1319       /* if the keyframe is at a different position, we need to update the
1320        * requested seek time */
1321       if (index != kindex) {
1322         index = kindex;
1323
1324         /* get timestamp of keyframe */
1325         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1326         GST_DEBUG_OBJECT (qtdemux,
1327             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1328             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1329             str->samples[kindex].offset);
1330
1331         /* keyframes in the segment get a chance to change the
1332          * desired_offset. keyframes out of the segment are
1333          * ignored. */
1334         if (media_time >= seg->media_start) {
1335           GstClockTime seg_time;
1336
1337           /* this keyframe is inside the segment, convert back to
1338            * segment time */
1339           seg_time = (media_time - seg->media_start) + seg->time;
1340           if (seg_time < min_offset)
1341             min_offset = seg_time;
1342         }
1343       }
1344     }
1345
1346     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1347       min_byte_offset = str->samples[index].offset;
1348   }
1349
1350   if (key_time)
1351     *key_time = min_offset;
1352   if (key_offset)
1353     *key_offset = min_byte_offset;
1354 }
1355
1356 static gboolean
1357 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1358     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1359 {
1360   gboolean res;
1361
1362   g_return_val_if_fail (format != NULL, FALSE);
1363   g_return_val_if_fail (cur != NULL, FALSE);
1364   g_return_val_if_fail (stop != NULL, FALSE);
1365
1366   if (*format == GST_FORMAT_TIME)
1367     return TRUE;
1368
1369   res = TRUE;
1370   if (cur_type != GST_SEEK_TYPE_NONE)
1371     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1372   if (res && stop_type != GST_SEEK_TYPE_NONE)
1373     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1374
1375   if (res)
1376     *format = GST_FORMAT_TIME;
1377
1378   return res;
1379 }
1380
1381 /* perform seek in push based mode:
1382    find BYTE position to move to based on time and delegate to upstream
1383 */
1384 static gboolean
1385 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1386 {
1387   gdouble rate;
1388   GstFormat format;
1389   GstSeekFlags flags;
1390   GstSeekType cur_type, stop_type;
1391   gint64 cur, stop, key_cur;
1392   gboolean res;
1393   gint64 byte_cur;
1394   gint64 original_stop;
1395   guint32 seqnum;
1396
1397   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1398
1399   gst_event_parse_seek (event, &rate, &format, &flags,
1400       &cur_type, &cur, &stop_type, &stop);
1401   seqnum = gst_event_get_seqnum (event);
1402
1403   /* only forward streaming and seeking is possible */
1404   if (rate <= 0)
1405     goto unsupported_seek;
1406
1407   /* convert to TIME if needed and possible */
1408   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1409           stop_type, &stop))
1410     goto no_format;
1411
1412   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1413    * the original stop position to use when upstream pushes the new segment
1414    * for this seek */
1415   original_stop = stop;
1416   stop = -1;
1417
1418   /* find reasonable corresponding BYTE position,
1419    * also try to mind about keyframes, since we can not go back a bit for them
1420    * later on */
1421   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1422
1423   if (byte_cur == -1)
1424     goto abort_seek;
1425
1426   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1427       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1428       stop);
1429
1430   GST_OBJECT_LOCK (qtdemux);
1431   qtdemux->seek_offset = byte_cur;
1432   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1433     qtdemux->push_seek_start = cur;
1434   } else {
1435     qtdemux->push_seek_start = key_cur;
1436   }
1437
1438   if (stop_type == GST_SEEK_TYPE_NONE) {
1439     qtdemux->push_seek_stop = qtdemux->segment.stop;
1440   } else {
1441     qtdemux->push_seek_stop = original_stop;
1442   }
1443   GST_OBJECT_UNLOCK (qtdemux);
1444
1445   /* BYTE seek event */
1446   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1447       stop_type, stop);
1448   gst_event_set_seqnum (event, seqnum);
1449   res = gst_pad_push_event (qtdemux->sinkpad, event);
1450
1451   return res;
1452
1453   /* ERRORS */
1454 abort_seek:
1455   {
1456     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1457         "seek aborted.");
1458     return FALSE;
1459   }
1460 unsupported_seek:
1461   {
1462     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1463     return FALSE;
1464   }
1465 no_format:
1466   {
1467     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1468     return FALSE;
1469   }
1470 }
1471
1472 /* perform the seek.
1473  *
1474  * We set all segment_indexes in the streams to unknown and
1475  * adjust the time_position to the desired position. this is enough
1476  * to trigger a segment switch in the streaming thread to start
1477  * streaming from the desired position.
1478  *
1479  * Keyframe seeking is a little more complicated when dealing with
1480  * segments. Ideally we want to move to the previous keyframe in
1481  * the segment but there might not be a keyframe in the segment. In
1482  * fact, none of the segments could contain a keyframe. We take a
1483  * practical approach: seek to the previous keyframe in the segment,
1484  * if there is none, seek to the beginning of the segment.
1485  *
1486  * Called with STREAM_LOCK
1487  */
1488 static gboolean
1489 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1490     guint32 seqnum, GstSeekFlags flags)
1491 {
1492   gint64 desired_offset;
1493   gint n;
1494
1495   desired_offset = segment->position;
1496
1497   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1498       GST_TIME_ARGS (desired_offset));
1499
1500   /* may not have enough fragmented info to do this adjustment,
1501    * and we can't scan (and probably should not) at this time with
1502    * possibly flushing upstream */
1503   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1504     gint64 min_offset;
1505
1506     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1507     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1508         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1509     desired_offset = min_offset;
1510   }
1511
1512   /* and set all streams to the final position */
1513   gst_flow_combiner_reset (qtdemux->flowcombiner);
1514   qtdemux->segment_seqnum = seqnum;
1515   for (n = 0; n < qtdemux->n_streams; n++) {
1516     QtDemuxStream *stream = qtdemux->streams[n];
1517
1518     stream->time_position = desired_offset;
1519     stream->accumulated_base = 0;
1520     stream->sample_index = -1;
1521     stream->offset_in_sample = 0;
1522     stream->segment_index = -1;
1523     stream->sent_eos = FALSE;
1524
1525     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1526       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1527   }
1528   segment->position = desired_offset;
1529   segment->time = desired_offset;
1530   if (segment->rate >= 0) {
1531     segment->start = desired_offset;
1532
1533     /* we stop at the end */
1534     if (segment->stop == -1)
1535       segment->stop = segment->duration;
1536   } else {
1537     segment->stop = desired_offset;
1538   }
1539
1540   if (qtdemux->fragmented)
1541     qtdemux->fragmented_seek_pending = TRUE;
1542
1543   return TRUE;
1544 }
1545
1546 /* do a seek in pull based mode */
1547 static gboolean
1548 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1549 {
1550   gdouble rate;
1551   GstFormat format;
1552   GstSeekFlags flags;
1553   GstSeekType cur_type, stop_type;
1554   gint64 cur, stop;
1555   gboolean flush;
1556   gboolean update;
1557   GstSegment seeksegment;
1558   guint32 seqnum = 0;
1559   GstEvent *flush_event;
1560
1561   if (event) {
1562     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1563
1564     gst_event_parse_seek (event, &rate, &format, &flags,
1565         &cur_type, &cur, &stop_type, &stop);
1566     seqnum = gst_event_get_seqnum (event);
1567
1568     /* we have to have a format as the segment format. Try to convert
1569      * if not. */
1570     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1571             stop_type, &stop))
1572       goto no_format;
1573
1574     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1575   } else {
1576     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1577     flags = 0;
1578   }
1579
1580   flush = flags & GST_SEEK_FLAG_FLUSH;
1581
1582   /* stop streaming, either by flushing or by pausing the task */
1583   if (flush) {
1584     flush_event = gst_event_new_flush_start ();
1585     if (seqnum)
1586       gst_event_set_seqnum (flush_event, seqnum);
1587     /* unlock upstream pull_range */
1588     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1589     /* make sure out loop function exits */
1590     gst_qtdemux_push_event (qtdemux, flush_event);
1591   } else {
1592     /* non flushing seek, pause the task */
1593     gst_pad_pause_task (qtdemux->sinkpad);
1594   }
1595
1596   /* wait for streaming to finish */
1597   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1598
1599   /* copy segment, we need this because we still need the old
1600    * segment when we close the current segment. */
1601   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1602
1603   if (event) {
1604     /* configure the segment with the seek variables */
1605     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1606     gst_segment_do_seek (&seeksegment, rate, format, flags,
1607         cur_type, cur, stop_type, stop, &update);
1608   }
1609
1610   /* now do the seek, this actually never returns FALSE */
1611   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1612
1613   /* prepare for streaming again */
1614   if (flush) {
1615     flush_event = gst_event_new_flush_stop (TRUE);
1616     if (seqnum)
1617       gst_event_set_seqnum (flush_event, seqnum);
1618
1619     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1620     gst_qtdemux_push_event (qtdemux, flush_event);
1621   }
1622
1623   /* commit the new segment */
1624   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1625
1626   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1627     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1628         qtdemux->segment.format, qtdemux->segment.position);
1629     if (seqnum)
1630       gst_message_set_seqnum (msg, seqnum);
1631     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1632   }
1633
1634   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1635   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1636       qtdemux->sinkpad, NULL);
1637
1638   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1639
1640   return TRUE;
1641
1642   /* ERRORS */
1643 no_format:
1644   {
1645     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1646     return FALSE;
1647   }
1648 }
1649
1650 static gboolean
1651 qtdemux_ensure_index (GstQTDemux * qtdemux)
1652 {
1653   guint i;
1654
1655   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1656
1657   /* Build complete index */
1658   for (i = 0; i < qtdemux->n_streams; i++) {
1659     QtDemuxStream *stream = qtdemux->streams[i];
1660
1661     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1662       goto parse_error;
1663   }
1664   return TRUE;
1665
1666   /* ERRORS */
1667 parse_error:
1668   {
1669     GST_LOG_OBJECT (qtdemux,
1670         "Building complete index of stream %u for seeking failed!", i);
1671     return FALSE;
1672   }
1673 }
1674
1675 static gboolean
1676 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1677     GstEvent * event)
1678 {
1679   gboolean res = TRUE;
1680   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1681
1682   switch (GST_EVENT_TYPE (event)) {
1683     case GST_EVENT_SEEK:
1684     {
1685 #ifndef GST_DISABLE_GST_DEBUG
1686       GstClockTime ts = gst_util_get_timestamp ();
1687 #endif
1688
1689       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1690         /* seek should be handled by upstream, we might need to re-download fragments */
1691         GST_DEBUG_OBJECT (qtdemux,
1692             "let upstream handle seek for fragmented playback");
1693         goto upstream;
1694       }
1695
1696       /* Build complete index for seeking;
1697        * if not a fragmented file at least */
1698       if (!qtdemux->fragmented)
1699         if (!qtdemux_ensure_index (qtdemux))
1700           goto index_failed;
1701 #ifndef GST_DISABLE_GST_DEBUG
1702       ts = gst_util_get_timestamp () - ts;
1703       GST_INFO_OBJECT (qtdemux,
1704           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1705 #endif
1706     }
1707       if (qtdemux->pullbased) {
1708         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1709       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1710         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1711         res = TRUE;
1712       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1713           && !qtdemux->fragmented) {
1714         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1715       } else {
1716         GST_DEBUG_OBJECT (qtdemux,
1717             "ignoring seek in push mode in current state");
1718         res = FALSE;
1719       }
1720       gst_event_unref (event);
1721       break;
1722     case GST_EVENT_QOS:
1723     case GST_EVENT_NAVIGATION:
1724       res = FALSE;
1725       gst_event_unref (event);
1726       break;
1727     default:
1728     upstream:
1729       res = gst_pad_event_default (pad, parent, event);
1730       break;
1731   }
1732
1733 done:
1734   return res;
1735
1736   /* ERRORS */
1737 index_failed:
1738   {
1739     GST_ERROR_OBJECT (qtdemux, "Index failed");
1740     gst_event_unref (event);
1741     res = FALSE;
1742     goto done;
1743   }
1744 }
1745
1746 /* stream/index return sample that is min/max w.r.t. byte position,
1747  * time is min/max w.r.t. time of samples,
1748  * the latter need not be time of the former sample */
1749 static void
1750 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1751     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1752 {
1753   gint i, n, index;
1754   gint64 time, min_time;
1755   QtDemuxStream *stream;
1756
1757   min_time = -1;
1758   stream = NULL;
1759   index = -1;
1760
1761   for (n = 0; n < qtdemux->n_streams; ++n) {
1762     QtDemuxStream *str;
1763     gint inc;
1764     gboolean set_sample;
1765
1766     str = qtdemux->streams[n];
1767     set_sample = !set;
1768
1769     if (fw) {
1770       i = 0;
1771       inc = 1;
1772     } else {
1773       i = str->n_samples - 1;
1774       inc = -1;
1775     }
1776
1777     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1778       if (str->samples[i].size == 0)
1779         continue;
1780
1781       if (fw && (str->samples[i].offset < byte_pos))
1782         continue;
1783
1784       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1785         continue;
1786
1787       /* move stream to first available sample */
1788       if (set) {
1789         gst_qtdemux_move_stream (qtdemux, str, i);
1790         set_sample = TRUE;
1791       }
1792
1793       /* avoid index from sparse streams since they might be far away */
1794       if (!str->sparse) {
1795         /* determine min/max time */
1796         time = QTSAMPLE_PTS (str, &str->samples[i]);
1797         if (min_time == -1 || (!fw && time > min_time) ||
1798             (fw && time < min_time)) {
1799           min_time = time;
1800         }
1801
1802         /* determine stream with leading sample, to get its position */
1803         if (!stream ||
1804             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1805             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1806           stream = str;
1807           index = i;
1808         }
1809       }
1810       break;
1811     }
1812
1813     /* no sample for this stream, mark eos */
1814     if (!set_sample)
1815       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1816   }
1817
1818   if (_time)
1819     *_time = min_time;
1820   if (_stream)
1821     *_stream = stream;
1822   if (_index)
1823     *_index = index;
1824 }
1825
1826 static QtDemuxStream *
1827 _create_stream (void)
1828 {
1829   QtDemuxStream *stream;
1830
1831   stream = g_new0 (QtDemuxStream, 1);
1832   /* new streams always need a discont */
1833   stream->discont = TRUE;
1834   /* we enable clipping for raw audio/video streams */
1835   stream->need_clip = FALSE;
1836   stream->need_process = FALSE;
1837   stream->segment_index = -1;
1838   stream->time_position = 0;
1839   stream->sample_index = -1;
1840   stream->offset_in_sample = 0;
1841   stream->new_stream = TRUE;
1842   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1843   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1844   stream->protected = FALSE;
1845   stream->protection_scheme_type = 0;
1846   stream->protection_scheme_version = 0;
1847   stream->protection_scheme_info = NULL;
1848   stream->n_samples_moof = 0;
1849   stream->duration_moof = 0;
1850   g_queue_init (&stream->protection_scheme_event_queue);
1851   return stream;
1852 }
1853
1854 static gboolean
1855 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1856 {
1857   GstStructure *structure;
1858   const gchar *variant;
1859   const GstCaps *mediacaps = NULL;
1860
1861   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1862
1863   structure = gst_caps_get_structure (caps, 0);
1864   variant = gst_structure_get_string (structure, "variant");
1865
1866   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1867     QtDemuxStream *stream;
1868     const GValue *value;
1869
1870     demux->fragmented = TRUE;
1871     demux->mss_mode = TRUE;
1872
1873     if (demux->n_streams > 1) {
1874       /* can't do this, we can only renegotiate for another mss format */
1875       return FALSE;
1876     }
1877
1878     value = gst_structure_get_value (structure, "media-caps");
1879     /* create stream */
1880     if (value) {
1881       const GValue *timescale_v;
1882
1883       /* TODO update when stream changes during playback */
1884
1885       if (demux->n_streams == 0) {
1886         stream = _create_stream ();
1887         demux->streams[demux->n_streams] = stream;
1888         demux->n_streams = 1;
1889       } else {
1890         stream = demux->streams[0];
1891       }
1892
1893       timescale_v = gst_structure_get_value (structure, "timescale");
1894       if (timescale_v) {
1895         stream->timescale = g_value_get_uint64 (timescale_v);
1896       } else {
1897         /* default mss timescale */
1898         stream->timescale = 10000000;
1899       }
1900       demux->timescale = stream->timescale;
1901
1902       mediacaps = gst_value_get_caps (value);
1903       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1904         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1905             mediacaps);
1906         stream->new_caps = TRUE;
1907       }
1908       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1909       structure = gst_caps_get_structure (mediacaps, 0);
1910       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1911         stream->subtype = FOURCC_vide;
1912
1913         gst_structure_get_int (structure, "width", &stream->width);
1914         gst_structure_get_int (structure, "height", &stream->height);
1915         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1916             &stream->fps_d);
1917       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1918         gint rate = 0;
1919         stream->subtype = FOURCC_soun;
1920         gst_structure_get_int (structure, "channels", &stream->n_channels);
1921         gst_structure_get_int (structure, "rate", &rate);
1922         stream->rate = rate;
1923       }
1924     }
1925     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1926   } else {
1927     demux->mss_mode = FALSE;
1928   }
1929
1930   return TRUE;
1931 }
1932
1933 static void
1934 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1935 {
1936   gint n;
1937
1938   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1939   gst_pad_stop_task (qtdemux->sinkpad);
1940
1941   if (hard || qtdemux->upstream_format_is_time) {
1942     qtdemux->state = QTDEMUX_STATE_INITIAL;
1943     qtdemux->neededbytes = 16;
1944     qtdemux->todrop = 0;
1945     qtdemux->pullbased = FALSE;
1946     qtdemux->posted_redirect = FALSE;
1947     qtdemux->first_mdat = -1;
1948     qtdemux->header_size = 0;
1949     qtdemux->mdatoffset = -1;
1950     qtdemux->restoredata_offset = -1;
1951     if (qtdemux->mdatbuffer)
1952       gst_buffer_unref (qtdemux->mdatbuffer);
1953     if (qtdemux->restoredata_buffer)
1954       gst_buffer_unref (qtdemux->restoredata_buffer);
1955     qtdemux->mdatbuffer = NULL;
1956     qtdemux->restoredata_buffer = NULL;
1957     qtdemux->mdatleft = 0;
1958     if (qtdemux->comp_brands)
1959       gst_buffer_unref (qtdemux->comp_brands);
1960     qtdemux->comp_brands = NULL;
1961     qtdemux->last_moov_offset = -1;
1962     if (qtdemux->moov_node)
1963       g_node_destroy (qtdemux->moov_node);
1964     qtdemux->moov_node = NULL;
1965     qtdemux->moov_node_compressed = NULL;
1966     if (qtdemux->tag_list)
1967       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1968     qtdemux->tag_list = NULL;
1969 #if 0
1970     if (qtdemux->element_index)
1971       gst_object_unref (qtdemux->element_index);
1972     qtdemux->element_index = NULL;
1973 #endif
1974     qtdemux->major_brand = 0;
1975     if (qtdemux->pending_newsegment)
1976       gst_event_unref (qtdemux->pending_newsegment);
1977     qtdemux->pending_newsegment = NULL;
1978     qtdemux->upstream_format_is_time = FALSE;
1979     qtdemux->upstream_seekable = FALSE;
1980     qtdemux->upstream_size = 0;
1981
1982     qtdemux->fragment_start = -1;
1983     qtdemux->fragment_start_offset = -1;
1984     qtdemux->duration = 0;
1985     qtdemux->moof_offset = 0;
1986     qtdemux->chapters_track_id = 0;
1987     qtdemux->have_group_id = FALSE;
1988     qtdemux->group_id = G_MAXUINT;
1989
1990     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1991         NULL);
1992     g_queue_clear (&qtdemux->protection_event_queue);
1993   }
1994   qtdemux->offset = 0;
1995   gst_adapter_clear (qtdemux->adapter);
1996   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1997   qtdemux->segment_seqnum = 0;
1998
1999   if (hard) {
2000     for (n = 0; n < qtdemux->n_streams; n++) {
2001       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2002       qtdemux->streams[n] = NULL;
2003     }
2004     qtdemux->n_streams = 0;
2005     qtdemux->n_video_streams = 0;
2006     qtdemux->n_audio_streams = 0;
2007     qtdemux->n_sub_streams = 0;
2008     qtdemux->exposed = FALSE;
2009     qtdemux->fragmented = FALSE;
2010     qtdemux->mss_mode = FALSE;
2011     gst_caps_replace (&qtdemux->media_caps, NULL);
2012     qtdemux->timescale = 0;
2013     qtdemux->got_moov = FALSE;
2014     if (qtdemux->protection_system_ids) {
2015       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2016       qtdemux->protection_system_ids = NULL;
2017     }
2018   } else if (qtdemux->mss_mode) {
2019     gst_flow_combiner_reset (qtdemux->flowcombiner);
2020     for (n = 0; n < qtdemux->n_streams; n++)
2021       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2022   } else {
2023     gst_flow_combiner_reset (qtdemux->flowcombiner);
2024     for (n = 0; n < qtdemux->n_streams; n++) {
2025       qtdemux->streams[n]->sent_eos = FALSE;
2026       qtdemux->streams[n]->time_position = 0;
2027       qtdemux->streams[n]->accumulated_base = 0;
2028     }
2029     if (!qtdemux->pending_newsegment) {
2030       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2031       if (qtdemux->segment_seqnum)
2032         gst_event_set_seqnum (qtdemux->pending_newsegment,
2033             qtdemux->segment_seqnum);
2034     }
2035   }
2036 }
2037
2038
2039 /* Maps the @segment to the qt edts internal segments and pushes
2040  * the correspnding segment event.
2041  *
2042  * If it ends up being at a empty segment, a gap will be pushed and the next
2043  * edts segment will be activated in sequence.
2044  *
2045  * To be used in push-mode only */
2046 static void
2047 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2048 {
2049   gint n, i;
2050
2051   for (n = 0; n < qtdemux->n_streams; n++) {
2052     QtDemuxStream *stream = qtdemux->streams[n];
2053
2054     stream->time_position = segment->start;
2055
2056     /* in push mode we should be guaranteed that we will have empty segments
2057      * at the beginning and then one segment after, other scenarios are not
2058      * supported and are discarded when parsing the edts */
2059     for (i = 0; i < stream->n_segments; i++) {
2060       if (stream->segments[i].stop_time > segment->start) {
2061         gst_qtdemux_activate_segment (qtdemux, stream, i,
2062             stream->time_position);
2063         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2064           /* push the empty segment and move to the next one */
2065           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2066               stream->time_position);
2067           continue;
2068         }
2069
2070         g_assert (i == stream->n_segments - 1);
2071       }
2072     }
2073   }
2074 }
2075
2076 static gboolean
2077 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2078     GstEvent * event)
2079 {
2080   GstQTDemux *demux = GST_QTDEMUX (parent);
2081   gboolean res = TRUE;
2082
2083   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2084
2085   switch (GST_EVENT_TYPE (event)) {
2086     case GST_EVENT_SEGMENT:
2087     {
2088       gint64 offset = 0;
2089       QtDemuxStream *stream;
2090       gint idx;
2091       GstSegment segment;
2092
2093       /* some debug output */
2094       gst_event_copy_segment (event, &segment);
2095       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2096           &segment);
2097
2098       /* erase any previously set segment */
2099       gst_event_replace (&demux->pending_newsegment, NULL);
2100
2101       if (segment.format == GST_FORMAT_TIME) {
2102         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2103         gst_event_replace (&demux->pending_newsegment, event);
2104         demux->upstream_format_is_time = TRUE;
2105       } else {
2106         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2107             "not in time format");
2108
2109         /* chain will send initial newsegment after pads have been added */
2110         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2111           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2112           goto exit;
2113         }
2114       }
2115
2116       /* check if this matches a time seek we received previously
2117        * FIXME for backwards compatibility reasons we use the
2118        * seek_offset here to compare. In the future we might want to
2119        * change this to use the seqnum as it uniquely should identify
2120        * the segment that corresponds to the seek. */
2121       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2122           ", received segment offset %" G_GINT64_FORMAT,
2123           demux->seek_offset, segment.start);
2124       if (segment.format == GST_FORMAT_BYTES
2125           && demux->seek_offset == segment.start) {
2126         GST_OBJECT_LOCK (demux);
2127         offset = segment.start;
2128
2129         segment.format = GST_FORMAT_TIME;
2130         segment.start = demux->push_seek_start;
2131         segment.stop = demux->push_seek_stop;
2132         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2133             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2134             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2135         GST_OBJECT_UNLOCK (demux);
2136       }
2137
2138       /* we only expect a BYTE segment, e.g. following a seek */
2139       if (segment.format == GST_FORMAT_BYTES) {
2140         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2141           offset = segment.start;
2142
2143           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2144               NULL, (gint64 *) & segment.start);
2145           if ((gint64) segment.start < 0)
2146             segment.start = 0;
2147         }
2148         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2149           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2150               NULL, (gint64 *) & segment.stop);
2151           /* keyframe seeking should already arrange for start >= stop,
2152            * but make sure in other rare cases */
2153           segment.stop = MAX (segment.stop, segment.start);
2154         }
2155       } else if (segment.format == GST_FORMAT_TIME) {
2156         /* push all data on the adapter before starting this
2157          * new segment */
2158         gst_qtdemux_process_adapter (demux, TRUE);
2159       } else {
2160         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2161         goto exit;
2162       }
2163
2164       /* accept upstream's notion of segment and distribute along */
2165       segment.format = GST_FORMAT_TIME;
2166       segment.position = segment.time = segment.start;
2167       segment.duration = demux->segment.duration;
2168       segment.base = gst_segment_to_running_time (&demux->segment,
2169           GST_FORMAT_TIME, demux->segment.position);
2170
2171       gst_segment_copy_into (&segment, &demux->segment);
2172       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2173
2174       /* map segment to internal qt segments and push on each stream */
2175       if (demux->n_streams) {
2176         if (demux->fragmented) {
2177           GstEvent *segment_event = gst_event_new_segment (&segment);
2178
2179           gst_event_replace (&demux->pending_newsegment, NULL);
2180           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2181           gst_qtdemux_push_event (demux, segment_event);
2182         } else {
2183           gst_event_replace (&demux->pending_newsegment, NULL);
2184           gst_qtdemux_map_and_push_segments (demux, &segment);
2185         }
2186       }
2187
2188       /* clear leftover in current segment, if any */
2189       gst_adapter_clear (demux->adapter);
2190
2191       /* set up streaming thread */
2192       demux->offset = offset;
2193       if (demux->upstream_format_is_time) {
2194         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2195             "set values to restart reading from a new atom");
2196         demux->neededbytes = 16;
2197         demux->todrop = 0;
2198       } else {
2199         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2200             NULL);
2201         if (stream) {
2202           demux->todrop = stream->samples[idx].offset - offset;
2203           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2204         } else {
2205           /* set up for EOS */
2206           demux->neededbytes = -1;
2207           demux->todrop = 0;
2208         }
2209       }
2210     exit:
2211       gst_event_unref (event);
2212       res = TRUE;
2213       goto drop;
2214     }
2215     case GST_EVENT_FLUSH_START:
2216     {
2217       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2218         gst_event_unref (event);
2219         goto drop;
2220       }
2221       break;
2222     }
2223     case GST_EVENT_FLUSH_STOP:
2224     {
2225       guint64 dur;
2226
2227       dur = demux->segment.duration;
2228       gst_qtdemux_reset (demux, FALSE);
2229       demux->segment.duration = dur;
2230
2231       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2232         gst_event_unref (event);
2233         goto drop;
2234       }
2235       break;
2236     }
2237     case GST_EVENT_EOS:
2238       /* If we are in push mode, and get an EOS before we've seen any streams,
2239        * then error out - we have nowhere to send the EOS */
2240       if (!demux->pullbased) {
2241         gint i;
2242         gboolean has_valid_stream = FALSE;
2243         for (i = 0; i < demux->n_streams; i++) {
2244           if (demux->streams[i]->pad != NULL) {
2245             has_valid_stream = TRUE;
2246             break;
2247           }
2248         }
2249         if (!has_valid_stream)
2250           gst_qtdemux_post_no_playable_stream_error (demux);
2251         else {
2252           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2253               (guint) gst_adapter_available (demux->adapter));
2254           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2255             res = FALSE;
2256           }
2257         }
2258       }
2259       break;
2260     case GST_EVENT_CAPS:{
2261       GstCaps *caps = NULL;
2262
2263       gst_event_parse_caps (event, &caps);
2264       gst_qtdemux_setcaps (demux, caps);
2265       res = TRUE;
2266       gst_event_unref (event);
2267       goto drop;
2268     }
2269     case GST_EVENT_PROTECTION:
2270     {
2271       const gchar *system_id = NULL;
2272
2273       gst_event_parse_protection (event, &system_id, NULL, NULL);
2274       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2275           system_id);
2276       gst_qtdemux_append_protection_system_id (demux, system_id);
2277       /* save the event for later, for source pads that have not been created */
2278       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2279       /* send it to all pads that already exist */
2280       gst_qtdemux_push_event (demux, event);
2281       res = TRUE;
2282       goto drop;
2283     }
2284     default:
2285       break;
2286   }
2287
2288   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2289
2290 drop:
2291   return res;
2292 }
2293
2294 #if 0
2295 static void
2296 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2297 {
2298   GstQTDemux *demux = GST_QTDEMUX (element);
2299
2300   GST_OBJECT_LOCK (demux);
2301   if (demux->element_index)
2302     gst_object_unref (demux->element_index);
2303   if (index) {
2304     demux->element_index = gst_object_ref (index);
2305   } else {
2306     demux->element_index = NULL;
2307   }
2308   GST_OBJECT_UNLOCK (demux);
2309   /* object lock might be taken again */
2310   if (index)
2311     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2312   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2313       demux->element_index, demux->index_id);
2314 }
2315
2316 static GstIndex *
2317 gst_qtdemux_get_index (GstElement * element)
2318 {
2319   GstIndex *result = NULL;
2320   GstQTDemux *demux = GST_QTDEMUX (element);
2321
2322   GST_OBJECT_LOCK (demux);
2323   if (demux->element_index)
2324     result = gst_object_ref (demux->element_index);
2325   GST_OBJECT_UNLOCK (demux);
2326
2327   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2328
2329   return result;
2330 }
2331 #endif
2332
2333 static void
2334 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2335 {
2336   g_free ((gpointer) stream->stco.data);
2337   stream->stco.data = NULL;
2338   g_free ((gpointer) stream->stsz.data);
2339   stream->stsz.data = NULL;
2340   g_free ((gpointer) stream->stsc.data);
2341   stream->stsc.data = NULL;
2342   g_free ((gpointer) stream->stts.data);
2343   stream->stts.data = NULL;
2344   g_free ((gpointer) stream->stss.data);
2345   stream->stss.data = NULL;
2346   g_free ((gpointer) stream->stps.data);
2347   stream->stps.data = NULL;
2348   g_free ((gpointer) stream->ctts.data);
2349   stream->ctts.data = NULL;
2350 }
2351
2352 static void
2353 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2354     QtDemuxStream * stream)
2355 {
2356   g_free (stream->segments);
2357   stream->segments = NULL;
2358   stream->segment_index = -1;
2359   stream->accumulated_base = 0;
2360 }
2361
2362 static void
2363 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2364     QtDemuxStream * stream)
2365 {
2366   g_free (stream->samples);
2367   stream->samples = NULL;
2368   gst_qtdemux_stbl_free (stream);
2369
2370   /* fragments */
2371   g_free (stream->ra_entries);
2372   stream->ra_entries = NULL;
2373   stream->n_ra_entries = 0;
2374
2375   stream->sample_index = -1;
2376   stream->stbl_index = -1;
2377   stream->n_samples = 0;
2378   stream->time_position = 0;
2379
2380   stream->n_samples_moof = 0;
2381   stream->duration_moof = 0;
2382 }
2383
2384 static void
2385 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2386 {
2387   if (stream->allocator)
2388     gst_object_unref (stream->allocator);
2389   while (stream->buffers) {
2390     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2391     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2392   }
2393   if (stream->rgb8_palette) {
2394     gst_memory_unref (stream->rgb8_palette);
2395     stream->rgb8_palette = NULL;
2396   }
2397
2398   if (stream->pending_tags)
2399     gst_tag_list_unref (stream->pending_tags);
2400   stream->pending_tags = NULL;
2401   g_free (stream->redirect_uri);
2402   stream->redirect_uri = NULL;
2403   stream->sent_eos = FALSE;
2404   stream->sparse = FALSE;
2405   stream->protected = FALSE;
2406   if (stream->protection_scheme_info) {
2407     if (stream->protection_scheme_type == FOURCC_cenc) {
2408       QtDemuxCencSampleSetInfo *info =
2409           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2410       if (info->default_properties)
2411         gst_structure_free (info->default_properties);
2412       if (info->crypto_info)
2413         g_ptr_array_free (info->crypto_info, TRUE);
2414     }
2415     g_free (stream->protection_scheme_info);
2416     stream->protection_scheme_info = NULL;
2417   }
2418   stream->protection_scheme_type = 0;
2419   stream->protection_scheme_version = 0;
2420   g_queue_foreach (&stream->protection_scheme_event_queue,
2421       (GFunc) gst_event_unref, NULL);
2422   g_queue_clear (&stream->protection_scheme_event_queue);
2423   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2424   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2425 }
2426
2427 static void
2428 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2429 {
2430   gst_qtdemux_stream_clear (qtdemux, stream);
2431   if (stream->caps)
2432     gst_caps_unref (stream->caps);
2433   stream->caps = NULL;
2434   if (stream->pad) {
2435     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2436     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2437   }
2438   g_free (stream);
2439 }
2440
2441 static void
2442 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2443 {
2444   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2445
2446   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2447   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2448   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2449   qtdemux->n_streams--;
2450 }
2451
2452 static GstStateChangeReturn
2453 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2454 {
2455   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2456   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2457
2458   switch (transition) {
2459     case GST_STATE_CHANGE_PAUSED_TO_READY:
2460       break;
2461     default:
2462       break;
2463   }
2464
2465   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2466
2467   switch (transition) {
2468     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2469       gst_qtdemux_reset (qtdemux, TRUE);
2470       break;
2471     }
2472     default:
2473       break;
2474   }
2475
2476   return result;
2477 }
2478
2479 static void
2480 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2481 {
2482   /* counts as header data */
2483   qtdemux->header_size += length;
2484
2485   /* only consider at least a sufficiently complete ftyp atom */
2486   if (length >= 20) {
2487     GstBuffer *buf;
2488
2489     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2490     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2491         GST_FOURCC_ARGS (qtdemux->major_brand));
2492     if (qtdemux->comp_brands)
2493       gst_buffer_unref (qtdemux->comp_brands);
2494     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2495     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2496   }
2497 }
2498
2499 static void
2500 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2501     GstTagList * xmptaglist)
2502 {
2503   /* Strip out bogus fields */
2504   if (xmptaglist) {
2505     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2506       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2507       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2508     } else {
2509       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2510     }
2511
2512     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2513
2514     /* prioritize native tags using _KEEP mode */
2515     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2516     gst_tag_list_unref (xmptaglist);
2517   }
2518 }
2519
2520 static void
2521 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2522     guint offset)
2523 {
2524   GstByteReader br;
2525   guint8 version;
2526   guint32 flags = 0;
2527   guint i;
2528   guint8 iv_size = 8;
2529   QtDemuxStream *stream;
2530   GstStructure *structure;
2531   QtDemuxCencSampleSetInfo *ss_info = NULL;
2532   const gchar *system_id;
2533   gboolean uses_sub_sample_encryption = FALSE;
2534
2535   if (qtdemux->n_streams == 0)
2536     return;
2537
2538   stream = qtdemux->streams[0];
2539
2540   structure = gst_caps_get_structure (stream->caps, 0);
2541   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2542     GST_WARNING_OBJECT (qtdemux,
2543         "Attempting PIFF box parsing on an unencrypted stream.");
2544     return;
2545   }
2546
2547   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2548       G_TYPE_STRING, &system_id, NULL);
2549   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2550
2551   stream->protected = TRUE;
2552   stream->protection_scheme_type = FOURCC_cenc;
2553
2554   if (!stream->protection_scheme_info)
2555     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2556
2557   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2558
2559   if (ss_info->default_properties)
2560     gst_structure_free (ss_info->default_properties);
2561
2562   ss_info->default_properties =
2563       gst_structure_new ("application/x-cenc",
2564       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2565
2566   if (ss_info->crypto_info) {
2567     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2568     g_ptr_array_free (ss_info->crypto_info, TRUE);
2569     ss_info->crypto_info = NULL;
2570   }
2571
2572   /* skip UUID */
2573   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2574
2575   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2576     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2577     return;
2578   }
2579
2580   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2581     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2582     return;
2583   }
2584
2585   if ((flags & 0x000001)) {
2586     guint32 algorithm_id = 0;
2587     const guint8 *kid;
2588     GstBuffer *kid_buf;
2589     gboolean is_encrypted = TRUE;
2590
2591     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2592       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2593       return;
2594     }
2595
2596     algorithm_id >>= 8;
2597     if (algorithm_id == 0) {
2598       is_encrypted = FALSE;
2599     } else if (algorithm_id == 1) {
2600       /* FIXME: maybe store this in properties? */
2601       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2602     } else if (algorithm_id == 2) {
2603       /* FIXME: maybe store this in properties? */
2604       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2605     }
2606
2607     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2608       return;
2609
2610     if (!gst_byte_reader_get_data (&br, 16, &kid))
2611       return;
2612
2613     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2614     gst_buffer_fill (kid_buf, 0, kid, 16);
2615     if (ss_info->default_properties)
2616       gst_structure_free (ss_info->default_properties);
2617     ss_info->default_properties =
2618         gst_structure_new ("application/x-cenc",
2619         "iv_size", G_TYPE_UINT, iv_size,
2620         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2621         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2622     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2623         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2624     gst_buffer_unref (kid_buf);
2625   } else if ((flags & 0x000002)) {
2626     uses_sub_sample_encryption = TRUE;
2627   }
2628
2629   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2630     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2631     return;
2632   }
2633
2634   ss_info->crypto_info =
2635       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2636       (GDestroyNotify) qtdemux_gst_structure_free);
2637
2638   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2639     GstStructure *properties;
2640     guint8 *data;
2641     GstBuffer *buf;
2642
2643     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2644     if (properties == NULL) {
2645       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2646       return;
2647     }
2648
2649     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2650       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2651       gst_structure_free (properties);
2652       return;
2653     }
2654     buf = gst_buffer_new_wrapped (data, iv_size);
2655     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2656     gst_buffer_unref (buf);
2657
2658     if (uses_sub_sample_encryption) {
2659       guint16 n_subsamples;
2660
2661       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2662           || n_subsamples == 0) {
2663         GST_ERROR_OBJECT (qtdemux,
2664             "failed to get subsample count for sample %u", i);
2665         gst_structure_free (properties);
2666         return;
2667       }
2668       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2669       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2670         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2671             i);
2672         gst_structure_free (properties);
2673         return;
2674       }
2675       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2676       gst_structure_set (properties,
2677           "subsample_count", G_TYPE_UINT, n_subsamples,
2678           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2679       gst_buffer_unref (buf);
2680     } else {
2681       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2682     }
2683
2684     g_ptr_array_add (ss_info->crypto_info, properties);
2685   }
2686 }
2687
2688 static void
2689 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2690 {
2691   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2692     0x97, 0xA9, 0x42, 0xE8,
2693     0x9C, 0x71, 0x99, 0x94,
2694     0x91, 0xE3, 0xAF, 0xAC
2695   };
2696   static const guint8 playready_uuid[] = {
2697     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2698     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2699   };
2700
2701   static const guint8 piff_sample_encryption_uuid[] = {
2702     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2703     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2704   };
2705
2706   guint offset;
2707
2708   /* counts as header data */
2709   qtdemux->header_size += length;
2710
2711   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2712
2713   if (length <= offset + 16) {
2714     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2715     return;
2716   }
2717
2718   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2719     GstBuffer *buf;
2720     GstTagList *taglist;
2721
2722     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2723         length - offset - 16, NULL);
2724     taglist = gst_tag_list_from_xmp_buffer (buf);
2725     gst_buffer_unref (buf);
2726
2727     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2728
2729   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2730     int len;
2731     const gunichar2 *s_utf16;
2732     char *contents;
2733
2734     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2735     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2736     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2737     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2738
2739     g_free (contents);
2740
2741     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2742         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2743         (NULL));
2744   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2745     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2746   } else {
2747     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2748         GST_READ_UINT32_LE (buffer + offset),
2749         GST_READ_UINT32_LE (buffer + offset + 4),
2750         GST_READ_UINT32_LE (buffer + offset + 8),
2751         GST_READ_UINT32_LE (buffer + offset + 12));
2752   }
2753 }
2754
2755 static void
2756 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2757 {
2758   GstSidxParser sidx_parser;
2759   GstIsoffParserResult res;
2760   guint consumed;
2761
2762   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2763
2764   res =
2765       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2766       &consumed);
2767   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2768   if (res == GST_ISOFF_QT_PARSER_DONE) {
2769     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2770   }
2771   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2772 }
2773
2774 /* caller verifies at least 8 bytes in buf */
2775 static void
2776 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2777     guint64 * plength, guint32 * pfourcc)
2778 {
2779   guint64 length;
2780   guint32 fourcc;
2781
2782   length = QT_UINT32 (data);
2783   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2784   fourcc = QT_FOURCC (data + 4);
2785   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2786
2787   if (length == 0) {
2788     length = G_MAXUINT64;
2789   } else if (length == 1 && size >= 16) {
2790     /* this means we have an extended size, which is the 64 bit value of
2791      * the next 8 bytes */
2792     length = QT_UINT64 (data + 8);
2793     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2794   }
2795
2796   if (plength)
2797     *plength = length;
2798   if (pfourcc)
2799     *pfourcc = fourcc;
2800 }
2801
2802 static gboolean
2803 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2804 {
2805   guint32 version = 0;
2806   GstClockTime duration = 0;
2807
2808   if (!gst_byte_reader_get_uint32_be (br, &version))
2809     goto failed;
2810
2811   version >>= 24;
2812   if (version == 1) {
2813     if (!gst_byte_reader_get_uint64_be (br, &duration))
2814       goto failed;
2815   } else {
2816     guint32 dur = 0;
2817
2818     if (!gst_byte_reader_get_uint32_be (br, &dur))
2819       goto failed;
2820     duration = dur;
2821   }
2822
2823   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2824   qtdemux->duration = duration;
2825
2826   return TRUE;
2827
2828 failed:
2829   {
2830     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2831     return FALSE;
2832   }
2833 }
2834
2835 static gboolean
2836 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2837     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2838 {
2839   if (!stream->parsed_trex && qtdemux->moov_node) {
2840     GNode *mvex, *trex;
2841     GstByteReader trex_data;
2842
2843     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2844     if (mvex) {
2845       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2846           &trex_data);
2847       while (trex) {
2848         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2849
2850         /* skip version/flags */
2851         if (!gst_byte_reader_skip (&trex_data, 4))
2852           goto next;
2853         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2854           goto next;
2855         if (id != stream->track_id)
2856           goto next;
2857         /* sample description index; ignore */
2858         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2859           goto next;
2860         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2861           goto next;
2862         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2863           goto next;
2864         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2865           goto next;
2866
2867         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2868             "duration %d,  size %d, flags 0x%x", stream->track_id,
2869             dur, size, flags);
2870
2871         stream->parsed_trex = TRUE;
2872         stream->def_sample_duration = dur;
2873         stream->def_sample_size = size;
2874         stream->def_sample_flags = flags;
2875
2876       next:
2877         /* iterate all siblings */
2878         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2879             &trex_data);
2880       }
2881     }
2882   }
2883
2884   *ds_duration = stream->def_sample_duration;
2885   *ds_size = stream->def_sample_size;
2886   *ds_flags = stream->def_sample_flags;
2887
2888   /* even then, above values are better than random ... */
2889   if (G_UNLIKELY (!stream->parsed_trex)) {
2890     GST_WARNING_OBJECT (qtdemux,
2891         "failed to find fragment defaults for stream %d", stream->track_id);
2892     return FALSE;
2893   }
2894
2895   return TRUE;
2896 }
2897
2898 /* This method should be called whenever a more accurate duration might
2899  * have been found. It will update all relevant variables if/where needed
2900  */
2901 static void
2902 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2903 {
2904   guint i;
2905   guint64 movdur;
2906   GstClockTime prevdur;
2907
2908   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2909
2910   if (movdur > qtdemux->duration) {
2911     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2912     GST_DEBUG_OBJECT (qtdemux,
2913         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2914         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2915     qtdemux->duration = movdur;
2916     GST_DEBUG_OBJECT (qtdemux,
2917         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2918         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2919         GST_TIME_ARGS (qtdemux->segment.stop));
2920     if (qtdemux->segment.duration == prevdur) {
2921       /* If the current segment has duration/stop identical to previous duration
2922        * update them also (because they were set at that point in time with
2923        * the wrong duration */
2924       /* We convert the value *from* the timescale version to avoid rounding errors */
2925       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2926       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2927       qtdemux->segment.duration = fixeddur;
2928       qtdemux->segment.stop = fixeddur;
2929     }
2930   }
2931   for (i = 0; i < qtdemux->n_streams; i++) {
2932     QtDemuxStream *stream = qtdemux->streams[i];
2933     if (stream) {
2934       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2935       if (movdur > stream->duration) {
2936         GST_DEBUG_OBJECT (qtdemux,
2937             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2938             GST_TIME_ARGS (duration));
2939         stream->duration = movdur;
2940         if (stream->dummy_segment) {
2941           /* Update all dummy values to new duration */
2942           stream->segments[0].stop_time = duration;
2943           stream->segments[0].duration = duration;
2944           stream->segments[0].media_stop = duration;
2945
2946           /* let downstream know we possibly have a new stop time */
2947           if (stream->segment_index != -1) {
2948             GstClockTime pos;
2949
2950             if (qtdemux->segment.rate >= 0) {
2951               pos = stream->segment.start;
2952             } else {
2953               pos = stream->segment.stop;
2954             }
2955
2956             gst_qtdemux_stream_update_segment (qtdemux, stream,
2957                 stream->segment_index, pos, NULL, NULL);
2958           }
2959         }
2960       }
2961     }
2962   }
2963 }
2964
2965 static gboolean
2966 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2967     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2968     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2969     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2970 {
2971   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2972   guint64 timestamp;
2973   gint32 data_offset = 0;
2974   guint32 flags = 0, first_flags = 0, samples_count = 0;
2975   gint i;
2976   guint8 *data;
2977   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2978   QtDemuxSample *sample;
2979   gboolean ismv = FALSE;
2980
2981   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2982       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2983       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2984       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2985
2986   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2987     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2988     return TRUE;
2989   }
2990
2991   /* presence of stss or not can't really tell us much,
2992    * and flags and so on tend to be marginally reliable in these files */
2993   if (stream->subtype == FOURCC_soun) {
2994     GST_DEBUG_OBJECT (qtdemux,
2995         "sound track in fragmented file; marking all keyframes");
2996     stream->all_keyframe = TRUE;
2997   }
2998
2999   if (!gst_byte_reader_skip (trun, 1) ||
3000       !gst_byte_reader_get_uint24_be (trun, &flags))
3001     goto fail;
3002
3003   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3004     goto fail;
3005
3006   if (flags & TR_DATA_OFFSET) {
3007     /* note this is really signed */
3008     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3009       goto fail;
3010     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3011     /* default base offset = first byte of moof */
3012     if (*base_offset == -1) {
3013       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3014       *base_offset = moof_offset;
3015     }
3016     *running_offset = *base_offset + data_offset;
3017   } else {
3018     /* if no offset at all, that would mean data starts at moof start,
3019      * which is a bit wrong and is ismv crappy way, so compensate
3020      * assuming data is in mdat following moof */
3021     if (*base_offset == -1) {
3022       *base_offset = moof_offset + moof_length + 8;
3023       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3024       ismv = TRUE;
3025     }
3026     if (*running_offset == -1)
3027       *running_offset = *base_offset;
3028   }
3029
3030   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3031       *running_offset);
3032   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3033       data_offset, flags, samples_count);
3034
3035   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3036     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3037       GST_DEBUG_OBJECT (qtdemux,
3038           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3039       flags ^= TR_FIRST_SAMPLE_FLAGS;
3040     } else {
3041       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3042         goto fail;
3043       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3044     }
3045   }
3046
3047   /* FIXME ? spec says other bits should also be checked to determine
3048    * entry size (and prefix size for that matter) */
3049   entry_size = 0;
3050   dur_offset = size_offset = 0;
3051   if (flags & TR_SAMPLE_DURATION) {
3052     GST_LOG_OBJECT (qtdemux, "entry duration present");
3053     dur_offset = entry_size;
3054     entry_size += 4;
3055   }
3056   if (flags & TR_SAMPLE_SIZE) {
3057     GST_LOG_OBJECT (qtdemux, "entry size present");
3058     size_offset = entry_size;
3059     entry_size += 4;
3060   }
3061   if (flags & TR_SAMPLE_FLAGS) {
3062     GST_LOG_OBJECT (qtdemux, "entry flags present");
3063     flags_offset = entry_size;
3064     entry_size += 4;
3065   }
3066   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3067     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3068     ct_offset = entry_size;
3069     entry_size += 4;
3070   }
3071
3072   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3073     goto fail;
3074   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3075
3076   if (stream->n_samples + samples_count >=
3077       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3078     goto index_too_big;
3079
3080   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3081       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3082       (stream->n_samples + samples_count) *
3083       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3084
3085   /* create a new array of samples if it's the first sample parsed */
3086   if (stream->n_samples == 0) {
3087     g_assert (stream->samples == NULL);
3088     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3089     /* or try to reallocate it with space enough to insert the new samples */
3090   } else
3091     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3092         stream->n_samples + samples_count);
3093   if (stream->samples == NULL)
3094     goto out_of_memory;
3095
3096   if (qtdemux->fragment_start != -1) {
3097     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3098     qtdemux->fragment_start = -1;
3099   } else {
3100     if (stream->n_samples == 0) {
3101       if (decode_ts > 0) {
3102         timestamp = decode_ts;
3103       } else if (stream->pending_seek != NULL) {
3104         /* if we don't have a timestamp from a tfdt box, we'll use the one
3105          * from the mfra seek table */
3106         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3107             GST_TIME_ARGS (stream->pending_seek->ts));
3108
3109         /* FIXME: this is not fully correct, the timestamp refers to the random
3110          * access sample refered to in the tfra entry, which may not necessarily
3111          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3112         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3113       } else {
3114         timestamp = 0;
3115       }
3116
3117       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3118       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3119           GST_TIME_ARGS (gst_ts));
3120     } else {
3121       /* subsequent fragments extend stream */
3122       timestamp =
3123           stream->samples[stream->n_samples - 1].timestamp +
3124           stream->samples[stream->n_samples - 1].duration;
3125
3126       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3127       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3128           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3129     }
3130   }
3131
3132   sample = stream->samples + stream->n_samples;
3133   for (i = 0; i < samples_count; i++) {
3134     guint32 dur, size, sflags, ct;
3135
3136     /* first read sample data */
3137     if (flags & TR_SAMPLE_DURATION) {
3138       dur = QT_UINT32 (data + dur_offset);
3139     } else {
3140       dur = d_sample_duration;
3141     }
3142     if (flags & TR_SAMPLE_SIZE) {
3143       size = QT_UINT32 (data + size_offset);
3144     } else {
3145       size = d_sample_size;
3146     }
3147     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3148       if (i == 0) {
3149         sflags = first_flags;
3150       } else {
3151         sflags = d_sample_flags;
3152       }
3153     } else if (flags & TR_SAMPLE_FLAGS) {
3154       sflags = QT_UINT32 (data + flags_offset);
3155     } else {
3156       sflags = d_sample_flags;
3157     }
3158     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3159       ct = QT_UINT32 (data + ct_offset);
3160     } else {
3161       ct = 0;
3162     }
3163     data += entry_size;
3164
3165     /* fill the sample information */
3166     sample->offset = *running_offset;
3167     sample->pts_offset = ct;
3168     sample->size = size;
3169     sample->timestamp = timestamp;
3170     sample->duration = dur;
3171     /* sample-is-difference-sample */
3172     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3173      * now idea how it relates to bitfield other than massive LE/BE confusion */
3174     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3175     *running_offset += size;
3176     timestamp += dur;
3177     stream->duration_moof += dur;
3178     sample++;
3179   }
3180
3181   /* Update total duration if needed */
3182   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3183
3184   stream->n_samples += samples_count;
3185   stream->n_samples_moof += samples_count;
3186
3187   if (stream->pending_seek != NULL)
3188     stream->pending_seek = NULL;
3189
3190   return TRUE;
3191
3192 fail:
3193   {
3194     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3195     return FALSE;
3196   }
3197 out_of_memory:
3198   {
3199     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3200         stream->n_samples);
3201     return FALSE;
3202   }
3203 index_too_big:
3204   {
3205     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3206         "be larger than %uMB (broken file?)", stream->n_samples,
3207         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3208     return FALSE;
3209   }
3210 }
3211
3212 /* find stream with @id */
3213 static inline QtDemuxStream *
3214 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3215 {
3216   QtDemuxStream *stream;
3217   gint i;
3218
3219   /* check */
3220   if (G_UNLIKELY (!id)) {
3221     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3222     return NULL;
3223   }
3224
3225   /* try to get it fast and simple */
3226   if (G_LIKELY (id <= qtdemux->n_streams)) {
3227     stream = qtdemux->streams[id - 1];
3228     if (G_LIKELY (stream->track_id == id))
3229       return stream;
3230   }
3231
3232   /* linear search otherwise */
3233   for (i = 0; i < qtdemux->n_streams; i++) {
3234     stream = qtdemux->streams[i];
3235     if (stream->track_id == id)
3236       return stream;
3237   }
3238   if (qtdemux->mss_mode) {
3239     /* mss should have only 1 stream anyway */
3240     return qtdemux->streams[0];
3241   }
3242
3243   return NULL;
3244 }
3245
3246 static gboolean
3247 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3248     guint32 * fragment_number)
3249 {
3250   if (!gst_byte_reader_skip (mfhd, 4))
3251     goto fail;
3252   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3253     goto fail;
3254   return TRUE;
3255 fail:
3256   {
3257     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3258     return FALSE;
3259   }
3260 }
3261
3262 static gboolean
3263 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3264     QtDemuxStream ** stream, guint32 * default_sample_duration,
3265     guint32 * default_sample_size, guint32 * default_sample_flags,
3266     gint64 * base_offset)
3267 {
3268   guint32 flags = 0;
3269   guint32 track_id = 0;
3270
3271   if (!gst_byte_reader_skip (tfhd, 1) ||
3272       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3273     goto invalid_track;
3274
3275   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3276     goto invalid_track;
3277
3278   *stream = qtdemux_find_stream (qtdemux, track_id);
3279   if (G_UNLIKELY (!*stream))
3280     goto unknown_stream;
3281
3282   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3283     *base_offset = qtdemux->moof_offset;
3284
3285   if (flags & TF_BASE_DATA_OFFSET)
3286     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3287       goto invalid_track;
3288
3289   /* obtain stream defaults */
3290   qtdemux_parse_trex (qtdemux, *stream,
3291       default_sample_duration, default_sample_size, default_sample_flags);
3292
3293   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3294   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3295     if (!gst_byte_reader_skip (tfhd, 4))
3296       goto invalid_track;
3297
3298   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3299     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3300       goto invalid_track;
3301
3302   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3303     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3304       goto invalid_track;
3305
3306   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3307     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3308       goto invalid_track;
3309
3310   return TRUE;
3311
3312 invalid_track:
3313   {
3314     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3315     return FALSE;
3316   }
3317 unknown_stream:
3318   {
3319     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3320     return TRUE;
3321   }
3322 }
3323
3324 static gboolean
3325 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3326     guint64 * decode_time)
3327 {
3328   guint32 version = 0;
3329
3330   if (!gst_byte_reader_get_uint32_be (br, &version))
3331     return FALSE;
3332
3333   version >>= 24;
3334   if (version == 1) {
3335     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3336       goto failed;
3337   } else {
3338     guint32 dec_time = 0;
3339     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3340       goto failed;
3341     *decode_time = dec_time;
3342   }
3343
3344   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3345       *decode_time);
3346
3347   return TRUE;
3348
3349 failed:
3350   {
3351     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3352     return FALSE;
3353   }
3354 }
3355
3356 /* Returns a pointer to a GstStructure containing the properties of
3357  * the stream sample identified by @sample_index. The caller must unref
3358  * the returned object after use. Returns NULL if unsuccessful. */
3359 static GstStructure *
3360 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3361     QtDemuxStream * stream, guint sample_index)
3362 {
3363   QtDemuxCencSampleSetInfo *info = NULL;
3364
3365   g_return_val_if_fail (stream != NULL, NULL);
3366   g_return_val_if_fail (stream->protected, NULL);
3367   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3368
3369   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3370
3371   /* Currently, cenc properties for groups of samples are not supported, so
3372    * simply return a copy of the default sample properties */
3373   return gst_structure_copy (info->default_properties);
3374 }
3375
3376 /* Parses the sizes of sample auxiliary information contained within a stream,
3377  * as given in a saiz box. Returns array of sample_count guint8 size values,
3378  * or NULL on failure */
3379 static guint8 *
3380 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3381     GstByteReader * br, guint32 * sample_count)
3382 {
3383   guint32 flags = 0;
3384   guint8 *info_sizes;
3385   guint8 default_info_size;
3386
3387   g_return_val_if_fail (qtdemux != NULL, NULL);
3388   g_return_val_if_fail (stream != NULL, NULL);
3389   g_return_val_if_fail (br != NULL, NULL);
3390   g_return_val_if_fail (sample_count != NULL, NULL);
3391
3392   if (!gst_byte_reader_get_uint32_be (br, &flags))
3393     return NULL;
3394
3395   if (flags & 0x1) {
3396     /* aux_info_type and aux_info_type_parameter are ignored */
3397     if (!gst_byte_reader_skip (br, 8))
3398       return NULL;
3399   }
3400
3401   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3402     return NULL;
3403   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3404
3405   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3406     return NULL;
3407   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3408
3409
3410   if (default_info_size == 0) {
3411     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3412       return NULL;
3413     }
3414   } else {
3415     info_sizes = g_new (guint8, *sample_count);
3416     memset (info_sizes, default_info_size, *sample_count);
3417   }
3418
3419   return info_sizes;
3420 }
3421
3422 /* Parses the offset of sample auxiliary information contained within a stream,
3423  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3424 static gboolean
3425 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3426     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3427     guint64 * offset)
3428 {
3429   guint8 version = 0;
3430   guint32 flags = 0;
3431   guint32 aux_info_type = 0;
3432   guint32 aux_info_type_parameter = 0;
3433   guint32 entry_count;
3434   guint32 off_32;
3435   guint64 off_64;
3436   const guint8 *aux_info_type_data = NULL;
3437
3438   g_return_val_if_fail (qtdemux != NULL, FALSE);
3439   g_return_val_if_fail (stream != NULL, FALSE);
3440   g_return_val_if_fail (br != NULL, FALSE);
3441   g_return_val_if_fail (offset != NULL, FALSE);
3442
3443   if (!gst_byte_reader_get_uint8 (br, &version))
3444     return FALSE;
3445
3446   if (!gst_byte_reader_get_uint24_be (br, &flags))
3447     return FALSE;
3448
3449   if (flags & 0x1) {
3450
3451     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3452       return FALSE;
3453     aux_info_type = QT_FOURCC (aux_info_type_data);
3454
3455     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3456       return FALSE;
3457   } else if (stream->protected) {
3458     aux_info_type = stream->protection_scheme_type;
3459   } else {
3460     aux_info_type = stream->fourcc;
3461   }
3462
3463   if (info_type)
3464     *info_type = aux_info_type;
3465   if (info_type_parameter)
3466     *info_type_parameter = aux_info_type_parameter;
3467
3468   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3469       "aux_info_type_parameter:  %#06x",
3470       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3471
3472   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3473     return FALSE;
3474
3475   if (entry_count != 1) {
3476     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3477     return FALSE;
3478   }
3479
3480   if (version == 0) {
3481     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3482       return FALSE;
3483     *offset = (guint64) off_32;
3484   } else {
3485     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3486       return FALSE;
3487     *offset = off_64;
3488   }
3489
3490   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3491   return TRUE;
3492 }
3493
3494 static void
3495 qtdemux_gst_structure_free (GstStructure * gststructure)
3496 {
3497   if (gststructure) {
3498     gst_structure_free (gststructure);
3499   }
3500 }
3501
3502 /* Parses auxiliary information relating to samples protected using Common
3503  * Encryption (cenc); the format of this information is defined in
3504  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3505 static gboolean
3506 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3507     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3508 {
3509   QtDemuxCencSampleSetInfo *ss_info = NULL;
3510   guint8 size;
3511   gint i;
3512
3513   g_return_val_if_fail (qtdemux != NULL, FALSE);
3514   g_return_val_if_fail (stream != NULL, FALSE);
3515   g_return_val_if_fail (br != NULL, FALSE);
3516   g_return_val_if_fail (stream->protected, FALSE);
3517   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3518
3519   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3520
3521   if (ss_info->crypto_info) {
3522     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3523     g_ptr_array_free (ss_info->crypto_info, TRUE);
3524   }
3525
3526   ss_info->crypto_info =
3527       g_ptr_array_new_full (sample_count,
3528       (GDestroyNotify) qtdemux_gst_structure_free);
3529
3530   for (i = 0; i < sample_count; ++i) {
3531     GstStructure *properties;
3532     guint16 n_subsamples = 0;
3533     guint8 *data;
3534     guint iv_size;
3535     GstBuffer *buf;
3536
3537     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3538     if (properties == NULL) {
3539       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3540       return FALSE;
3541     }
3542     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3543       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3544       gst_structure_free (properties);
3545       return FALSE;
3546     }
3547     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3548       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3549       gst_structure_free (properties);
3550       return FALSE;
3551     }
3552     buf = gst_buffer_new_wrapped (data, iv_size);
3553     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3554     gst_buffer_unref (buf);
3555     size = info_sizes[i];
3556     if (size > iv_size) {
3557       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3558           || !(n_subsamples > 0)) {
3559         gst_structure_free (properties);
3560         GST_ERROR_OBJECT (qtdemux,
3561             "failed to get subsample count for sample %u", i);
3562         return FALSE;
3563       }
3564       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3565       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3566         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3567             i);
3568         gst_structure_free (properties);
3569         return FALSE;
3570       }
3571       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3572       if (!buf) {
3573         gst_structure_free (properties);
3574         return FALSE;
3575       }
3576       gst_structure_set (properties,
3577           "subsample_count", G_TYPE_UINT, n_subsamples,
3578           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3579       gst_buffer_unref (buf);
3580     } else {
3581       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3582     }
3583     g_ptr_array_add (ss_info->crypto_info, properties);
3584   }
3585   return TRUE;
3586 }
3587
3588 /* Converts a UUID in raw byte form to a string representation, as defined in
3589  * RFC 4122. The caller takes ownership of the returned string and is
3590  * responsible for freeing it after use. */
3591 static gchar *
3592 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3593 {
3594   const guint8 *uuid = (const guint8 *) uuid_bytes;
3595
3596   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3597       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3598       uuid[0], uuid[1], uuid[2], uuid[3],
3599       uuid[4], uuid[5], uuid[6], uuid[7],
3600       uuid[8], uuid[9], uuid[10], uuid[11],
3601       uuid[12], uuid[13], uuid[14], uuid[15]);
3602 }
3603
3604 /* Parses a Protection System Specific Header box (pssh), as defined in the
3605  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3606  * information needed by a specific content protection system in order to
3607  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3608  * otherwise. */
3609 static gboolean
3610 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3611 {
3612   gchar *sysid_string;
3613   guint32 pssh_size = QT_UINT32 (node->data);
3614   GstBuffer *pssh = NULL;
3615   GstEvent *event = NULL;
3616   guint32 parent_box_type;
3617   gint i;
3618
3619   if (G_UNLIKELY (pssh_size < 32U)) {
3620     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3621     return FALSE;
3622   }
3623
3624   sysid_string =
3625       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3626
3627   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3628
3629   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3630   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3631       gst_buffer_get_size (pssh));
3632
3633   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3634
3635   /* Push an event containing the pssh box onto the queues of all streams. */
3636   event = gst_event_new_protection (sysid_string, pssh,
3637       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3638   for (i = 0; i < qtdemux->n_streams; ++i) {
3639     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3640         gst_event_ref (event));
3641   }
3642   g_free (sysid_string);
3643   gst_event_unref (event);
3644   gst_buffer_unref (pssh);
3645   return TRUE;
3646 }
3647
3648 static gboolean
3649 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3650     guint64 moof_offset, QtDemuxStream * stream)
3651 {
3652   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3653   GNode *uuid_node;
3654   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3655   GNode *saiz_node, *saio_node, *pssh_node;
3656   GstByteReader saiz_data, saio_data;
3657   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3658   gint64 base_offset, running_offset;
3659   guint32 frag_num;
3660
3661   /* NOTE @stream ignored */
3662
3663   moof_node = g_node_new ((guint8 *) buffer);
3664   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3665   qtdemux_node_dump (qtdemux, moof_node);
3666
3667   /* Get fragment number from mfhd and check it's valid */
3668   mfhd_node =
3669       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3670   if (mfhd_node == NULL)
3671     goto missing_mfhd;
3672   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3673     goto fail;
3674   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3675
3676   /* unknown base_offset to start with */
3677   base_offset = running_offset = -1;
3678   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3679   while (traf_node) {
3680     guint64 decode_time = 0;
3681
3682     /* Fragment Header node */
3683     tfhd_node =
3684         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3685         &tfhd_data);
3686     if (!tfhd_node)
3687       goto missing_tfhd;
3688     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3689             &ds_size, &ds_flags, &base_offset))
3690       goto missing_tfhd;
3691
3692     /* The following code assumes at most a single set of sample auxiliary
3693      * data in the fragment (consisting of a saiz box and a corresponding saio
3694      * box); in theory, however, there could be multiple sets of sample
3695      * auxiliary data in a fragment. */
3696     saiz_node =
3697         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3698         &saiz_data);
3699     if (saiz_node) {
3700       guint32 info_type = 0;
3701       guint64 offset = 0;
3702       guint32 info_type_parameter = 0;
3703
3704       g_free (qtdemux->cenc_aux_info_sizes);
3705
3706       qtdemux->cenc_aux_info_sizes =
3707           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3708           &qtdemux->cenc_aux_sample_count);
3709       if (qtdemux->cenc_aux_info_sizes == NULL) {
3710         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3711         goto fail;
3712       }
3713       saio_node =
3714           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3715           &saio_data);
3716       if (!saio_node) {
3717         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3718         g_free (qtdemux->cenc_aux_info_sizes);
3719         qtdemux->cenc_aux_info_sizes = NULL;
3720         goto fail;
3721       }
3722
3723       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3724                   &info_type, &info_type_parameter, &offset))) {
3725         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3726         g_free (qtdemux->cenc_aux_info_sizes);
3727         qtdemux->cenc_aux_info_sizes = NULL;
3728         goto fail;
3729       }
3730       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3731         offset += (guint64) (base_offset - qtdemux->moof_offset);
3732       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3733         GstByteReader br;
3734         if (offset > length) {
3735           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3736           qtdemux->cenc_aux_info_offset = offset;
3737         } else {
3738           gst_byte_reader_init (&br, buffer + offset, length - offset);
3739           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3740                   qtdemux->cenc_aux_info_sizes,
3741                   qtdemux->cenc_aux_sample_count)) {
3742             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3743             g_free (qtdemux->cenc_aux_info_sizes);
3744             qtdemux->cenc_aux_info_sizes = NULL;
3745             goto fail;
3746           }
3747         }
3748       }
3749     }
3750
3751     tfdt_node =
3752         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3753         &tfdt_data);
3754     if (tfdt_node) {
3755       /* We'll use decode_time to interpolate timestamps
3756        * in case the input timestamps are missing */
3757       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3758
3759       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3760           " (%" GST_TIME_FORMAT ")", decode_time,
3761           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3762
3763       /* Discard the fragment buffer timestamp info to avoid using it.
3764        * Rely on tfdt instead as it is more accurate than the timestamp
3765        * that is fetched from a manifest/playlist and is usually
3766        * less accurate. */
3767       qtdemux->fragment_start = -1;
3768     }
3769
3770     if (G_UNLIKELY (!stream)) {
3771       /* we lost track of offset, we'll need to regain it,
3772        * but can delay complaining until later or avoid doing so altogether */
3773       base_offset = -2;
3774       goto next;
3775     }
3776     if (G_UNLIKELY (base_offset < -1))
3777       goto lost_offset;
3778
3779     if (qtdemux->upstream_format_is_time)
3780       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3781
3782     /* initialise moof sample data */
3783     stream->n_samples_moof = 0;
3784     stream->duration_moof = 0;
3785
3786     /* Track Run node */
3787     trun_node =
3788         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3789         &trun_data);
3790     while (trun_node) {
3791       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3792           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3793           &running_offset, decode_time);
3794       /* iterate all siblings */
3795       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3796           &trun_data);
3797     }
3798
3799     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3800     if (uuid_node) {
3801       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3802       guint32 box_length = QT_UINT32 (uuid_buffer);
3803
3804       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3805     }
3806
3807     /* if no new base_offset provided for next traf,
3808      * base is end of current traf */
3809     base_offset = running_offset;
3810     running_offset = -1;
3811
3812     if (stream->n_samples_moof && stream->duration_moof)
3813       stream->new_caps = TRUE;
3814
3815   next:
3816     /* iterate all siblings */
3817     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3818   }
3819
3820   /* parse any protection system info */
3821   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3822   while (pssh_node) {
3823     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3824     qtdemux_parse_pssh (qtdemux, pssh_node);
3825     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3826   }
3827
3828   g_node_destroy (moof_node);
3829   return TRUE;
3830
3831 missing_tfhd:
3832   {
3833     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3834     goto fail;
3835   }
3836 missing_mfhd:
3837   {
3838     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3839     goto fail;
3840   }
3841 lost_offset:
3842   {
3843     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3844     goto fail;
3845   }
3846 fail:
3847   {
3848     g_node_destroy (moof_node);
3849     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3850         (_("This file is corrupt and cannot be played.")), (NULL));
3851     return FALSE;
3852   }
3853 }
3854
3855 #if 0
3856 /* might be used if some day we actually use mfra & co
3857  * for random access to fragments,
3858  * but that will require quite some modifications and much less relying
3859  * on a sample array */
3860 #endif
3861
3862 static gboolean
3863 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3864 {
3865   QtDemuxStream *stream;
3866   guint32 ver_flags, track_id, len, num_entries, i;
3867   guint value_size, traf_size, trun_size, sample_size;
3868   guint64 time = 0, moof_offset = 0;
3869 #if 0
3870   GstBuffer *buf = NULL;
3871   GstFlowReturn ret;
3872 #endif
3873   GstByteReader tfra;
3874
3875   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3876
3877   if (!gst_byte_reader_skip (&tfra, 8))
3878     return FALSE;
3879
3880   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3881     return FALSE;
3882
3883   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3884       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3885       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3886     return FALSE;
3887
3888   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3889
3890   stream = qtdemux_find_stream (qtdemux, track_id);
3891   if (stream == NULL)
3892     goto unknown_trackid;
3893
3894   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3895   sample_size = (len & 3) + 1;
3896   trun_size = ((len & 12) >> 2) + 1;
3897   traf_size = ((len & 48) >> 4) + 1;
3898
3899   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3900       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3901
3902   if (num_entries == 0)
3903     goto no_samples;
3904
3905   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3906           value_size + value_size + traf_size + trun_size + sample_size))
3907     goto corrupt_file;
3908
3909   g_free (stream->ra_entries);
3910   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3911   stream->n_ra_entries = num_entries;
3912
3913   for (i = 0; i < num_entries; i++) {
3914     qt_atom_parser_get_offset (&tfra, value_size, &time);
3915     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3916     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3917     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3918     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3919
3920     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3921
3922     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3923         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3924
3925     stream->ra_entries[i].ts = time;
3926     stream->ra_entries[i].moof_offset = moof_offset;
3927
3928     /* don't want to go through the entire file and read all moofs at startup */
3929 #if 0
3930     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3931     if (ret != GST_FLOW_OK)
3932       goto corrupt_file;
3933     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3934         moof_offset, stream);
3935     gst_buffer_unref (buf);
3936 #endif
3937   }
3938
3939   check_update_duration (qtdemux, time);
3940
3941   return TRUE;
3942
3943 /* ERRORS */
3944 unknown_trackid:
3945   {
3946     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3947     return FALSE;
3948   }
3949 corrupt_file:
3950   {
3951     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3952     return FALSE;
3953   }
3954 no_samples:
3955   {
3956     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3957     return FALSE;
3958   }
3959 }
3960
3961 static gboolean
3962 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3963 {
3964   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3965   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3966   GstBuffer *mfro = NULL, *mfra = NULL;
3967   GstFlowReturn flow;
3968   gboolean ret = FALSE;
3969   GNode *mfra_node, *tfra_node;
3970   guint64 mfra_offset = 0;
3971   guint32 fourcc, mfra_size;
3972   gint64 len;
3973
3974   /* query upstream size in bytes */
3975   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3976     goto size_query_failed;
3977
3978   /* mfro box should be at the very end of the file */
3979   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3980   if (flow != GST_FLOW_OK)
3981     goto exit;
3982
3983   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3984
3985   fourcc = QT_FOURCC (mfro_map.data + 4);
3986   if (fourcc != FOURCC_mfro)
3987     goto exit;
3988
3989   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3990   if (mfro_map.size < 16)
3991     goto invalid_mfro_size;
3992
3993   mfra_size = QT_UINT32 (mfro_map.data + 12);
3994   if (mfra_size >= len)
3995     goto invalid_mfra_size;
3996
3997   mfra_offset = len - mfra_size;
3998
3999   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4000       mfra_offset, mfra_size);
4001
4002   /* now get and parse mfra box */
4003   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4004   if (flow != GST_FLOW_OK)
4005     goto broken_file;
4006
4007   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4008
4009   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4010   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4011
4012   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4013
4014   while (tfra_node) {
4015     qtdemux_parse_tfra (qtdemux, tfra_node);
4016     /* iterate all siblings */
4017     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4018   }
4019   g_node_destroy (mfra_node);
4020
4021   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4022   ret = TRUE;
4023
4024 exit:
4025
4026   if (mfro) {
4027     if (mfro_map.memory != NULL)
4028       gst_buffer_unmap (mfro, &mfro_map);
4029     gst_buffer_unref (mfro);
4030   }
4031   if (mfra) {
4032     if (mfra_map.memory != NULL)
4033       gst_buffer_unmap (mfra, &mfra_map);
4034     gst_buffer_unref (mfra);
4035   }
4036   return ret;
4037
4038 /* ERRORS */
4039 size_query_failed:
4040   {
4041     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4042     goto exit;
4043   }
4044 invalid_mfro_size:
4045   {
4046     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4047     goto exit;
4048   }
4049 invalid_mfra_size:
4050   {
4051     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4052     goto exit;
4053   }
4054 broken_file:
4055   {
4056     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4057     goto exit;
4058   }
4059 }
4060
4061 static guint64
4062 add_offset (guint64 offset, guint64 advance)
4063 {
4064   /* Avoid 64-bit overflow by clamping */
4065   if (offset > G_MAXUINT64 - advance)
4066     return G_MAXUINT64;
4067   return offset + advance;
4068 }
4069
4070 static GstFlowReturn
4071 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4072 {
4073   guint64 length = 0;
4074   guint32 fourcc = 0;
4075   GstBuffer *buf = NULL;
4076   GstFlowReturn ret = GST_FLOW_OK;
4077   guint64 cur_offset = qtdemux->offset;
4078   GstMapInfo map;
4079
4080   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4081   if (G_UNLIKELY (ret != GST_FLOW_OK))
4082     goto beach;
4083   gst_buffer_map (buf, &map, GST_MAP_READ);
4084   if (G_LIKELY (map.size >= 8))
4085     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4086   gst_buffer_unmap (buf, &map);
4087   gst_buffer_unref (buf);
4088
4089   /* maybe we already got most we needed, so only consider this eof */
4090   if (G_UNLIKELY (length == 0)) {
4091     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4092         (_("Invalid atom size.")),
4093         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4094             GST_FOURCC_ARGS (fourcc)));
4095     ret = GST_FLOW_EOS;
4096     goto beach;
4097   }
4098
4099   switch (fourcc) {
4100     case FOURCC_moof:
4101       /* record for later parsing when needed */
4102       if (!qtdemux->moof_offset) {
4103         qtdemux->moof_offset = qtdemux->offset;
4104       }
4105       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4106         /* FIXME */
4107       } else {
4108         qtdemux->offset += length;      /* skip moof and keep going */
4109       }
4110       if (qtdemux->got_moov) {
4111         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4112         ret = GST_FLOW_EOS;
4113         goto beach;
4114       }
4115       break;
4116     case FOURCC_mdat:
4117     case FOURCC_free:
4118     case FOURCC_wide:
4119     case FOURCC_PICT:
4120     case FOURCC_pnot:
4121     {
4122       GST_LOG_OBJECT (qtdemux,
4123           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4124           GST_FOURCC_ARGS (fourcc), cur_offset);
4125       qtdemux->offset = add_offset (qtdemux->offset, length);
4126       break;
4127     }
4128     case FOURCC_moov:
4129     {
4130       GstBuffer *moov = NULL;
4131
4132       if (qtdemux->got_moov) {
4133         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4134         qtdemux->offset = add_offset (qtdemux->offset, length);
4135         goto beach;
4136       }
4137
4138       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4139       if (ret != GST_FLOW_OK)
4140         goto beach;
4141       gst_buffer_map (moov, &map, GST_MAP_READ);
4142
4143       if (length != map.size) {
4144         /* Some files have a 'moov' atom at the end of the file which contains
4145          * a terminal 'free' atom where the body of the atom is missing.
4146          * Check for, and permit, this special case.
4147          */
4148         if (map.size >= 8) {
4149           guint8 *final_data = map.data + (map.size - 8);
4150           guint32 final_length = QT_UINT32 (final_data);
4151           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4152
4153           if (final_fourcc == FOURCC_free
4154               && map.size + final_length - 8 == length) {
4155             /* Ok, we've found that special case. Allocate a new buffer with
4156              * that free atom actually present. */
4157             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4158             gst_buffer_fill (newmoov, 0, map.data, map.size);
4159             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4160             gst_buffer_unmap (moov, &map);
4161             gst_buffer_unref (moov);
4162             moov = newmoov;
4163             gst_buffer_map (moov, &map, GST_MAP_READ);
4164           }
4165         }
4166       }
4167
4168       if (length != map.size) {
4169         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4170             (_("This file is incomplete and cannot be played.")),
4171             ("We got less than expected (received %" G_GSIZE_FORMAT
4172                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4173                 (guint) length, cur_offset));
4174         gst_buffer_unmap (moov, &map);
4175         gst_buffer_unref (moov);
4176         ret = GST_FLOW_ERROR;
4177         goto beach;
4178       }
4179       qtdemux->offset += length;
4180
4181       qtdemux_parse_moov (qtdemux, map.data, length);
4182       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4183
4184       qtdemux_parse_tree (qtdemux);
4185       g_node_destroy (qtdemux->moov_node);
4186       gst_buffer_unmap (moov, &map);
4187       gst_buffer_unref (moov);
4188       qtdemux->moov_node = NULL;
4189       qtdemux->got_moov = TRUE;
4190
4191       break;
4192     }
4193     case FOURCC_ftyp:
4194     {
4195       GstBuffer *ftyp = NULL;
4196
4197       /* extract major brand; might come in handy for ISO vs QT issues */
4198       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4199       if (ret != GST_FLOW_OK)
4200         goto beach;
4201       qtdemux->offset += length;
4202       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4203       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4204       gst_buffer_unmap (ftyp, &map);
4205       gst_buffer_unref (ftyp);
4206       break;
4207     }
4208     case FOURCC_uuid:
4209     {
4210       GstBuffer *uuid = NULL;
4211
4212       /* uuid are extension atoms */
4213       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4214       if (ret != GST_FLOW_OK)
4215         goto beach;
4216       qtdemux->offset += length;
4217       gst_buffer_map (uuid, &map, GST_MAP_READ);
4218       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4219       gst_buffer_unmap (uuid, &map);
4220       gst_buffer_unref (uuid);
4221       break;
4222     }
4223     case FOURCC_sidx:
4224     {
4225       GstBuffer *sidx = NULL;
4226       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4227       if (ret != GST_FLOW_OK)
4228         goto beach;
4229       qtdemux->offset += length;
4230       gst_buffer_map (sidx, &map, GST_MAP_READ);
4231       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4232       gst_buffer_unmap (sidx, &map);
4233       gst_buffer_unref (sidx);
4234       break;
4235     }
4236     default:
4237     {
4238       GstBuffer *unknown = NULL;
4239
4240       GST_LOG_OBJECT (qtdemux,
4241           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4242           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4243           cur_offset);
4244       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4245       if (ret != GST_FLOW_OK)
4246         goto beach;
4247       gst_buffer_map (unknown, &map, GST_MAP_READ);
4248       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4249       gst_buffer_unmap (unknown, &map);
4250       gst_buffer_unref (unknown);
4251       qtdemux->offset += length;
4252       break;
4253     }
4254   }
4255
4256 beach:
4257   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4258     /* digested all data, show what we have */
4259     qtdemux_prepare_streams (qtdemux);
4260     ret = qtdemux_expose_streams (qtdemux);
4261
4262     qtdemux->state = QTDEMUX_STATE_MOVIE;
4263     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4264         qtdemux->state);
4265     return ret;
4266   }
4267   return ret;
4268 }
4269
4270 /* Seeks to the previous keyframe of the indexed stream and
4271  * aligns other streams with respect to the keyframe timestamp
4272  * of indexed stream. Only called in case of Reverse Playback
4273  */
4274 static GstFlowReturn
4275 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4276 {
4277   guint8 n = 0;
4278   guint32 seg_idx = 0, k_index = 0;
4279   guint32 ref_seg_idx, ref_k_index;
4280   GstClockTime k_pos = 0, last_stop = 0;
4281   QtDemuxSegment *seg = NULL;
4282   QtDemuxStream *ref_str = NULL;
4283   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4284   guint64 target_ts;
4285
4286   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4287    * and finally align all the other streams on that timestamp with their
4288    * respective keyframes */
4289   for (n = 0; n < qtdemux->n_streams; n++) {
4290     QtDemuxStream *str = qtdemux->streams[n];
4291
4292     /* No candidate yet, take the first stream */
4293     if (!ref_str) {
4294       ref_str = str;
4295       continue;
4296     }
4297
4298     /* So that stream has a segment, we prefer video streams */
4299     if (str->subtype == FOURCC_vide) {
4300       ref_str = str;
4301       break;
4302     }
4303   }
4304
4305   if (G_UNLIKELY (!ref_str)) {
4306     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4307     goto eos;
4308   }
4309
4310   if (G_UNLIKELY (!ref_str->from_sample)) {
4311     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4312     goto eos;
4313   }
4314
4315   /* So that stream has been playing from from_sample to to_sample. We will
4316    * get the timestamp of the previous sample and search for a keyframe before
4317    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4318   if (ref_str->subtype == FOURCC_vide) {
4319     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4320         ref_str->from_sample - 1);
4321   } else {
4322     if (ref_str->from_sample >= 10)
4323       k_index = ref_str->from_sample - 10;
4324     else
4325       k_index = 0;
4326   }
4327
4328   target_ts =
4329       ref_str->samples[k_index].timestamp +
4330       ref_str->samples[k_index].pts_offset;
4331
4332   /* get current segment for that stream */
4333   seg = &ref_str->segments[ref_str->segment_index];
4334   /* Use segment start in original timescale for comparisons */
4335   seg_media_start_mov = seg->trak_media_start;
4336
4337   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4338       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4339       k_index, target_ts, seg_media_start_mov,
4340       GST_TIME_ARGS (seg->media_start));
4341
4342   /* Crawl back through segments to find the one containing this I frame */
4343   while (target_ts < seg_media_start_mov) {
4344     GST_DEBUG_OBJECT (qtdemux,
4345         "keyframe position (sample %u) is out of segment %u " " target %"
4346         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4347         ref_str->segment_index, target_ts, seg_media_start_mov);
4348
4349     if (G_UNLIKELY (!ref_str->segment_index)) {
4350       /* Reached first segment, let's consider it's EOS */
4351       goto eos;
4352     }
4353     ref_str->segment_index--;
4354     seg = &ref_str->segments[ref_str->segment_index];
4355     /* Use segment start in original timescale for comparisons */
4356     seg_media_start_mov = seg->trak_media_start;
4357   }
4358   /* Calculate time position of the keyframe and where we should stop */
4359   k_pos =
4360       QTSTREAMTIME_TO_GSTTIME (ref_str,
4361       target_ts - seg->trak_media_start) + seg->time;
4362   last_stop =
4363       QTSTREAMTIME_TO_GSTTIME (ref_str,
4364       ref_str->samples[ref_str->from_sample].timestamp -
4365       seg->trak_media_start) + seg->time;
4366
4367   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4368       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4369       k_index, GST_TIME_ARGS (k_pos));
4370
4371   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4372   qtdemux->segment.position = last_stop;
4373   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4374       GST_TIME_ARGS (last_stop));
4375
4376   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4377     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4378     goto eos;
4379   }
4380
4381   ref_seg_idx = ref_str->segment_index;
4382   ref_k_index = k_index;
4383
4384   /* Align them all on this */
4385   for (n = 0; n < qtdemux->n_streams; n++) {
4386     guint32 index = 0;
4387     GstClockTime seg_time = 0;
4388     QtDemuxStream *str = qtdemux->streams[n];
4389
4390     /* aligning reference stream again might lead to backing up to yet another
4391      * keyframe (due to timestamp rounding issues),
4392      * potentially putting more load on downstream; so let's try to avoid */
4393     if (str == ref_str) {
4394       seg_idx = ref_seg_idx;
4395       seg = &str->segments[seg_idx];
4396       k_index = ref_k_index;
4397       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4398           "sample at index %d", n, ref_str->segment_index, k_index);
4399     } else {
4400       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4401       GST_DEBUG_OBJECT (qtdemux,
4402           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4403           seg_idx, GST_TIME_ARGS (k_pos));
4404
4405       /* get segment and time in the segment */
4406       seg = &str->segments[seg_idx];
4407       seg_time = k_pos - seg->time;
4408
4409       /* get the media time in the segment.
4410        * No adjustment for empty "filler" segments */
4411       if (seg->media_start != GST_CLOCK_TIME_NONE)
4412         seg_time += seg->media_start;
4413
4414       /* get the index of the sample with media time */
4415       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4416       GST_DEBUG_OBJECT (qtdemux,
4417           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4418           GST_TIME_ARGS (seg_time), index);
4419
4420       /* find previous keyframe */
4421       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4422     }
4423
4424     /* Remember until where we want to go */
4425     str->to_sample = str->from_sample - 1;
4426     /* Define our time position */
4427     target_ts =
4428         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4429     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4430     if (seg->media_start != GST_CLOCK_TIME_NONE)
4431       str->time_position -= seg->media_start;
4432
4433     /* Now seek back in time */
4434     gst_qtdemux_move_stream (qtdemux, str, k_index);
4435     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4436         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4437         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4438   }
4439
4440   return GST_FLOW_OK;
4441
4442 eos:
4443   return GST_FLOW_EOS;
4444 }
4445
4446 /*
4447  * Gets the current qt segment start, stop and position for the
4448  * given time offset. This is used in update_segment()
4449  */
4450 static void
4451 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4452     QtDemuxStream * stream, GstClockTime offset,
4453     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4454 {
4455   GstClockTime seg_time;
4456   GstClockTime start, stop, time;
4457   QtDemuxSegment *segment;
4458
4459   segment = &stream->segments[stream->segment_index];
4460
4461   /* get time in this segment */
4462   seg_time = (offset - segment->time) * segment->rate;
4463
4464   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4465       GST_TIME_ARGS (seg_time));
4466
4467   if (G_UNLIKELY (seg_time > segment->duration)) {
4468     GST_LOG_OBJECT (stream->pad,
4469         "seg_time > segment->duration %" GST_TIME_FORMAT,
4470         GST_TIME_ARGS (segment->duration));
4471     seg_time = segment->duration;
4472   }
4473
4474   /* qtdemux->segment.stop is in outside-time-realm, whereas
4475    * segment->media_stop is in track-time-realm.
4476    *
4477    * In order to compare the two, we need to bring segment.stop
4478    * into the track-time-realm
4479    *
4480    * FIXME - does this comment still hold? Don't see any conversion here */
4481
4482   stop = qtdemux->segment.stop;
4483   if (stop == GST_CLOCK_TIME_NONE)
4484     stop = qtdemux->segment.duration;
4485   if (stop == GST_CLOCK_TIME_NONE)
4486     stop = segment->media_stop;
4487   else
4488     stop =
4489         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4490
4491   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4492     start = segment->time + seg_time;
4493     time = offset;
4494     stop = start - seg_time + segment->duration;
4495   } else if (qtdemux->segment.rate >= 0) {
4496     start = MIN (segment->media_start + seg_time, stop);
4497     time = offset;
4498   } else {
4499     if (segment->media_start >= qtdemux->segment.start) {
4500       time = segment->time;
4501     } else {
4502       time = segment->time + (qtdemux->segment.start - segment->media_start);
4503     }
4504
4505     start = MAX (segment->media_start, qtdemux->segment.start);
4506     stop = MIN (segment->media_start + seg_time, stop);
4507   }
4508
4509   *_start = start;
4510   *_stop = stop;
4511   *_time = time;
4512 }
4513
4514 /*
4515  * Updates the qt segment used for the stream and pushes a new segment event
4516  * downstream on this stream's pad.
4517  */
4518 static gboolean
4519 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4520     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4521     GstClockTime * _stop)
4522 {
4523   QtDemuxSegment *segment;
4524   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4525   gdouble rate;
4526   GstEvent *event;
4527
4528   /* update the current segment */
4529   stream->segment_index = seg_idx;
4530
4531   /* get the segment */
4532   segment = &stream->segments[seg_idx];
4533
4534   if (G_UNLIKELY (offset < segment->time)) {
4535     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4536         GST_TIME_ARGS (segment->time));
4537     return FALSE;
4538   }
4539
4540   /* segment lies beyond total indicated duration */
4541   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4542           segment->time > qtdemux->segment.duration)) {
4543     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4544         " < segment->time %" GST_TIME_FORMAT,
4545         GST_TIME_ARGS (qtdemux->segment.duration),
4546         GST_TIME_ARGS (segment->time));
4547     return FALSE;
4548   }
4549
4550   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4551       &start, &stop, &time);
4552
4553   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4554       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4555       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4556
4557   /* combine global rate with that of the segment */
4558   rate = segment->rate * qtdemux->segment.rate;
4559
4560   /* Copy flags from main segment */
4561   stream->segment.flags = qtdemux->segment.flags;
4562
4563   /* update the segment values used for clipping */
4564   stream->segment.offset = qtdemux->segment.offset;
4565   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4566   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4567   stream->segment.rate = rate;
4568   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4569       stream->cslg_shift);
4570   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4571       stream->cslg_shift);
4572   stream->segment.time = time;
4573   stream->segment.position = stream->segment.start;
4574
4575   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4576       &stream->segment);
4577
4578   /* now prepare and send the segment */
4579   if (stream->pad) {
4580     event = gst_event_new_segment (&stream->segment);
4581     if (qtdemux->segment_seqnum) {
4582       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4583     }
4584     gst_pad_push_event (stream->pad, event);
4585     /* assume we can send more data now */
4586     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4587     /* clear to send tags on this pad now */
4588     gst_qtdemux_push_tags (qtdemux, stream);
4589   }
4590
4591   if (_start)
4592     *_start = start;
4593   if (_stop)
4594     *_stop = stop;
4595
4596   return TRUE;
4597 }
4598
4599 /* activate the given segment number @seg_idx of @stream at time @offset.
4600  * @offset is an absolute global position over all the segments.
4601  *
4602  * This will push out a NEWSEGMENT event with the right values and
4603  * position the stream index to the first decodable sample before
4604  * @offset.
4605  */
4606 static gboolean
4607 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4608     guint32 seg_idx, GstClockTime offset)
4609 {
4610   QtDemuxSegment *segment;
4611   guint32 index, kf_index;
4612   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4613
4614   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4615       seg_idx, GST_TIME_ARGS (offset));
4616
4617   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4618           &start, &stop))
4619     return FALSE;
4620
4621   segment = &stream->segments[stream->segment_index];
4622
4623   /* in the fragmented case, we pick a fragment that starts before our
4624    * desired position and rely on downstream to wait for a keyframe
4625    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4626    * tfra entries tells us which trun/sample the key unit is in, but we don't
4627    * make use of this additional information at the moment) */
4628   if (qtdemux->fragmented) {
4629     stream->to_sample = G_MAXUINT32;
4630     return TRUE;
4631   }
4632
4633   /* We don't need to look for a sample in push-based */
4634   if (!qtdemux->pullbased)
4635     return TRUE;
4636
4637   /* and move to the keyframe before the indicated media time of the
4638    * segment */
4639   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4640     if (qtdemux->segment.rate >= 0) {
4641       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4642       stream->to_sample = G_MAXUINT32;
4643       GST_DEBUG_OBJECT (stream->pad,
4644           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4645           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4646           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4647     } else {
4648       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4649       stream->to_sample = index;
4650       GST_DEBUG_OBJECT (stream->pad,
4651           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4652           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4653           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4654     }
4655   } else {
4656     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4657         "this is an empty segment");
4658     return TRUE;
4659   }
4660
4661   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4662    * encountered an error and printed a message so we return appropriately */
4663   if (index == -1)
4664     return FALSE;
4665
4666   /* we're at the right spot */
4667   if (index == stream->sample_index) {
4668     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4669     return TRUE;
4670   }
4671
4672   /* find keyframe of the target index */
4673   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4674
4675 /* *INDENT-OFF* */
4676 /* indent does stupid stuff with stream->samples[].timestamp */
4677
4678   /* if we move forwards, we don't have to go back to the previous
4679    * keyframe since we already sent that. We can also just jump to
4680    * the keyframe right before the target index if there is one. */
4681   if (index > stream->sample_index) {
4682     /* moving forwards check if we move past a keyframe */
4683     if (kf_index > stream->sample_index) {
4684       GST_DEBUG_OBJECT (stream->pad,
4685            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4686            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4687            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4688       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4689     } else {
4690       GST_DEBUG_OBJECT (stream->pad,
4691           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4692           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4693           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4694     }
4695   } else {
4696     GST_DEBUG_OBJECT (stream->pad,
4697         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4698         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4699         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4700     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4701   }
4702
4703 /* *INDENT-ON* */
4704
4705   return TRUE;
4706 }
4707
4708 /* prepare to get the current sample of @stream, getting essential values.
4709  *
4710  * This function will also prepare and send the segment when needed.
4711  *
4712  * Return FALSE if the stream is EOS.
4713  *
4714  * PULL-BASED
4715  */
4716 static gboolean
4717 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4718     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4719     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4720     gboolean * keyframe)
4721 {
4722   QtDemuxSample *sample;
4723   GstClockTime time_position;
4724   guint32 seg_idx;
4725
4726   g_return_val_if_fail (stream != NULL, FALSE);
4727
4728   time_position = stream->time_position;
4729   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4730     goto eos;
4731
4732   seg_idx = stream->segment_index;
4733   if (G_UNLIKELY (seg_idx == -1)) {
4734     /* find segment corresponding to time_position if we are looking
4735      * for a segment. */
4736     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4737   }
4738
4739   /* different segment, activate it, sample_index will be set. */
4740   if (G_UNLIKELY (stream->segment_index != seg_idx))
4741     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4742
4743   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4744                   segment_index]))) {
4745     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4746
4747     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4748         " prepare empty sample");
4749
4750     *empty = TRUE;
4751     *pts = *dts = time_position;
4752     *duration = seg->duration - (time_position - seg->time);
4753
4754     return TRUE;
4755   }
4756
4757   *empty = FALSE;
4758
4759   if (stream->sample_index == -1)
4760     stream->sample_index = 0;
4761
4762   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4763       stream->sample_index, stream->n_samples);
4764
4765   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4766     if (!qtdemux->fragmented)
4767       goto eos;
4768
4769     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4770     do {
4771       GstFlowReturn flow;
4772
4773       GST_OBJECT_LOCK (qtdemux);
4774       flow = qtdemux_add_fragmented_samples (qtdemux);
4775       GST_OBJECT_UNLOCK (qtdemux);
4776
4777       if (flow != GST_FLOW_OK)
4778         goto eos;
4779     }
4780     while (stream->sample_index >= stream->n_samples);
4781   }
4782
4783   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4784     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4785         stream->sample_index);
4786     return FALSE;
4787   }
4788
4789   /* now get the info for the sample we're at */
4790   sample = &stream->samples[stream->sample_index];
4791
4792   *dts = QTSAMPLE_DTS (stream, sample);
4793   *pts = QTSAMPLE_PTS (stream, sample);
4794   *offset = sample->offset;
4795   *size = sample->size;
4796   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4797   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4798
4799   return TRUE;
4800
4801   /* special cases */
4802 eos:
4803   {
4804     stream->time_position = GST_CLOCK_TIME_NONE;
4805     return FALSE;
4806   }
4807 }
4808
4809 /* move to the next sample in @stream.
4810  *
4811  * Moves to the next segment when needed.
4812  */
4813 static void
4814 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4815 {
4816   QtDemuxSample *sample;
4817   QtDemuxSegment *segment;
4818
4819   /* get current segment */
4820   segment = &stream->segments[stream->segment_index];
4821
4822   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4823     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4824     goto next_segment;
4825   }
4826
4827   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4828     /* Mark the stream as EOS */
4829     GST_DEBUG_OBJECT (qtdemux,
4830         "reached max allowed sample %u, mark EOS", stream->to_sample);
4831     stream->time_position = GST_CLOCK_TIME_NONE;
4832     return;
4833   }
4834
4835   /* move to next sample */
4836   stream->sample_index++;
4837   stream->offset_in_sample = 0;
4838
4839   /* reached the last sample, we need the next segment */
4840   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4841     goto next_segment;
4842
4843   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4844     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4845         stream->sample_index);
4846     return;
4847   }
4848
4849   /* get next sample */
4850   sample = &stream->samples[stream->sample_index];
4851
4852   /* see if we are past the segment */
4853   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4854     goto next_segment;
4855
4856   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4857     /* inside the segment, update time_position, looks very familiar to
4858      * GStreamer segments, doesn't it? */
4859     stream->time_position =
4860         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4861   } else {
4862     /* not yet in segment, time does not yet increment. This means
4863      * that we are still prerolling keyframes to the decoder so it can
4864      * decode the first sample of the segment. */
4865     stream->time_position = segment->time;
4866   }
4867   return;
4868
4869   /* move to the next segment */
4870 next_segment:
4871   {
4872     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4873
4874     if (stream->segment_index == stream->n_segments - 1) {
4875       /* are we at the end of the last segment, we're EOS */
4876       stream->time_position = GST_CLOCK_TIME_NONE;
4877     } else {
4878       /* else we're only at the end of the current segment */
4879       stream->time_position = segment->stop_time;
4880     }
4881     /* make sure we select a new segment */
4882
4883     /* accumulate previous segments */
4884     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4885       stream->accumulated_base +=
4886           (stream->segment.stop -
4887           stream->segment.start) / ABS (stream->segment.rate);
4888
4889     stream->segment_index = -1;
4890   }
4891 }
4892
4893 static void
4894 gst_qtdemux_sync_streams (GstQTDemux * demux)
4895 {
4896   gint i;
4897
4898   if (demux->n_streams <= 1)
4899     return;
4900
4901   for (i = 0; i < demux->n_streams; i++) {
4902     QtDemuxStream *stream;
4903     GstClockTime end_time;
4904
4905     stream = demux->streams[i];
4906
4907     if (!stream->pad)
4908       continue;
4909
4910     /* TODO advance time on subtitle streams here, if any some day */
4911
4912     /* some clips/trailers may have unbalanced streams at the end,
4913      * so send EOS on shorter stream to prevent stalling others */
4914
4915     /* do not mess with EOS if SEGMENT seeking */
4916     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4917       continue;
4918
4919     if (demux->pullbased) {
4920       /* loop mode is sample time based */
4921       if (!STREAM_IS_EOS (stream))
4922         continue;
4923     } else {
4924       /* push mode is byte position based */
4925       if (stream->n_samples &&
4926           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4927         continue;
4928     }
4929
4930     if (stream->sent_eos)
4931       continue;
4932
4933     /* only act if some gap */
4934     end_time = stream->segments[stream->n_segments - 1].stop_time;
4935     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4936         ", stream end: %" GST_TIME_FORMAT,
4937         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4938     if (GST_CLOCK_TIME_IS_VALID (end_time)
4939         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4940       GstEvent *event;
4941
4942       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4943           GST_PAD_NAME (stream->pad));
4944       stream->sent_eos = TRUE;
4945       event = gst_event_new_eos ();
4946       if (demux->segment_seqnum)
4947         gst_event_set_seqnum (event, demux->segment_seqnum);
4948       gst_pad_push_event (stream->pad, event);
4949     }
4950   }
4951 }
4952
4953 /* EOS and NOT_LINKED need to be combined. This means that we return:
4954  *
4955  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4956  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4957  */
4958 static GstFlowReturn
4959 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4960     GstFlowReturn ret)
4961 {
4962   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4963
4964   if (stream->pad)
4965     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4966         ret);
4967   else
4968     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4969
4970   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4971   return ret;
4972 }
4973
4974 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4975  * completely clipped
4976  *
4977  * Should be used only with raw buffers */
4978 static GstBuffer *
4979 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4980     GstBuffer * buf)
4981 {
4982   guint64 start, stop, cstart, cstop, diff;
4983   GstClockTime pts, duration;
4984   gsize size, osize;
4985   gint num_rate, denom_rate;
4986   gint frame_size;
4987   gboolean clip_data;
4988   guint offset;
4989
4990   osize = size = gst_buffer_get_size (buf);
4991   offset = 0;
4992
4993   /* depending on the type, setup the clip parameters */
4994   if (stream->subtype == FOURCC_soun) {
4995     frame_size = stream->bytes_per_frame;
4996     num_rate = GST_SECOND;
4997     denom_rate = (gint) stream->rate;
4998     clip_data = TRUE;
4999   } else if (stream->subtype == FOURCC_vide) {
5000     frame_size = size;
5001     num_rate = stream->fps_n;
5002     denom_rate = stream->fps_d;
5003     clip_data = FALSE;
5004   } else
5005     goto wrong_type;
5006
5007   if (frame_size <= 0)
5008     goto bad_frame_size;
5009
5010   /* we can only clip if we have a valid pts */
5011   pts = GST_BUFFER_PTS (buf);
5012   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5013     goto no_pts;
5014
5015   duration = GST_BUFFER_DURATION (buf);
5016
5017   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5018     duration =
5019         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5020   }
5021
5022   start = pts;
5023   stop = start + duration;
5024
5025   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5026               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5027     goto clipped;
5028
5029   /* see if some clipping happened */
5030   diff = cstart - start;
5031   if (diff > 0) {
5032     pts += diff;
5033     duration -= diff;
5034
5035     if (clip_data) {
5036       /* bring clipped time to samples and to bytes */
5037       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5038       diff *= frame_size;
5039
5040       GST_DEBUG_OBJECT (qtdemux,
5041           "clipping start to %" GST_TIME_FORMAT " %"
5042           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5043
5044       offset = diff;
5045       size -= diff;
5046     }
5047   }
5048   diff = stop - cstop;
5049   if (diff > 0) {
5050     duration -= diff;
5051
5052     if (clip_data) {
5053       /* bring clipped time to samples and then to bytes */
5054       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5055       diff *= frame_size;
5056       GST_DEBUG_OBJECT (qtdemux,
5057           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5058           " bytes", GST_TIME_ARGS (cstop), diff);
5059       size -= diff;
5060     }
5061   }
5062
5063   if (offset != 0 || size != osize)
5064     gst_buffer_resize (buf, offset, size);
5065
5066   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5067   GST_BUFFER_PTS (buf) = pts;
5068   GST_BUFFER_DURATION (buf) = duration;
5069
5070   return buf;
5071
5072   /* dropped buffer */
5073 wrong_type:
5074   {
5075     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5076     return buf;
5077   }
5078 bad_frame_size:
5079   {
5080     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5081     return buf;
5082   }
5083 no_pts:
5084   {
5085     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5086     return buf;
5087   }
5088 clipped:
5089   {
5090     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5091     gst_buffer_unref (buf);
5092     return NULL;
5093   }
5094 }
5095
5096 /* the input buffer metadata must be writable,
5097  * but time/duration etc not yet set and need not be preserved */
5098 static GstBuffer *
5099 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5100     GstBuffer * buf)
5101 {
5102   GstMapInfo map;
5103   guint nsize = 0;
5104   gchar *str;
5105
5106   /* not many cases for now */
5107   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5108     /* send a one time dvd clut event */
5109     if (stream->pending_event && stream->pad)
5110       gst_pad_push_event (stream->pad, stream->pending_event);
5111     stream->pending_event = NULL;
5112   }
5113
5114   if (G_UNLIKELY (stream->subtype != FOURCC_text
5115           && stream->subtype != FOURCC_sbtl &&
5116           stream->subtype != FOURCC_subp)) {
5117     return buf;
5118   }
5119
5120   gst_buffer_map (buf, &map, GST_MAP_READ);
5121
5122   /* empty buffer is sent to terminate previous subtitle */
5123   if (map.size <= 2) {
5124     gst_buffer_unmap (buf, &map);
5125     gst_buffer_unref (buf);
5126     return NULL;
5127   }
5128   if (stream->subtype == FOURCC_subp) {
5129     /* That's all the processing needed for subpictures */
5130     gst_buffer_unmap (buf, &map);
5131     return buf;
5132   }
5133
5134   nsize = GST_READ_UINT16_BE (map.data);
5135   nsize = MIN (nsize, map.size - 2);
5136
5137   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5138       nsize, map.size);
5139
5140   /* takes care of UTF-8 validation or UTF-16 recognition,
5141    * no other encoding expected */
5142   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5143   gst_buffer_unmap (buf, &map);
5144   if (str) {
5145     gst_buffer_unref (buf);
5146     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5147   } else {
5148     /* this should not really happen unless the subtitle is corrupted */
5149     gst_buffer_unref (buf);
5150     buf = NULL;
5151   }
5152
5153   /* FIXME ? convert optional subsequent style info to markup */
5154
5155   return buf;
5156 }
5157
5158 /* Sets a buffer's attributes properly and pushes it downstream.
5159  * Also checks for additional actions and custom processing that may
5160  * need to be done first.
5161  */
5162 static GstFlowReturn
5163 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5164     QtDemuxStream * stream, GstBuffer * buf,
5165     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5166     gboolean keyframe, GstClockTime position, guint64 byte_position)
5167 {
5168   GstFlowReturn ret = GST_FLOW_OK;
5169
5170   /* offset the timestamps according to the edit list */
5171
5172   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5173     gchar *url;
5174     GstMapInfo map;
5175
5176     gst_buffer_map (buf, &map, GST_MAP_READ);
5177     url = g_strndup ((gchar *) map.data, map.size);
5178     gst_buffer_unmap (buf, &map);
5179     if (url != NULL && strlen (url) != 0) {
5180       /* we have RTSP redirect now */
5181       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5182           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5183               gst_structure_new ("redirect",
5184                   "new-location", G_TYPE_STRING, url, NULL)));
5185       qtdemux->posted_redirect = TRUE;
5186     } else {
5187       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5188           "posting");
5189     }
5190     g_free (url);
5191   }
5192
5193   /* position reporting */
5194   if (qtdemux->segment.rate >= 0) {
5195     qtdemux->segment.position = position;
5196     gst_qtdemux_sync_streams (qtdemux);
5197   }
5198
5199   if (G_UNLIKELY (!stream->pad)) {
5200     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5201     gst_buffer_unref (buf);
5202     goto exit;
5203   }
5204
5205   /* send out pending buffers */
5206   while (stream->buffers) {
5207     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5208
5209     if (G_UNLIKELY (stream->discont)) {
5210       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5211       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5212       stream->discont = FALSE;
5213     } else {
5214       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5215     }
5216
5217     gst_pad_push (stream->pad, buffer);
5218
5219     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5220   }
5221
5222   /* we're going to modify the metadata */
5223   buf = gst_buffer_make_writable (buf);
5224
5225   if (G_UNLIKELY (stream->need_process))
5226     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5227
5228   if (!buf) {
5229     goto exit;
5230   }
5231
5232   GST_BUFFER_DTS (buf) = dts;
5233   GST_BUFFER_PTS (buf) = pts;
5234   GST_BUFFER_DURATION (buf) = duration;
5235   GST_BUFFER_OFFSET (buf) = -1;
5236   GST_BUFFER_OFFSET_END (buf) = -1;
5237
5238   if (G_UNLIKELY (stream->rgb8_palette))
5239     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5240
5241   if (G_UNLIKELY (stream->padding)) {
5242     gst_buffer_resize (buf, stream->padding, -1);
5243   }
5244 #if 0
5245   if (G_UNLIKELY (qtdemux->element_index)) {
5246     GstClockTime stream_time;
5247
5248     stream_time =
5249         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5250         timestamp);
5251     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5252       GST_LOG_OBJECT (qtdemux,
5253           "adding association %" GST_TIME_FORMAT "-> %"
5254           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5255       gst_index_add_association (qtdemux->element_index,
5256           qtdemux->index_id,
5257           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5258           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5259           GST_FORMAT_BYTES, byte_position, NULL);
5260     }
5261   }
5262 #endif
5263
5264   if (stream->need_clip)
5265     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5266
5267   if (G_UNLIKELY (buf == NULL))
5268     goto exit;
5269
5270   if (G_UNLIKELY (stream->discont)) {
5271     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5272     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5273     stream->discont = FALSE;
5274   } else {
5275     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5276   }
5277
5278   if (!keyframe) {
5279     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5280     stream->on_keyframe = FALSE;
5281   } else {
5282     stream->on_keyframe = TRUE;
5283   }
5284
5285
5286   GST_LOG_OBJECT (qtdemux,
5287       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5288       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5289       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5290       GST_PAD_NAME (stream->pad));
5291
5292   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5293     GstStructure *crypto_info;
5294     QtDemuxCencSampleSetInfo *info =
5295         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5296     gint index;
5297     GstEvent *event;
5298
5299     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5300       gst_pad_push_event (stream->pad, event);
5301     }
5302
5303     if (qtdemux->cenc_aux_info_offset > 0 && info->crypto_info == NULL) {
5304       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5305       gst_buffer_unref (buf);
5306       goto exit;
5307     }
5308
5309     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
5310     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5311       /* steal structure from array */
5312       crypto_info = g_ptr_array_index (info->crypto_info, index);
5313       g_ptr_array_index (info->crypto_info, index) = NULL;
5314       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
5315       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5316         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5317     }
5318   }
5319
5320   ret = gst_pad_push (stream->pad, buf);
5321
5322   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5323     /* mark position in stream, we'll need this to know when to send GAP event */
5324     stream->segment.position = pts + duration;
5325   }
5326
5327 exit:
5328   return ret;
5329 }
5330
5331 static const QtDemuxRandomAccessEntry *
5332 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5333     GstClockTime pos, gboolean after)
5334 {
5335   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5336   guint n_entries = stream->n_ra_entries;
5337   guint i;
5338
5339   /* we assume the table is sorted */
5340   for (i = 0; i < n_entries; ++i) {
5341     if (entries[i].ts > pos)
5342       break;
5343   }
5344
5345   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5346    * probably okay to assume that the index lists the very first fragment */
5347   if (i == 0)
5348     return &entries[0];
5349
5350   if (after)
5351     return &entries[i];
5352   else
5353     return &entries[i - 1];
5354 }
5355
5356 static gboolean
5357 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5358 {
5359   const QtDemuxRandomAccessEntry *best_entry = NULL;
5360   guint i;
5361
5362   GST_OBJECT_LOCK (qtdemux);
5363
5364   g_assert (qtdemux->n_streams > 0);
5365
5366   for (i = 0; i < qtdemux->n_streams; i++) {
5367     const QtDemuxRandomAccessEntry *entry;
5368     QtDemuxStream *stream;
5369     gboolean is_audio_or_video;
5370
5371     stream = qtdemux->streams[i];
5372
5373     g_free (stream->samples);
5374     stream->samples = NULL;
5375     stream->n_samples = 0;
5376     stream->stbl_index = -1;    /* no samples have yet been parsed */
5377     stream->sample_index = -1;
5378
5379     if (stream->ra_entries == NULL)
5380       continue;
5381
5382     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5383       is_audio_or_video = TRUE;
5384     else
5385       is_audio_or_video = FALSE;
5386
5387     entry =
5388         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5389         stream->time_position, !is_audio_or_video);
5390
5391     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5392         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5393
5394     stream->pending_seek = entry;
5395
5396     /* decide position to jump to just based on audio/video tracks, not subs */
5397     if (!is_audio_or_video)
5398       continue;
5399
5400     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5401       best_entry = entry;
5402   }
5403
5404   if (best_entry == NULL) {
5405     GST_OBJECT_UNLOCK (qtdemux);
5406     return FALSE;
5407   }
5408
5409   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5410       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5411       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5412       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5413
5414   qtdemux->moof_offset = best_entry->moof_offset;
5415
5416   qtdemux_add_fragmented_samples (qtdemux);
5417
5418   GST_OBJECT_UNLOCK (qtdemux);
5419   return TRUE;
5420 }
5421
5422 static GstFlowReturn
5423 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5424 {
5425   GstFlowReturn ret = GST_FLOW_OK;
5426   GstBuffer *buf = NULL;
5427   QtDemuxStream *stream;
5428   GstClockTime min_time;
5429   guint64 offset = 0;
5430   GstClockTime dts = GST_CLOCK_TIME_NONE;
5431   GstClockTime pts = GST_CLOCK_TIME_NONE;
5432   GstClockTime duration = 0;
5433   gboolean keyframe = FALSE;
5434   guint sample_size = 0;
5435   gboolean empty = 0;
5436   guint size;
5437   gint index;
5438   gint i;
5439
5440   gst_qtdemux_push_pending_newsegment (qtdemux);
5441
5442   if (qtdemux->fragmented_seek_pending) {
5443     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5444     gst_qtdemux_do_fragmented_seek (qtdemux);
5445     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5446     qtdemux->fragmented_seek_pending = FALSE;
5447   }
5448
5449   /* Figure out the next stream sample to output, min_time is expressed in
5450    * global time and runs over the edit list segments. */
5451   min_time = G_MAXUINT64;
5452   index = -1;
5453   for (i = 0; i < qtdemux->n_streams; i++) {
5454     GstClockTime position;
5455
5456     stream = qtdemux->streams[i];
5457     position = stream->time_position;
5458
5459     /* position of -1 is EOS */
5460     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5461       min_time = position;
5462       index = i;
5463     }
5464   }
5465   /* all are EOS */
5466   if (G_UNLIKELY (index == -1)) {
5467     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5468     goto eos;
5469   }
5470
5471   /* check for segment end */
5472   if (G_UNLIKELY (qtdemux->segment.stop != -1
5473           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5474               || (qtdemux->segment.rate < 0
5475                   && qtdemux->segment.start > min_time))
5476           && qtdemux->streams[index]->on_keyframe)) {
5477     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5478     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5479     goto eos_stream;
5480   }
5481
5482   /* gap events for subtitle streams */
5483   for (i = 0; i < qtdemux->n_streams; i++) {
5484     stream = qtdemux->streams[i];
5485     if (stream->pad && (stream->subtype == FOURCC_subp
5486             || stream->subtype == FOURCC_text
5487             || stream->subtype == FOURCC_sbtl)) {
5488       /* send one second gap events until the stream catches up */
5489       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5490       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5491           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5492           stream->segment.position + GST_SECOND < min_time) {
5493         GstEvent *gap =
5494             gst_event_new_gap (stream->segment.position, GST_SECOND);
5495         gst_pad_push_event (stream->pad, gap);
5496         stream->segment.position += GST_SECOND;
5497       }
5498     }
5499   }
5500
5501   stream = qtdemux->streams[index];
5502   if (stream->new_caps) {
5503     gst_qtdemux_configure_stream (qtdemux, stream);
5504     qtdemux_do_allocation (qtdemux, stream);
5505   }
5506
5507   /* fetch info for the current sample of this stream */
5508   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5509               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5510     goto eos_stream;
5511
5512   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5513   if (G_UNLIKELY (qtdemux->
5514           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5515     if (stream->subtype == FOURCC_vide && !keyframe) {
5516       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5517       goto next;
5518     }
5519   }
5520
5521   GST_DEBUG_OBJECT (qtdemux,
5522       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5523       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5524       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5525       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5526
5527   if (G_UNLIKELY (empty)) {
5528     /* empty segment, push a gap and move to the next one */
5529     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5530     stream->segment.position = pts + duration;
5531     goto next;
5532   }
5533
5534   /* hmm, empty sample, skip and move to next sample */
5535   if (G_UNLIKELY (sample_size <= 0))
5536     goto next;
5537
5538   /* last pushed sample was out of boundary, goto next sample */
5539   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5540     goto next;
5541
5542   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5543     size = sample_size;
5544   } else {
5545     GST_DEBUG_OBJECT (qtdemux,
5546         "size %d larger than stream max_buffer_size %d, trimming",
5547         sample_size, stream->max_buffer_size);
5548     size =
5549         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5550   }
5551
5552   if (qtdemux->cenc_aux_info_offset > 0) {
5553     GstMapInfo map;
5554     GstByteReader br;
5555     GstBuffer *aux_info = NULL;
5556
5557     /* pull the data stored before the sample */
5558     ret =
5559         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5560         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5561     if (G_UNLIKELY (ret != GST_FLOW_OK))
5562       goto beach;
5563     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5564     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5565     gst_byte_reader_init (&br, map.data + 8, map.size);
5566     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5567             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5568       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5569       gst_buffer_unmap (aux_info, &map);
5570       gst_buffer_unref (aux_info);
5571       ret = GST_FLOW_ERROR;
5572       goto beach;
5573     }
5574     gst_buffer_unmap (aux_info, &map);
5575     gst_buffer_unref (aux_info);
5576   }
5577
5578   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5579       offset);
5580
5581   if (stream->use_allocator) {
5582     /* if we have a per-stream allocator, use it */
5583     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5584   }
5585
5586   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5587       size, &buf);
5588   if (G_UNLIKELY (ret != GST_FLOW_OK))
5589     goto beach;
5590
5591   if (size != sample_size) {
5592     pts += gst_util_uint64_scale_int (GST_SECOND,
5593         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5594     dts += gst_util_uint64_scale_int (GST_SECOND,
5595         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5596     duration = gst_util_uint64_scale_int (GST_SECOND,
5597         size / stream->bytes_per_frame, stream->timescale);
5598   }
5599
5600   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5601       dts, pts, duration, keyframe, min_time, offset);
5602
5603   if (size != sample_size) {
5604     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5605     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5606
5607     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5608         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5609     if (time_position >= segment->media_start) {
5610       /* inside the segment, update time_position, looks very familiar to
5611        * GStreamer segments, doesn't it? */
5612       stream->time_position = (time_position - segment->media_start) +
5613           segment->time;
5614     } else {
5615       /* not yet in segment, time does not yet increment. This means
5616        * that we are still prerolling keyframes to the decoder so it can
5617        * decode the first sample of the segment. */
5618       stream->time_position = segment->time;
5619     }
5620   }
5621
5622   /* combine flows */
5623   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5624   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5625    * we have no more data for the pad to push */
5626   if (ret == GST_FLOW_EOS)
5627     ret = GST_FLOW_OK;
5628
5629   stream->offset_in_sample += size;
5630   if (stream->offset_in_sample >= sample_size) {
5631     gst_qtdemux_advance_sample (qtdemux, stream);
5632   }
5633   goto beach;
5634
5635 next:
5636   gst_qtdemux_advance_sample (qtdemux, stream);
5637
5638 beach:
5639   return ret;
5640
5641   /* special cases */
5642 eos:
5643   {
5644     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5645     ret = GST_FLOW_EOS;
5646     goto beach;
5647   }
5648 eos_stream:
5649   {
5650     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5651     /* EOS will be raised if all are EOS */
5652     ret = GST_FLOW_OK;
5653     goto beach;
5654   }
5655 }
5656
5657 static void
5658 gst_qtdemux_loop (GstPad * pad)
5659 {
5660   GstQTDemux *qtdemux;
5661   guint64 cur_offset;
5662   GstFlowReturn ret;
5663
5664   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5665
5666   cur_offset = qtdemux->offset;
5667   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5668       cur_offset, qt_demux_state_string (qtdemux->state));
5669
5670   switch (qtdemux->state) {
5671     case QTDEMUX_STATE_INITIAL:
5672     case QTDEMUX_STATE_HEADER:
5673       ret = gst_qtdemux_loop_state_header (qtdemux);
5674       break;
5675     case QTDEMUX_STATE_MOVIE:
5676       ret = gst_qtdemux_loop_state_movie (qtdemux);
5677       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5678         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5679       }
5680       break;
5681     default:
5682       /* ouch */
5683       goto invalid_state;
5684   }
5685
5686   /* if something went wrong, pause */
5687   if (ret != GST_FLOW_OK)
5688     goto pause;
5689
5690 done:
5691   gst_object_unref (qtdemux);
5692   return;
5693
5694   /* ERRORS */
5695 invalid_state:
5696   {
5697     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5698         (NULL), ("streaming stopped, invalid state"));
5699     gst_pad_pause_task (pad);
5700     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5701     goto done;
5702   }
5703 pause:
5704   {
5705     const gchar *reason = gst_flow_get_name (ret);
5706
5707     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5708
5709     gst_pad_pause_task (pad);
5710
5711     /* fatal errors need special actions */
5712     /* check EOS */
5713     if (ret == GST_FLOW_EOS) {
5714       if (qtdemux->n_streams == 0) {
5715         /* we have no streams, post an error */
5716         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5717       }
5718       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5719         gint64 stop;
5720
5721         if ((stop = qtdemux->segment.stop) == -1)
5722           stop = qtdemux->segment.duration;
5723
5724         if (qtdemux->segment.rate >= 0) {
5725           GstMessage *message;
5726           GstEvent *event;
5727
5728           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5729           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5730               GST_FORMAT_TIME, stop);
5731           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5732           if (qtdemux->segment_seqnum) {
5733             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5734             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5735           }
5736           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5737           gst_qtdemux_push_event (qtdemux, event);
5738         } else {
5739           GstMessage *message;
5740           GstEvent *event;
5741
5742           /*  For Reverse Playback */
5743           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5744           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5745               GST_FORMAT_TIME, qtdemux->segment.start);
5746           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5747               qtdemux->segment.start);
5748           if (qtdemux->segment_seqnum) {
5749             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5750             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5751           }
5752           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5753           gst_qtdemux_push_event (qtdemux, event);
5754         }
5755       } else {
5756         GstEvent *event;
5757
5758         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5759         event = gst_event_new_eos ();
5760         if (qtdemux->segment_seqnum)
5761           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5762         gst_qtdemux_push_event (qtdemux, event);
5763       }
5764     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5765       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5766           (NULL), ("streaming stopped, reason %s", reason));
5767       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5768     }
5769     goto done;
5770   }
5771 }
5772
5773 /*
5774  * has_next_entry
5775  *
5776  * Returns if there are samples to be played.
5777  */
5778 static gboolean
5779 has_next_entry (GstQTDemux * demux)
5780 {
5781   QtDemuxStream *stream;
5782   int i;
5783
5784   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5785
5786   for (i = 0; i < demux->n_streams; i++) {
5787     stream = demux->streams[i];
5788
5789     if (stream->sample_index == -1) {
5790       stream->sample_index = 0;
5791       stream->offset_in_sample = 0;
5792     }
5793
5794     if (stream->sample_index >= stream->n_samples) {
5795       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5796       continue;
5797     }
5798     GST_DEBUG_OBJECT (demux, "Found a sample");
5799     return TRUE;
5800   }
5801
5802   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5803   return FALSE;
5804 }
5805
5806 /*
5807  * next_entry_size
5808  *
5809  * Returns the size of the first entry at the current offset.
5810  * If -1, there are none (which means EOS or empty file).
5811  */
5812 static guint64
5813 next_entry_size (GstQTDemux * demux)
5814 {
5815   QtDemuxStream *stream;
5816   int i;
5817   int smallidx = -1;
5818   guint64 smalloffs = (guint64) - 1;
5819   QtDemuxSample *sample;
5820
5821   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5822       demux->offset);
5823
5824   for (i = 0; i < demux->n_streams; i++) {
5825     stream = demux->streams[i];
5826
5827     if (stream->sample_index == -1) {
5828       stream->sample_index = 0;
5829       stream->offset_in_sample = 0;
5830     }
5831
5832     if (stream->sample_index >= stream->n_samples) {
5833       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5834       continue;
5835     }
5836
5837     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5838       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5839           stream->sample_index);
5840       return -1;
5841     }
5842
5843     sample = &stream->samples[stream->sample_index];
5844
5845     GST_LOG_OBJECT (demux,
5846         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5847         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5848         sample->offset, sample->size);
5849
5850     if (((smalloffs == -1)
5851             || (sample->offset < smalloffs)) && (sample->size)) {
5852       smallidx = i;
5853       smalloffs = sample->offset;
5854     }
5855   }
5856
5857   GST_LOG_OBJECT (demux,
5858       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5859       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5860
5861   if (smallidx == -1)
5862     return -1;
5863
5864   stream = demux->streams[smallidx];
5865   sample = &stream->samples[stream->sample_index];
5866
5867   if (sample->offset >= demux->offset) {
5868     demux->todrop = sample->offset - demux->offset;
5869     return sample->size + demux->todrop;
5870   }
5871
5872   GST_DEBUG_OBJECT (demux,
5873       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5874   return -1;
5875 }
5876
5877 static void
5878 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5879 {
5880   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5881
5882   gst_element_post_message (GST_ELEMENT_CAST (demux),
5883       gst_message_new_element (GST_OBJECT_CAST (demux),
5884           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5885 }
5886
5887 static gboolean
5888 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5889 {
5890   GstEvent *event;
5891   gboolean res = 0;
5892
5893   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5894
5895   event =
5896       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5897       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5898       GST_SEEK_TYPE_NONE, -1);
5899
5900   /* store seqnum to drop flush events, they don't need to reach downstream */
5901   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5902   res = gst_pad_push_event (demux->sinkpad, event);
5903   demux->offset_seek_seqnum = 0;
5904
5905   return res;
5906 }
5907
5908 /* check for seekable upstream, above and beyond a mere query */
5909 static void
5910 gst_qtdemux_check_seekability (GstQTDemux * demux)
5911 {
5912   GstQuery *query;
5913   gboolean seekable = FALSE;
5914   gint64 start = -1, stop = -1;
5915
5916   if (demux->upstream_size)
5917     return;
5918
5919   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5920   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5921     GST_DEBUG_OBJECT (demux, "seeking query failed");
5922     goto done;
5923   }
5924
5925   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5926
5927   /* try harder to query upstream size if we didn't get it the first time */
5928   if (seekable && stop == -1) {
5929     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5930     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5931   }
5932
5933   /* if upstream doesn't know the size, it's likely that it's not seekable in
5934    * practice even if it technically may be seekable */
5935   if (seekable && (start != 0 || stop <= start)) {
5936     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5937     seekable = FALSE;
5938   }
5939
5940 done:
5941   gst_query_unref (query);
5942
5943   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5944       G_GUINT64_FORMAT ")", seekable, start, stop);
5945   demux->upstream_seekable = seekable;
5946   demux->upstream_size = seekable ? stop : -1;
5947 }
5948
5949 static void
5950 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5951 {
5952   g_return_if_fail (bytes <= demux->todrop);
5953
5954   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5955   gst_adapter_flush (demux->adapter, bytes);
5956   demux->neededbytes -= bytes;
5957   demux->offset += bytes;
5958   demux->todrop -= bytes;
5959 }
5960
5961 static void
5962 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5963 {
5964   if (G_UNLIKELY (demux->pending_newsegment)) {
5965     gint i;
5966
5967     gst_qtdemux_push_pending_newsegment (demux);
5968     /* clear to send tags on all streams */
5969     for (i = 0; i < demux->n_streams; i++) {
5970       QtDemuxStream *stream;
5971       stream = demux->streams[i];
5972       gst_qtdemux_push_tags (demux, stream);
5973       if (stream->sparse) {
5974         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5975         gst_pad_push_event (stream->pad,
5976             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
5977       }
5978     }
5979   }
5980 }
5981
5982 static void
5983 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
5984     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
5985 {
5986   GstClockTime ts, dur;
5987   GstEvent *gap;
5988
5989   ts = pos;
5990   dur =
5991       stream->segments[segment_index].duration - (pos -
5992       stream->segments[segment_index].time);
5993   gap = gst_event_new_gap (ts, dur);
5994   stream->time_position += dur;
5995
5996   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
5997       "segment: %" GST_PTR_FORMAT, gap);
5998   gst_pad_push_event (stream->pad, gap);
5999 }
6000
6001 static void
6002 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6003     QtDemuxStream * stream)
6004 {
6005   gint i;
6006
6007   /* Push any initial gap segments before proceeding to the
6008    * 'real' data */
6009   for (i = 0; i < stream->n_segments; i++) {
6010     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6011
6012     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6013       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6014           stream->time_position);
6015     } else {
6016       /* Only support empty segment at the beginning followed by
6017        * one non-empty segment, this was checked when parsing the
6018        * edts atom, arriving here is unexpected */
6019       g_assert (i + 1 == stream->n_segments);
6020       break;
6021     }
6022   }
6023 }
6024
6025 static GstFlowReturn
6026 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6027 {
6028   GstQTDemux *demux;
6029
6030   demux = GST_QTDEMUX (parent);
6031
6032   GST_DEBUG_OBJECT (demux,
6033       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6034       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT,
6035       GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6036       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6037       gst_buffer_get_size (inbuf));
6038
6039   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6040     gint i;
6041
6042     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6043
6044     for (i = 0; i < demux->n_streams; i++) {
6045       demux->streams[i]->discont = TRUE;
6046     }
6047
6048     /* Reverse fragmented playback, need to flush all we have before
6049      * consuming a new fragment.
6050      * The samples array have the timestamps calculated by accumulating the
6051      * durations but this won't work for reverse playback of fragments as
6052      * the timestamps of a subsequent fragment should be smaller than the
6053      * previously received one. */
6054     if (demux->fragmented && demux->segment.rate < 0) {
6055       gst_qtdemux_process_adapter (demux, TRUE);
6056       for (i = 0; i < demux->n_streams; i++)
6057         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6058     }
6059   }
6060
6061   gst_adapter_push (demux->adapter, inbuf);
6062
6063   GST_DEBUG_OBJECT (demux,
6064       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6065       demux->neededbytes, gst_adapter_available (demux->adapter));
6066
6067   return gst_qtdemux_process_adapter (demux, FALSE);
6068 }
6069
6070 static GstFlowReturn
6071 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6072 {
6073   GstFlowReturn ret = GST_FLOW_OK;
6074
6075   /* we never really mean to buffer that much */
6076   if (demux->neededbytes == -1) {
6077     goto eos;
6078   }
6079
6080   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6081       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6082
6083     GST_DEBUG_OBJECT (demux,
6084         "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
6085         qt_demux_state_string (demux->state), demux->neededbytes,
6086         demux->offset);
6087
6088     switch (demux->state) {
6089       case QTDEMUX_STATE_INITIAL:{
6090         const guint8 *data;
6091         guint32 fourcc;
6092         guint64 size;
6093
6094         gst_qtdemux_check_seekability (demux);
6095
6096         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6097
6098         /* get fourcc/length, set neededbytes */
6099         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6100             &size, &fourcc);
6101         gst_adapter_unmap (demux->adapter);
6102         data = NULL;
6103         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6104             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6105         if (size == 0) {
6106           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6107               (_("This file is invalid and cannot be played.")),
6108               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6109                   GST_FOURCC_ARGS (fourcc)));
6110           ret = GST_FLOW_ERROR;
6111           break;
6112         }
6113         if (fourcc == FOURCC_mdat) {
6114           gint next_entry = next_entry_size (demux);
6115           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6116             /* we have the headers, start playback */
6117             demux->state = QTDEMUX_STATE_MOVIE;
6118             demux->neededbytes = next_entry;
6119             demux->mdatleft = size;
6120           } else {
6121             /* no headers yet, try to get them */
6122             guint bs;
6123             gboolean res;
6124             guint64 old, target;
6125
6126           buffer_data:
6127             old = demux->offset;
6128             target = old + size;
6129
6130             /* try to jump over the atom with a seek */
6131             /* only bother if it seems worth doing so,
6132              * and avoids possible upstream/server problems */
6133             if (demux->upstream_seekable &&
6134                 demux->upstream_size > 4 * (1 << 20)) {
6135               res = qtdemux_seek_offset (demux, target);
6136             } else {
6137               GST_DEBUG_OBJECT (demux, "skipping seek");
6138               res = FALSE;
6139             }
6140
6141             if (res) {
6142               GST_DEBUG_OBJECT (demux, "seek success");
6143               /* remember the offset fo the first mdat so we can seek back to it
6144                * after we have the headers */
6145               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6146                 demux->first_mdat = old;
6147                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6148                     demux->first_mdat);
6149               }
6150               /* seek worked, continue reading */
6151               demux->offset = target;
6152               demux->neededbytes = 16;
6153               demux->state = QTDEMUX_STATE_INITIAL;
6154             } else {
6155               /* seek failed, need to buffer */
6156               demux->offset = old;
6157               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6158               /* there may be multiple mdat (or alike) buffers */
6159               /* sanity check */
6160               if (demux->mdatbuffer)
6161                 bs = gst_buffer_get_size (demux->mdatbuffer);
6162               else
6163                 bs = 0;
6164               if (size + bs > 10 * (1 << 20))
6165                 goto no_moov;
6166               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6167               demux->neededbytes = size;
6168               if (!demux->mdatbuffer)
6169                 demux->mdatoffset = demux->offset;
6170             }
6171           }
6172         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6173           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6174               (_("This file is invalid and cannot be played.")),
6175               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6176                   GST_FOURCC_ARGS (fourcc), size));
6177           ret = GST_FLOW_ERROR;
6178           break;
6179         } else {
6180           /* this means we already started buffering and still no moov header,
6181            * let's continue buffering everything till we get moov */
6182           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6183                   || fourcc == FOURCC_moof))
6184             goto buffer_data;
6185           demux->neededbytes = size;
6186           demux->state = QTDEMUX_STATE_HEADER;
6187         }
6188         break;
6189       }
6190       case QTDEMUX_STATE_HEADER:{
6191         const guint8 *data;
6192         guint32 fourcc;
6193
6194         GST_DEBUG_OBJECT (demux, "In header");
6195
6196         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6197
6198         /* parse the header */
6199         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6200             &fourcc);
6201         if (fourcc == FOURCC_moov) {
6202           gint n;
6203
6204           /* in usual fragmented setup we could try to scan for more
6205            * and end up at the the moov (after mdat) again */
6206           if (demux->got_moov && demux->n_streams > 0 &&
6207               (!demux->fragmented
6208                   || demux->last_moov_offset == demux->offset)) {
6209             GST_DEBUG_OBJECT (demux,
6210                 "Skipping moov atom as we have (this) one already");
6211           } else {
6212             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6213
6214             if (demux->got_moov && demux->fragmented) {
6215               GST_DEBUG_OBJECT (demux,
6216                   "Got a second moov, clean up data from old one");
6217               if (demux->moov_node)
6218                 g_node_destroy (demux->moov_node);
6219               demux->moov_node = NULL;
6220               demux->moov_node_compressed = NULL;
6221             } else {
6222               /* prepare newsegment to send when streaming actually starts */
6223               if (!demux->pending_newsegment) {
6224                 demux->pending_newsegment =
6225                     gst_event_new_segment (&demux->segment);
6226                 if (demux->segment_seqnum)
6227                   gst_event_set_seqnum (demux->pending_newsegment,
6228                       demux->segment_seqnum);
6229               }
6230             }
6231
6232             demux->last_moov_offset = demux->offset;
6233
6234             qtdemux_parse_moov (demux, data, demux->neededbytes);
6235             qtdemux_node_dump (demux, demux->moov_node);
6236             qtdemux_parse_tree (demux);
6237             qtdemux_prepare_streams (demux);
6238             if (!demux->got_moov)
6239               qtdemux_expose_streams (demux);
6240             else {
6241
6242               for (n = 0; n < demux->n_streams; n++) {
6243                 QtDemuxStream *stream = demux->streams[n];
6244
6245                 gst_qtdemux_configure_stream (demux, stream);
6246               }
6247             }
6248
6249             demux->got_moov = TRUE;
6250             gst_qtdemux_check_send_pending_segment (demux);
6251
6252             /* fragmented streams headers shouldn't contain edts atoms */
6253             if (!demux->fragmented) {
6254               for (n = 0; n < demux->n_streams; n++) {
6255                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6256                     demux->streams[n]);
6257               }
6258             }
6259
6260             g_node_destroy (demux->moov_node);
6261             demux->moov_node = NULL;
6262             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6263           }
6264         } else if (fourcc == FOURCC_moof) {
6265           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6266             guint64 dist = 0;
6267             GstClockTime prev_pts;
6268             guint64 prev_offset;
6269
6270             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6271
6272             /*
6273              * The timestamp of the moof buffer is relevant as some scenarios
6274              * won't have the initial timestamp in the atoms. Whenever a new
6275              * buffer has started, we get that buffer's PTS and use it as a base
6276              * timestamp for the trun entries.
6277              *
6278              * To keep track of the current buffer timestamp and starting point
6279              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6280              * from the beggining of the buffer, with the distance and demux->offset
6281              * we know if it is still the same buffer or not.
6282              */
6283             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6284             prev_offset = demux->offset - dist;
6285             if (demux->fragment_start_offset == -1
6286                 || prev_offset > demux->fragment_start_offset) {
6287               demux->fragment_start_offset = prev_offset;
6288               demux->fragment_start = prev_pts;
6289               GST_DEBUG_OBJECT (demux,
6290                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6291                   GST_TIME_FORMAT, demux->fragment_start_offset,
6292                   GST_TIME_ARGS (demux->fragment_start));
6293             }
6294
6295             demux->moof_offset = demux->offset;
6296             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6297                     demux->offset, NULL)) {
6298               gst_adapter_unmap (demux->adapter);
6299               ret = GST_FLOW_ERROR;
6300               goto done;
6301             }
6302             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6303             if (demux->mss_mode && !demux->exposed) {
6304               if (!demux->pending_newsegment) {
6305                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6306                 demux->pending_newsegment =
6307                     gst_event_new_segment (&demux->segment);
6308                 if (demux->segment_seqnum)
6309                   gst_event_set_seqnum (demux->pending_newsegment,
6310                       demux->segment_seqnum);
6311               }
6312               qtdemux_expose_streams (demux);
6313             }
6314           } else {
6315             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6316           }
6317         } else if (fourcc == FOURCC_ftyp) {
6318           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6319           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6320         } else if (fourcc == FOURCC_uuid) {
6321           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6322           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6323         } else if (fourcc == FOURCC_sidx) {
6324           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6325           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6326         } else {
6327           GST_WARNING_OBJECT (demux,
6328               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6329               GST_FOURCC_ARGS (fourcc));
6330           /* Let's jump that one and go back to initial state */
6331         }
6332         gst_adapter_unmap (demux->adapter);
6333         data = NULL;
6334
6335         if (demux->mdatbuffer && demux->n_streams) {
6336           gsize remaining_data_size = 0;
6337
6338           /* the mdat was before the header */
6339           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6340               demux->n_streams, demux->mdatbuffer);
6341           /* restore our adapter/offset view of things with upstream;
6342            * put preceding buffered data ahead of current moov data.
6343            * This should also handle evil mdat, moov, mdat cases and alike */
6344           gst_adapter_flush (demux->adapter, demux->neededbytes);
6345
6346           /* Store any remaining data after the mdat for later usage */
6347           remaining_data_size = gst_adapter_available (demux->adapter);
6348           if (remaining_data_size > 0) {
6349             g_assert (demux->restoredata_buffer == NULL);
6350             demux->restoredata_buffer =
6351                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6352             demux->restoredata_offset = demux->offset + demux->neededbytes;
6353             GST_DEBUG_OBJECT (demux,
6354                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6355                 G_GUINT64_FORMAT, remaining_data_size,
6356                 demux->restoredata_offset);
6357           }
6358
6359           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6360           demux->mdatbuffer = NULL;
6361           demux->offset = demux->mdatoffset;
6362           demux->neededbytes = next_entry_size (demux);
6363           demux->state = QTDEMUX_STATE_MOVIE;
6364           demux->mdatleft = gst_adapter_available (demux->adapter);
6365         } else {
6366           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6367           gst_adapter_flush (demux->adapter, demux->neededbytes);
6368
6369           /* only go back to the mdat if there are samples to play */
6370           if (demux->got_moov && demux->first_mdat != -1
6371               && has_next_entry (demux)) {
6372             gboolean res;
6373
6374             /* we need to seek back */
6375             res = qtdemux_seek_offset (demux, demux->first_mdat);
6376             if (res) {
6377               demux->offset = demux->first_mdat;
6378             } else {
6379               GST_DEBUG_OBJECT (demux, "Seek back failed");
6380             }
6381           } else {
6382             demux->offset += demux->neededbytes;
6383           }
6384           demux->neededbytes = 16;
6385           demux->state = QTDEMUX_STATE_INITIAL;
6386         }
6387
6388         break;
6389       }
6390       case QTDEMUX_STATE_BUFFER_MDAT:{
6391         GstBuffer *buf;
6392         guint8 fourcc[4];
6393
6394         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6395             demux->offset);
6396         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6397         gst_buffer_extract (buf, 0, fourcc, 4);
6398         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6399             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6400         if (demux->mdatbuffer)
6401           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6402         else
6403           demux->mdatbuffer = buf;
6404         demux->offset += demux->neededbytes;
6405         demux->neededbytes = 16;
6406         demux->state = QTDEMUX_STATE_INITIAL;
6407         gst_qtdemux_post_progress (demux, 1, 1);
6408
6409         break;
6410       }
6411       case QTDEMUX_STATE_MOVIE:{
6412         QtDemuxStream *stream = NULL;
6413         QtDemuxSample *sample;
6414         int i = -1;
6415         GstClockTime dts, pts, duration;
6416         gboolean keyframe;
6417
6418         GST_DEBUG_OBJECT (demux,
6419             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6420
6421         if (demux->fragmented) {
6422           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6423               demux->mdatleft);
6424           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6425             /* if needed data starts within this atom,
6426              * then it should not exceed this atom */
6427             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6428               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6429                   (_("This file is invalid and cannot be played.")),
6430                   ("sample data crosses atom boundary"));
6431               ret = GST_FLOW_ERROR;
6432               break;
6433             }
6434             demux->mdatleft -= demux->neededbytes;
6435           } else {
6436             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6437             /* so we are dropping more than left in this atom */
6438             gst_qtdemux_drop_data (demux, demux->mdatleft);
6439             demux->mdatleft = 0;
6440
6441             /* need to resume atom parsing so we do not miss any other pieces */
6442             demux->state = QTDEMUX_STATE_INITIAL;
6443             demux->neededbytes = 16;
6444
6445             /* check if there was any stored post mdat data from previous buffers */
6446             if (demux->restoredata_buffer) {
6447               g_assert (gst_adapter_available (demux->adapter) == 0);
6448
6449               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6450               demux->restoredata_buffer = NULL;
6451               demux->offset = demux->restoredata_offset;
6452             }
6453
6454             break;
6455           }
6456         }
6457
6458         if (demux->todrop) {
6459           if (demux->cenc_aux_info_offset > 0) {
6460             GstByteReader br;
6461             const guint8 *data;
6462
6463             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6464             data = gst_adapter_map (demux->adapter, demux->todrop);
6465             gst_byte_reader_init (&br, data + 8, demux->todrop);
6466             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6467                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6468               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6469               ret = GST_FLOW_ERROR;
6470               gst_adapter_unmap (demux->adapter);
6471               g_free (demux->cenc_aux_info_sizes);
6472               demux->cenc_aux_info_sizes = NULL;
6473               goto done;
6474             }
6475             demux->cenc_aux_info_offset = 0;
6476             g_free (demux->cenc_aux_info_sizes);
6477             demux->cenc_aux_info_sizes = NULL;
6478             gst_adapter_unmap (demux->adapter);
6479           }
6480           gst_qtdemux_drop_data (demux, demux->todrop);
6481         }
6482
6483         /* first buffer? */
6484         /* initial newsegment sent here after having added pads,
6485          * possible others in sink_event */
6486         gst_qtdemux_check_send_pending_segment (demux);
6487
6488         /* Figure out which stream this packet belongs to */
6489         for (i = 0; i < demux->n_streams; i++) {
6490           stream = demux->streams[i];
6491           if (stream->sample_index >= stream->n_samples)
6492             continue;
6493           GST_LOG_OBJECT (demux,
6494               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6495               " / size:%d)", i, stream->sample_index,
6496               stream->samples[stream->sample_index].offset,
6497               stream->samples[stream->sample_index].size);
6498
6499           if (stream->samples[stream->sample_index].offset == demux->offset)
6500             break;
6501         }
6502
6503         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6504           goto unknown_stream;
6505
6506         if (stream->new_caps) {
6507           gst_qtdemux_configure_stream (demux, stream);
6508         }
6509
6510         /* Put data in a buffer, set timestamps, caps, ... */
6511         sample = &stream->samples[stream->sample_index];
6512
6513         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6514           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6515               GST_FOURCC_ARGS (stream->fourcc));
6516
6517           dts = QTSAMPLE_DTS (stream, sample);
6518           pts = QTSAMPLE_PTS (stream, sample);
6519           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6520           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6521
6522           /* check for segment end */
6523           if (G_UNLIKELY (demux->segment.stop != -1
6524                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6525             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6526             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6527
6528             /* skip this data, stream is EOS */
6529             gst_adapter_flush (demux->adapter, demux->neededbytes);
6530
6531             /* check if all streams are eos */
6532             ret = GST_FLOW_EOS;
6533             for (i = 0; i < demux->n_streams; i++) {
6534               if (!STREAM_IS_EOS (demux->streams[i])) {
6535                 ret = GST_FLOW_OK;
6536                 break;
6537               }
6538             }
6539
6540             if (ret == GST_FLOW_EOS) {
6541               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6542               goto eos;
6543             }
6544           } else {
6545             GstBuffer *outbuf;
6546
6547             outbuf =
6548                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6549
6550             /* FIXME: should either be an assert or a plain check */
6551             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6552
6553             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6554                 dts, pts, duration, keyframe, dts, demux->offset);
6555           }
6556
6557           /* combine flows */
6558           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6559           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6560             goto non_ok_unlinked_flow;
6561         } else {
6562           /* skip this data, stream is EOS */
6563           gst_adapter_flush (demux->adapter, demux->neededbytes);
6564         }
6565
6566         stream->sample_index++;
6567         stream->offset_in_sample = 0;
6568
6569         /* update current offset and figure out size of next buffer */
6570         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6571             demux->offset, demux->neededbytes);
6572         demux->offset += demux->neededbytes;
6573         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6574             demux->offset);
6575
6576         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6577           if (demux->fragmented) {
6578             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6579             /* there may be more to follow, only finish this atom */
6580             demux->todrop = demux->mdatleft;
6581             demux->neededbytes = demux->todrop;
6582             break;
6583           }
6584           goto eos;
6585         }
6586         break;
6587       }
6588       default:
6589         goto invalid_state;
6590     }
6591   }
6592
6593   /* when buffering movie data, at least show user something is happening */
6594   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6595       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6596     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6597         demux->neededbytes);
6598   }
6599 done:
6600
6601   return ret;
6602
6603   /* ERRORS */
6604 non_ok_unlinked_flow:
6605   {
6606     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6607         gst_flow_get_name (ret));
6608     return ret;
6609   }
6610 unknown_stream:
6611   {
6612     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6613     ret = GST_FLOW_ERROR;
6614     goto done;
6615   }
6616 eos:
6617   {
6618     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6619     ret = GST_FLOW_EOS;
6620     goto done;
6621   }
6622 invalid_state:
6623   {
6624     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6625         (NULL), ("qtdemuxer invalid state %d", demux->state));
6626     ret = GST_FLOW_ERROR;
6627     goto done;
6628   }
6629 no_moov:
6630   {
6631     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6632         (NULL), ("no 'moov' atom within the first 10 MB"));
6633     ret = GST_FLOW_ERROR;
6634     goto done;
6635   }
6636 }
6637
6638 static gboolean
6639 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6640 {
6641   GstQuery *query;
6642   gboolean pull_mode;
6643
6644   query = gst_query_new_scheduling ();
6645
6646   if (!gst_pad_peer_query (sinkpad, query)) {
6647     gst_query_unref (query);
6648     goto activate_push;
6649   }
6650
6651   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6652       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6653   gst_query_unref (query);
6654
6655   if (!pull_mode)
6656     goto activate_push;
6657
6658   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6659   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6660
6661 activate_push:
6662   {
6663     GST_DEBUG_OBJECT (sinkpad, "activating push");
6664     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6665   }
6666 }
6667
6668 static gboolean
6669 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6670     GstPadMode mode, gboolean active)
6671 {
6672   gboolean res;
6673   GstQTDemux *demux = GST_QTDEMUX (parent);
6674
6675   switch (mode) {
6676     case GST_PAD_MODE_PUSH:
6677       demux->pullbased = FALSE;
6678       res = TRUE;
6679       break;
6680     case GST_PAD_MODE_PULL:
6681       if (active) {
6682         demux->pullbased = TRUE;
6683         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6684             sinkpad, NULL);
6685       } else {
6686         res = gst_pad_stop_task (sinkpad);
6687       }
6688       break;
6689     default:
6690       res = FALSE;
6691       break;
6692   }
6693   return res;
6694 }
6695
6696 #ifdef HAVE_ZLIB
6697 static void *
6698 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6699 {
6700   return g_malloc (items * size);
6701 }
6702
6703 static void
6704 qtdemux_zfree (void *opaque, void *addr)
6705 {
6706   g_free (addr);
6707 }
6708
6709 static void *
6710 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6711 {
6712   guint8 *buffer;
6713   z_stream *z;
6714   int ret;
6715
6716   z = g_new0 (z_stream, 1);
6717   z->zalloc = qtdemux_zalloc;
6718   z->zfree = qtdemux_zfree;
6719   z->opaque = NULL;
6720
6721   z->next_in = z_buffer;
6722   z->avail_in = z_length;
6723
6724   buffer = (guint8 *) g_malloc (length);
6725   ret = inflateInit (z);
6726   while (z->avail_in > 0) {
6727     if (z->avail_out == 0) {
6728       length += 1024;
6729       buffer = (guint8 *) g_realloc (buffer, length);
6730       z->next_out = buffer + z->total_out;
6731       z->avail_out = 1024;
6732     }
6733     ret = inflate (z, Z_SYNC_FLUSH);
6734     if (ret != Z_OK)
6735       break;
6736   }
6737   if (ret != Z_STREAM_END) {
6738     g_warning ("inflate() returned %d", ret);
6739   }
6740
6741   g_free (z);
6742   return buffer;
6743 }
6744 #endif /* HAVE_ZLIB */
6745
6746 static gboolean
6747 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6748 {
6749   GNode *cmov;
6750
6751   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6752
6753   /* counts as header data */
6754   qtdemux->header_size += length;
6755
6756   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6757   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6758
6759   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6760   if (cmov) {
6761     guint32 method;
6762     GNode *dcom;
6763     GNode *cmvd;
6764
6765     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6766     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6767     if (dcom == NULL || cmvd == NULL)
6768       goto invalid_compression;
6769
6770     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6771     switch (method) {
6772 #ifdef HAVE_ZLIB
6773       case FOURCC_zlib:{
6774         guint uncompressed_length;
6775         guint compressed_length;
6776         guint8 *buf;
6777
6778         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6779         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6780         GST_LOG ("length = %u", uncompressed_length);
6781
6782         buf =
6783             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6784             compressed_length, uncompressed_length);
6785
6786         qtdemux->moov_node_compressed = qtdemux->moov_node;
6787         qtdemux->moov_node = g_node_new (buf);
6788
6789         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6790             uncompressed_length);
6791         break;
6792       }
6793 #endif /* HAVE_ZLIB */
6794       default:
6795         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6796             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6797         break;
6798     }
6799   }
6800   return TRUE;
6801
6802   /* ERRORS */
6803 invalid_compression:
6804   {
6805     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6806     return FALSE;
6807   }
6808 }
6809
6810 static gboolean
6811 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6812     const guint8 * end)
6813 {
6814   while (G_UNLIKELY (buf < end)) {
6815     GNode *child;
6816     guint32 len;
6817
6818     if (G_UNLIKELY (buf + 4 > end)) {
6819       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6820       break;
6821     }
6822     len = QT_UINT32 (buf);
6823     if (G_UNLIKELY (len == 0)) {
6824       GST_LOG_OBJECT (qtdemux, "empty container");
6825       break;
6826     }
6827     if (G_UNLIKELY (len < 8)) {
6828       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6829       break;
6830     }
6831     if (G_UNLIKELY (len > (end - buf))) {
6832       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6833           (gint) (end - buf));
6834       break;
6835     }
6836
6837     child = g_node_new ((guint8 *) buf);
6838     g_node_append (node, child);
6839     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6840     qtdemux_parse_node (qtdemux, child, buf, len);
6841
6842     buf += len;
6843   }
6844   return TRUE;
6845 }
6846
6847 static gboolean
6848 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6849     GNode * xdxt)
6850 {
6851   int len = QT_UINT32 (xdxt->data);
6852   guint8 *buf = xdxt->data;
6853   guint8 *end = buf + len;
6854   GstBuffer *buffer;
6855
6856   /* skip size and type */
6857   buf += 8;
6858   end -= 8;
6859
6860   while (buf < end) {
6861     gint size;
6862     guint32 type;
6863
6864     size = QT_UINT32 (buf);
6865     type = QT_FOURCC (buf + 4);
6866
6867     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6868
6869     if (buf + size > end || size <= 0)
6870       break;
6871
6872     buf += 8;
6873     size -= 8;
6874
6875     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6876         GST_FOURCC_ARGS (type));
6877
6878     switch (type) {
6879       case FOURCC_tCtH:
6880         buffer = gst_buffer_new_and_alloc (size);
6881         gst_buffer_fill (buffer, 0, buf, size);
6882         stream->buffers = g_slist_append (stream->buffers, buffer);
6883         GST_LOG_OBJECT (qtdemux, "parsing theora header");
6884         break;
6885       case FOURCC_tCt_:
6886         buffer = gst_buffer_new_and_alloc (size);
6887         gst_buffer_fill (buffer, 0, buf, size);
6888         stream->buffers = g_slist_append (stream->buffers, buffer);
6889         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6890         break;
6891       case FOURCC_tCtC:
6892         buffer = gst_buffer_new_and_alloc (size);
6893         gst_buffer_fill (buffer, 0, buf, size);
6894         stream->buffers = g_slist_append (stream->buffers, buffer);
6895         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6896         break;
6897       default:
6898         GST_WARNING_OBJECT (qtdemux,
6899             "unknown theora cookie %" GST_FOURCC_FORMAT,
6900             GST_FOURCC_ARGS (type));
6901         break;
6902     }
6903     buf += size;
6904   }
6905   return TRUE;
6906 }
6907
6908 static gboolean
6909 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
6910     guint length)
6911 {
6912   guint32 fourcc = 0;
6913   guint32 node_length = 0;
6914   const QtNodeType *type;
6915   const guint8 *end;
6916
6917   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
6918
6919   if (G_UNLIKELY (length < 8))
6920     goto not_enough_data;
6921
6922   node_length = QT_UINT32 (buffer);
6923   fourcc = QT_FOURCC (buffer + 4);
6924
6925   /* ignore empty nodes */
6926   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
6927     return TRUE;
6928
6929   type = qtdemux_type_get (fourcc);
6930
6931   end = buffer + length;
6932
6933   GST_LOG_OBJECT (qtdemux,
6934       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
6935       GST_FOURCC_ARGS (fourcc), node_length, type->name);
6936
6937   if (node_length > length)
6938     goto broken_atom_size;
6939
6940   if (type->flags & QT_FLAG_CONTAINER) {
6941     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
6942   } else {
6943     switch (fourcc) {
6944       case FOURCC_stsd:
6945       {
6946         if (node_length < 20) {
6947           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
6948           break;
6949         }
6950         GST_DEBUG_OBJECT (qtdemux,
6951             "parsing stsd (sample table, sample description) atom");
6952         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
6953         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6954         break;
6955       }
6956       case FOURCC_mp4a:
6957       case FOURCC_alac:
6958       {
6959         guint32 version;
6960         guint32 offset;
6961         guint min_size;
6962
6963         /* also read alac (or whatever) in stead of mp4a in the following,
6964          * since a similar layout is used in other cases as well */
6965         if (fourcc == FOURCC_mp4a)
6966           min_size = 20;
6967         else
6968           min_size = 40;
6969
6970         /* There are two things we might encounter here: a true mp4a atom, and
6971            an mp4a entry in an stsd atom. The latter is what we're interested
6972            in, and it looks like an atom, but isn't really one. The true mp4a
6973            atom is short, so we detect it based on length here. */
6974         if (length < min_size) {
6975           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
6976               GST_FOURCC_ARGS (fourcc));
6977           break;
6978         }
6979
6980         /* 'version' here is the sound sample description version. Types 0 and
6981            1 are documented in the QTFF reference, but type 2 is not: it's
6982            described in Apple header files instead (struct SoundDescriptionV2
6983            in Movies.h) */
6984         version = QT_UINT16 (buffer + 16);
6985
6986         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
6987             GST_FOURCC_ARGS (fourcc), version);
6988
6989         /* parse any esds descriptors */
6990         switch (version) {
6991           case 0:
6992             offset = 0x24;
6993             break;
6994           case 1:
6995             offset = 0x34;
6996             break;
6997           case 2:
6998             offset = 0x48;
6999             break;
7000           default:
7001             GST_WARNING_OBJECT (qtdemux,
7002                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7003                 GST_FOURCC_ARGS (fourcc), version);
7004             offset = 0;
7005             break;
7006         }
7007         if (offset)
7008           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7009         break;
7010       }
7011       case FOURCC_mp4v:
7012       case FOURCC_MP4V:
7013       case FOURCC_fmp4:
7014       case FOURCC_FMP4:
7015       case FOURCC_apcs:
7016       case FOURCC_apch:
7017       case FOURCC_apcn:
7018       case FOURCC_apco:
7019       case FOURCC_ap4h:
7020       {
7021         const guint8 *buf;
7022         guint32 version;
7023         int tlen;
7024
7025         /* codec_data is contained inside these atoms, which all have
7026          * the same format. */
7027
7028         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7029             GST_FOURCC_ARGS (fourcc));
7030         version = QT_UINT32 (buffer + 16);
7031         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7032         if (1 || version == 0x00000000) {
7033           buf = buffer + 0x32;
7034
7035           /* FIXME Quicktime uses PASCAL string while
7036            * the iso format uses C strings. Check the file
7037            * type before attempting to parse the string here. */
7038           tlen = QT_UINT8 (buf);
7039           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
7040           buf++;
7041           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
7042           /* the string has a reserved space of 32 bytes so skip
7043            * the remaining 31 */
7044           buf += 31;
7045           buf += 4;             /* and 4 bytes reserved */
7046
7047           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
7048
7049           qtdemux_parse_container (qtdemux, node, buf, end);
7050         }
7051         break;
7052       }
7053       case FOURCC_H264:
7054       {
7055         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
7056         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7057         break;
7058       }
7059       case FOURCC_avc1:
7060       {
7061         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
7062         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7063         break;
7064       }
7065       case FOURCC_avc3:
7066       {
7067         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
7068         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7069         break;
7070       }
7071       case FOURCC_H265:
7072       {
7073         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
7074         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7075         break;
7076       }
7077       case FOURCC_hvc1:
7078       {
7079         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
7080         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7081         break;
7082       }
7083       case FOURCC_hev1:
7084       {
7085         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
7086         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7087         break;
7088       }
7089       case FOURCC_mjp2:
7090       {
7091         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7092         break;
7093       }
7094       case FOURCC_meta:
7095       {
7096         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7097         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7098         break;
7099       }
7100       case FOURCC_mp4s:
7101       {
7102         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7103         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7104         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7105         break;
7106       }
7107       case FOURCC_XiTh:
7108       {
7109         guint32 version;
7110         guint32 offset;
7111
7112         version = QT_UINT32 (buffer + 12);
7113         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7114
7115         switch (version) {
7116           case 0x00000001:
7117             offset = 0x62;
7118             break;
7119           default:
7120             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7121             offset = 0;
7122             break;
7123         }
7124         if (offset)
7125           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7126         break;
7127       }
7128       case FOURCC_in24:
7129       {
7130         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7131         break;
7132       }
7133       case FOURCC_uuid:
7134       {
7135         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7136         break;
7137       }
7138       case FOURCC_encv:
7139       {
7140         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7141         break;
7142       }
7143       case FOURCC_enca:
7144       {
7145         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7146         break;
7147       }
7148       default:
7149         if (!strcmp (type->name, "unknown"))
7150           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7151         break;
7152     }
7153   }
7154   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7155       GST_FOURCC_ARGS (fourcc));
7156   return TRUE;
7157
7158 /* ERRORS */
7159 not_enough_data:
7160   {
7161     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7162         (_("This file is corrupt and cannot be played.")),
7163         ("Not enough data for an atom header, got only %u bytes", length));
7164     return FALSE;
7165   }
7166 broken_atom_size:
7167   {
7168     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7169         (_("This file is corrupt and cannot be played.")),
7170         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7171             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7172             length));
7173     return FALSE;
7174   }
7175 }
7176
7177 static GNode *
7178 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7179 {
7180   GNode *child;
7181   guint8 *buffer;
7182   guint32 child_fourcc;
7183
7184   for (child = g_node_first_child (node); child;
7185       child = g_node_next_sibling (child)) {
7186     buffer = (guint8 *) child->data;
7187
7188     child_fourcc = QT_FOURCC (buffer + 4);
7189
7190     if (G_UNLIKELY (child_fourcc == fourcc)) {
7191       return child;
7192     }
7193   }
7194   return NULL;
7195 }
7196
7197 static GNode *
7198 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7199     GstByteReader * parser)
7200 {
7201   GNode *child;
7202   guint8 *buffer;
7203   guint32 child_fourcc, child_len;
7204
7205   for (child = g_node_first_child (node); child;
7206       child = g_node_next_sibling (child)) {
7207     buffer = (guint8 *) child->data;
7208
7209     child_len = QT_UINT32 (buffer);
7210     child_fourcc = QT_FOURCC (buffer + 4);
7211
7212     if (G_UNLIKELY (child_fourcc == fourcc)) {
7213       if (G_UNLIKELY (child_len < (4 + 4)))
7214         return NULL;
7215       /* FIXME: must verify if atom length < parent atom length */
7216       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7217       return child;
7218     }
7219   }
7220   return NULL;
7221 }
7222
7223 static GNode *
7224 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7225     GstByteReader * parser)
7226 {
7227   GNode *child;
7228   guint8 *buffer;
7229   guint32 child_fourcc, child_len;
7230
7231   for (child = g_node_next_sibling (node); child;
7232       child = g_node_next_sibling (child)) {
7233     buffer = (guint8 *) child->data;
7234
7235     child_fourcc = QT_FOURCC (buffer + 4);
7236
7237     if (child_fourcc == fourcc) {
7238       if (parser) {
7239         child_len = QT_UINT32 (buffer);
7240         if (G_UNLIKELY (child_len < (4 + 4)))
7241           return NULL;
7242         /* FIXME: must verify if atom length < parent atom length */
7243         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7244       }
7245       return child;
7246     }
7247   }
7248   return NULL;
7249 }
7250
7251 static GNode *
7252 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7253 {
7254   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7255 }
7256
7257 static void
7258 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7259 {
7260 /* FIXME: This can only reliably work if demuxers have a
7261  * separate streaming thread per srcpad. This should be
7262  * done in a demuxer base class, which integrates parts
7263  * of multiqueue
7264  *
7265  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7266  */
7267 #if 0
7268   GstQuery *query;
7269
7270   query = gst_query_new_allocation (stream->caps, FALSE);
7271
7272   if (!gst_pad_peer_query (stream->pad, query)) {
7273     /* not a problem, just debug a little */
7274     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7275   }
7276
7277   if (stream->allocator)
7278     gst_object_unref (stream->allocator);
7279
7280   if (gst_query_get_n_allocation_params (query) > 0) {
7281     /* try the allocator */
7282     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7283         &stream->params);
7284     stream->use_allocator = TRUE;
7285   } else {
7286     stream->allocator = NULL;
7287     gst_allocation_params_init (&stream->params);
7288     stream->use_allocator = FALSE;
7289   }
7290   gst_query_unref (query);
7291 #endif
7292 }
7293
7294 static gboolean
7295 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7296     QtDemuxStream * stream)
7297 {
7298   GstStructure *s;
7299   const gchar *selected_system;
7300
7301   g_return_val_if_fail (qtdemux != NULL, FALSE);
7302   g_return_val_if_fail (stream != NULL, FALSE);
7303   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7304
7305   if (stream->protection_scheme_type != FOURCC_cenc) {
7306     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7307     return FALSE;
7308   }
7309   if (qtdemux->protection_system_ids == NULL) {
7310     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7311         "cenc protection system information has been found");
7312     return FALSE;
7313   }
7314   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7315   selected_system = gst_protection_select_system ((const gchar **)
7316       qtdemux->protection_system_ids->pdata);
7317   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7318       qtdemux->protection_system_ids->len - 1);
7319   if (!selected_system) {
7320     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7321         "suitable decryptor element has been found");
7322     return FALSE;
7323   }
7324
7325   s = gst_caps_get_structure (stream->caps, 0);
7326   if (!gst_structure_has_name (s, "application/x-cenc")) {
7327     gst_structure_set (s,
7328         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7329         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7330         NULL);
7331     gst_structure_set_name (s, "application/x-cenc");
7332   }
7333   return TRUE;
7334 }
7335
7336 static gboolean
7337 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7338 {
7339   if (stream->subtype == FOURCC_vide) {
7340     /* fps is calculated base on the duration of the average framerate since
7341      * qt does not have a fixed framerate. */
7342     gboolean fps_available = TRUE;
7343
7344     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7345       /* still frame */
7346       stream->fps_n = 0;
7347       stream->fps_d = 1;
7348     } else {
7349       if (stream->duration == 0 || stream->n_samples < 2) {
7350         stream->fps_n = stream->timescale;
7351         stream->fps_d = 1;
7352         fps_available = FALSE;
7353       } else {
7354         GstClockTime avg_duration;
7355         guint64 duration;
7356         guint32 n_samples;
7357
7358         /* duration and n_samples can be updated for fragmented format
7359          * so, framerate of fragmented format is calculated using data in a moof */
7360         if (qtdemux->fragmented && stream->n_samples_moof > 0
7361             && stream->duration_moof > 0) {
7362           n_samples = stream->n_samples_moof;
7363           duration = stream->duration_moof;
7364         } else {
7365           n_samples = stream->n_samples;
7366           duration = stream->duration;
7367         }
7368
7369         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7370         /* stream->duration is guint64, timescale, n_samples are guint32 */
7371         avg_duration =
7372             gst_util_uint64_scale_round (duration -
7373             stream->first_duration, GST_SECOND,
7374             (guint64) (stream->timescale) * (n_samples - 1));
7375
7376         GST_LOG_OBJECT (qtdemux,
7377             "Calculating avg sample duration based on stream (or moof) duration %"
7378             G_GUINT64_FORMAT
7379             " minus first sample %u, leaving %d samples gives %"
7380             GST_TIME_FORMAT, duration, stream->first_duration,
7381             n_samples - 1, GST_TIME_ARGS (avg_duration));
7382
7383         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7384             &stream->fps_d);
7385
7386         GST_DEBUG_OBJECT (qtdemux,
7387             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7388             stream->timescale, stream->fps_n, stream->fps_d);
7389       }
7390     }
7391
7392     if (stream->caps) {
7393       stream->caps = gst_caps_make_writable (stream->caps);
7394
7395       gst_caps_set_simple (stream->caps,
7396           "width", G_TYPE_INT, stream->width,
7397           "height", G_TYPE_INT, stream->height, NULL);
7398
7399       /* set framerate if calculated framerate is reliable */
7400       if (fps_available) {
7401         gst_caps_set_simple (stream->caps,
7402             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7403       }
7404
7405       /* calculate pixel-aspect-ratio using display width and height */
7406       GST_DEBUG_OBJECT (qtdemux,
7407           "video size %dx%d, target display size %dx%d", stream->width,
7408           stream->height, stream->display_width, stream->display_height);
7409       /* qt file might have pasp atom */
7410       if (stream->par_w > 0 && stream->par_h > 0) {
7411         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7412         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7413             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7414       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7415           stream->width > 0 && stream->height > 0) {
7416         gint n, d;
7417
7418         /* calculate the pixel aspect ratio using the display and pixel w/h */
7419         n = stream->display_width * stream->height;
7420         d = stream->display_height * stream->width;
7421         if (n == d)
7422           n = d = 1;
7423         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7424         stream->par_w = n;
7425         stream->par_h = d;
7426         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7427             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7428       }
7429
7430       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7431         guint par_w = 1, par_h = 1;
7432
7433         if (stream->par_w > 0 && stream->par_h > 0) {
7434           par_w = stream->par_w;
7435           par_h = stream->par_h;
7436         }
7437
7438         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7439                 stream->width, stream->height, par_w, par_h)) {
7440           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7441         }
7442
7443         gst_caps_set_simple (stream->caps,
7444             "multiview-mode", G_TYPE_STRING,
7445             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7446             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7447             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7448       }
7449     }
7450   }
7451
7452   else if (stream->subtype == FOURCC_soun) {
7453     if (stream->caps) {
7454       stream->caps = gst_caps_make_writable (stream->caps);
7455       if (stream->rate > 0)
7456         gst_caps_set_simple (stream->caps,
7457             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7458       if (stream->n_channels > 0)
7459         gst_caps_set_simple (stream->caps,
7460             "channels", G_TYPE_INT, stream->n_channels, NULL);
7461       if (stream->n_channels > 2) {
7462         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7463          * correctly; this is just the minimum we can do - assume
7464          * we don't actually have any channel positions. */
7465         gst_caps_set_simple (stream->caps,
7466             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7467       }
7468     }
7469   }
7470
7471   if (stream->pad) {
7472     GstCaps *prev_caps = NULL;
7473
7474     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7475     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7476     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7477     gst_pad_set_active (stream->pad, TRUE);
7478
7479     gst_pad_use_fixed_caps (stream->pad);
7480
7481     if (stream->protected) {
7482       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7483         GST_ERROR_OBJECT (qtdemux,
7484             "Failed to configure protected stream caps.");
7485         return FALSE;
7486       }
7487     }
7488
7489     if (stream->new_stream) {
7490       gchar *stream_id;
7491       GstEvent *event;
7492       GstStreamFlags stream_flags;
7493
7494       event =
7495           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7496           0);
7497       if (event) {
7498         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7499           qtdemux->have_group_id = TRUE;
7500         else
7501           qtdemux->have_group_id = FALSE;
7502         gst_event_unref (event);
7503       } else if (!qtdemux->have_group_id) {
7504         qtdemux->have_group_id = TRUE;
7505         qtdemux->group_id = gst_util_group_id_next ();
7506       }
7507
7508       stream->new_stream = FALSE;
7509       stream_id =
7510           gst_pad_create_stream_id_printf (stream->pad,
7511           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7512       event = gst_event_new_stream_start (stream_id);
7513       if (qtdemux->have_group_id)
7514         gst_event_set_group_id (event, qtdemux->group_id);
7515       stream_flags = GST_STREAM_FLAG_NONE;
7516       if (stream->disabled)
7517         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7518       if (stream->sparse)
7519         stream_flags |= GST_STREAM_FLAG_SPARSE;
7520       gst_event_set_stream_flags (event, stream_flags);
7521       gst_pad_push_event (stream->pad, event);
7522       g_free (stream_id);
7523     }
7524
7525     prev_caps = gst_pad_get_current_caps (stream->pad);
7526
7527     if (!prev_caps || !gst_caps_is_equal_fixed (prev_caps, stream->caps)) {
7528       GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7529       gst_pad_set_caps (stream->pad, stream->caps);
7530     } else {
7531       GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7532     }
7533
7534     if (prev_caps)
7535       gst_caps_unref (prev_caps);
7536     stream->new_caps = FALSE;
7537   }
7538   return TRUE;
7539 }
7540
7541 static gboolean
7542 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7543     QtDemuxStream * stream, GstTagList * list)
7544 {
7545   gboolean ret = TRUE;
7546   /* consistent default for push based mode */
7547   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7548
7549   if (stream->subtype == FOURCC_vide) {
7550     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7551
7552     stream->pad =
7553         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7554     g_free (name);
7555
7556     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7557       gst_object_unref (stream->pad);
7558       stream->pad = NULL;
7559       ret = FALSE;
7560       goto done;
7561     }
7562
7563     qtdemux->n_video_streams++;
7564   } else if (stream->subtype == FOURCC_soun) {
7565     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7566
7567     stream->pad =
7568         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7569     g_free (name);
7570     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7571       gst_object_unref (stream->pad);
7572       stream->pad = NULL;
7573       ret = FALSE;
7574       goto done;
7575     }
7576     qtdemux->n_audio_streams++;
7577   } else if (stream->subtype == FOURCC_strm) {
7578     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7579   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7580       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7581     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7582
7583     stream->pad =
7584         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7585     g_free (name);
7586     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7587       gst_object_unref (stream->pad);
7588       stream->pad = NULL;
7589       ret = FALSE;
7590       goto done;
7591     }
7592     qtdemux->n_sub_streams++;
7593   } else if (stream->caps) {
7594     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7595
7596     stream->pad =
7597         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7598     g_free (name);
7599     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7600       gst_object_unref (stream->pad);
7601       stream->pad = NULL;
7602       ret = FALSE;
7603       goto done;
7604     }
7605     qtdemux->n_video_streams++;
7606   } else {
7607     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7608     goto done;
7609   }
7610
7611   if (stream->pad) {
7612     GList *l;
7613
7614     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7615         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7616     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7617     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7618
7619     if (stream->pending_tags)
7620       gst_tag_list_unref (stream->pending_tags);
7621     stream->pending_tags = list;
7622     list = NULL;
7623     /* global tags go on each pad anyway */
7624     stream->send_global_tags = TRUE;
7625     /* send upstream GST_EVENT_PROTECTION events that were received before
7626        this source pad was created */
7627     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7628       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7629   }
7630 done:
7631   if (list)
7632     gst_tag_list_unref (list);
7633   return ret;
7634 }
7635
7636 /* find next atom with @fourcc starting at @offset */
7637 static GstFlowReturn
7638 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7639     guint64 * length, guint32 fourcc)
7640 {
7641   GstFlowReturn ret;
7642   guint32 lfourcc;
7643   GstBuffer *buf;
7644
7645   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7646       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7647
7648   while (TRUE) {
7649     GstMapInfo map;
7650
7651     buf = NULL;
7652     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7653     if (G_UNLIKELY (ret != GST_FLOW_OK))
7654       goto locate_failed;
7655     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7656       /* likely EOF */
7657       ret = GST_FLOW_EOS;
7658       gst_buffer_unref (buf);
7659       goto locate_failed;
7660     }
7661     gst_buffer_map (buf, &map, GST_MAP_READ);
7662     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7663     gst_buffer_unmap (buf, &map);
7664     gst_buffer_unref (buf);
7665
7666     if (G_UNLIKELY (*length == 0)) {
7667       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7668       ret = GST_FLOW_ERROR;
7669       goto locate_failed;
7670     }
7671
7672     if (lfourcc == fourcc) {
7673       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7674           *offset);
7675       break;
7676     } else {
7677       GST_LOG_OBJECT (qtdemux,
7678           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7679           GST_FOURCC_ARGS (fourcc), *offset);
7680       *offset += *length;
7681     }
7682   }
7683
7684   return GST_FLOW_OK;
7685
7686 locate_failed:
7687   {
7688     /* might simply have had last one */
7689     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7690     return ret;
7691   }
7692 }
7693
7694 /* should only do something in pull mode */
7695 /* call with OBJECT lock */
7696 static GstFlowReturn
7697 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7698 {
7699   guint64 length, offset;
7700   GstBuffer *buf = NULL;
7701   GstFlowReturn ret = GST_FLOW_OK;
7702   GstFlowReturn res = GST_FLOW_OK;
7703   GstMapInfo map;
7704
7705   offset = qtdemux->moof_offset;
7706   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7707
7708   if (!offset) {
7709     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7710     return GST_FLOW_EOS;
7711   }
7712
7713   /* best not do pull etc with lock held */
7714   GST_OBJECT_UNLOCK (qtdemux);
7715
7716   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7717   if (ret != GST_FLOW_OK)
7718     goto flow_failed;
7719
7720   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7721   if (G_UNLIKELY (ret != GST_FLOW_OK))
7722     goto flow_failed;
7723   gst_buffer_map (buf, &map, GST_MAP_READ);
7724   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7725     gst_buffer_unmap (buf, &map);
7726     gst_buffer_unref (buf);
7727     buf = NULL;
7728     goto parse_failed;
7729   }
7730
7731   gst_buffer_unmap (buf, &map);
7732   gst_buffer_unref (buf);
7733   buf = NULL;
7734
7735   offset += length;
7736   /* look for next moof */
7737   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7738   if (G_UNLIKELY (ret != GST_FLOW_OK))
7739     goto flow_failed;
7740
7741 exit:
7742   GST_OBJECT_LOCK (qtdemux);
7743
7744   qtdemux->moof_offset = offset;
7745
7746   return res;
7747
7748 parse_failed:
7749   {
7750     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7751     offset = 0;
7752     res = GST_FLOW_ERROR;
7753     goto exit;
7754   }
7755 flow_failed:
7756   {
7757     /* maybe upstream temporarily flushing */
7758     if (ret != GST_FLOW_FLUSHING) {
7759       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7760       offset = 0;
7761     } else {
7762       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7763       /* resume at current position next time */
7764     }
7765     res = ret;
7766     goto exit;
7767   }
7768 }
7769
7770 /* initialise bytereaders for stbl sub-atoms */
7771 static gboolean
7772 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7773 {
7774   stream->stbl_index = -1;      /* no samples have yet been parsed */
7775   stream->sample_index = -1;
7776
7777   /* time-to-sample atom */
7778   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7779     goto corrupt_file;
7780
7781   /* copy atom data into a new buffer for later use */
7782   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7783
7784   /* skip version + flags */
7785   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7786       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7787     goto corrupt_file;
7788   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7789
7790   /* make sure there's enough data */
7791   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7792     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7793     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7794         stream->n_sample_times);
7795     if (!stream->n_sample_times)
7796       goto corrupt_file;
7797   }
7798
7799   /* sync sample atom */
7800   stream->stps_present = FALSE;
7801   if ((stream->stss_present =
7802           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7803               &stream->stss) ? TRUE : FALSE) == TRUE) {
7804     /* copy atom data into a new buffer for later use */
7805     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7806
7807     /* skip version + flags */
7808     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7809         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7810       goto corrupt_file;
7811
7812     if (stream->n_sample_syncs) {
7813       /* make sure there's enough data */
7814       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7815         goto corrupt_file;
7816     }
7817
7818     /* partial sync sample atom */
7819     if ((stream->stps_present =
7820             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7821                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7822       /* copy atom data into a new buffer for later use */
7823       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7824
7825       /* skip version + flags */
7826       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7827           !gst_byte_reader_get_uint32_be (&stream->stps,
7828               &stream->n_sample_partial_syncs))
7829         goto corrupt_file;
7830
7831       /* if there are no entries, the stss table contains the real
7832        * sync samples */
7833       if (stream->n_sample_partial_syncs) {
7834         /* make sure there's enough data */
7835         if (!qt_atom_parser_has_chunks (&stream->stps,
7836                 stream->n_sample_partial_syncs, 4))
7837           goto corrupt_file;
7838       }
7839     }
7840   }
7841
7842   /* sample size */
7843   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7844     goto no_samples;
7845
7846   /* copy atom data into a new buffer for later use */
7847   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7848
7849   /* skip version + flags */
7850   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7851       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7852     goto corrupt_file;
7853
7854   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7855     goto corrupt_file;
7856
7857   if (!stream->n_samples)
7858     goto no_samples;
7859
7860   /* sample-to-chunk atom */
7861   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7862     goto corrupt_file;
7863
7864   /* copy atom data into a new buffer for later use */
7865   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7866
7867   /* skip version + flags */
7868   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7869       !gst_byte_reader_get_uint32_be (&stream->stsc,
7870           &stream->n_samples_per_chunk))
7871     goto corrupt_file;
7872
7873   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7874       stream->n_samples_per_chunk);
7875
7876   /* make sure there's enough data */
7877   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7878           12))
7879     goto corrupt_file;
7880
7881
7882   /* chunk offset */
7883   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7884     stream->co_size = sizeof (guint32);
7885   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7886           &stream->stco))
7887     stream->co_size = sizeof (guint64);
7888   else
7889     goto corrupt_file;
7890
7891   /* copy atom data into a new buffer for later use */
7892   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7893
7894   /* skip version + flags */
7895   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7896     goto corrupt_file;
7897
7898   /* chunks_are_samples == TRUE means treat chunks as samples */
7899   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7900   if (stream->chunks_are_samples) {
7901     /* treat chunks as samples */
7902     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7903       goto corrupt_file;
7904   } else {
7905     /* skip number of entries */
7906     if (!gst_byte_reader_skip (&stream->stco, 4))
7907       goto corrupt_file;
7908
7909     /* make sure there are enough data in the stsz atom */
7910     if (!stream->sample_size) {
7911       /* different sizes for each sample */
7912       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7913         goto corrupt_file;
7914     }
7915   }
7916
7917   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7918       stream->n_samples, (guint) sizeof (QtDemuxSample),
7919       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7920
7921   if (stream->n_samples >=
7922       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7923     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7924         "be larger than %uMB (broken file?)", stream->n_samples,
7925         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7926     return FALSE;
7927   }
7928
7929   g_assert (stream->samples == NULL);
7930   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7931   if (!stream->samples) {
7932     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7933         stream->n_samples);
7934     return FALSE;
7935   }
7936
7937   /* composition time-to-sample */
7938   if ((stream->ctts_present =
7939           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7940               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7941     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7942
7943     /* copy atom data into a new buffer for later use */
7944     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7945
7946     /* skip version + flags */
7947     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7948         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7949             &stream->n_composition_times))
7950       goto corrupt_file;
7951
7952     /* make sure there's enough data */
7953     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7954             4 + 4))
7955       goto corrupt_file;
7956
7957     /* This is optional, if missing we iterate the ctts */
7958     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7959       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7960           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7961         g_free ((gpointer) cslg.data);
7962         goto corrupt_file;
7963       }
7964     } else {
7965       gint32 cslg_least = 0;
7966       guint num_entries, pos;
7967       gint i;
7968
7969       pos = gst_byte_reader_get_pos (&stream->ctts);
7970       num_entries = stream->n_composition_times;
7971
7972       stream->cslg_shift = 0;
7973
7974       for (i = 0; i < num_entries; i++) {
7975         gint32 offset;
7976
7977         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7978         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7979
7980         if (offset < cslg_least)
7981           cslg_least = offset;
7982       }
7983
7984       if (cslg_least < 0)
7985         stream->cslg_shift = ABS (cslg_least);
7986       else
7987         stream->cslg_shift = 0;
7988
7989       /* reset the reader so we can generate sample table */
7990       gst_byte_reader_set_pos (&stream->ctts, pos);
7991     }
7992   } else {
7993     /* Ensure the cslg_shift value is consistent so we can use it
7994      * unconditionnally to produce TS and Segment */
7995     stream->cslg_shift = 0;
7996   }
7997
7998   return TRUE;
7999
8000 corrupt_file:
8001   {
8002     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8003         (_("This file is corrupt and cannot be played.")), (NULL));
8004     return FALSE;
8005   }
8006 no_samples:
8007   {
8008     gst_qtdemux_stbl_free (stream);
8009     if (!qtdemux->fragmented) {
8010       /* not quite good */
8011       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8012       return FALSE;
8013     } else {
8014       /* may pick up samples elsewhere */
8015       return TRUE;
8016     }
8017   }
8018 }
8019
8020 /* collect samples from the next sample to be parsed up to sample @n for @stream
8021  * by reading the info from @stbl
8022  *
8023  * This code can be executed from both the streaming thread and the seeking
8024  * thread so it takes the object lock to protect itself
8025  */
8026 static gboolean
8027 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8028 {
8029   gint i, j, k;
8030   QtDemuxSample *samples, *first, *cur, *last;
8031   guint32 n_samples_per_chunk;
8032   guint32 n_samples;
8033
8034   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8035       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8036       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8037
8038   n_samples = stream->n_samples;
8039
8040   if (n >= n_samples)
8041     goto out_of_samples;
8042
8043   GST_OBJECT_LOCK (qtdemux);
8044   if (n <= stream->stbl_index)
8045     goto already_parsed;
8046
8047   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8048
8049   if (!stream->stsz.data) {
8050     /* so we already parsed and passed all the moov samples;
8051      * onto fragmented ones */
8052     g_assert (qtdemux->fragmented);
8053     goto done;
8054   }
8055
8056   /* pointer to the sample table */
8057   samples = stream->samples;
8058
8059   /* starts from -1, moves to the next sample index to parse */
8060   stream->stbl_index++;
8061
8062   /* keep track of the first and last sample to fill */
8063   first = &samples[stream->stbl_index];
8064   last = &samples[n];
8065
8066   if (!stream->chunks_are_samples) {
8067     /* set the sample sizes */
8068     if (stream->sample_size == 0) {
8069       /* different sizes for each sample */
8070       for (cur = first; cur <= last; cur++) {
8071         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8072         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8073             (guint) (cur - samples), cur->size);
8074       }
8075     } else {
8076       /* samples have the same size */
8077       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8078       for (cur = first; cur <= last; cur++)
8079         cur->size = stream->sample_size;
8080     }
8081   }
8082
8083   n_samples_per_chunk = stream->n_samples_per_chunk;
8084   cur = first;
8085
8086   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8087     guint32 last_chunk;
8088
8089     if (stream->stsc_chunk_index >= stream->last_chunk
8090         || stream->stsc_chunk_index < stream->first_chunk) {
8091       stream->first_chunk =
8092           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8093       stream->samples_per_chunk =
8094           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8095       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8096
8097       /* chunk numbers are counted from 1 it seems */
8098       if (G_UNLIKELY (stream->first_chunk == 0))
8099         goto corrupt_file;
8100
8101       --stream->first_chunk;
8102
8103       /* the last chunk of each entry is calculated by taking the first chunk
8104        * of the next entry; except if there is no next, where we fake it with
8105        * INT_MAX */
8106       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8107         stream->last_chunk = G_MAXUINT32;
8108       } else {
8109         stream->last_chunk =
8110             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8111         if (G_UNLIKELY (stream->last_chunk == 0))
8112           goto corrupt_file;
8113
8114         --stream->last_chunk;
8115       }
8116
8117       GST_LOG_OBJECT (qtdemux,
8118           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8119           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8120
8121       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8122         goto corrupt_file;
8123
8124       if (stream->last_chunk != G_MAXUINT32) {
8125         if (!qt_atom_parser_peek_sub (&stream->stco,
8126                 stream->first_chunk * stream->co_size,
8127                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8128                 &stream->co_chunk))
8129           goto corrupt_file;
8130
8131       } else {
8132         stream->co_chunk = stream->stco;
8133         if (!gst_byte_reader_skip (&stream->co_chunk,
8134                 stream->first_chunk * stream->co_size))
8135           goto corrupt_file;
8136       }
8137
8138       stream->stsc_chunk_index = stream->first_chunk;
8139     }
8140
8141     last_chunk = stream->last_chunk;
8142
8143     if (stream->chunks_are_samples) {
8144       cur = &samples[stream->stsc_chunk_index];
8145
8146       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8147         if (j > n) {
8148           /* save state */
8149           stream->stsc_chunk_index = j;
8150           goto done;
8151         }
8152
8153         cur->offset =
8154             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8155             stream->co_size);
8156
8157         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8158             "%" G_GUINT64_FORMAT, j, cur->offset);
8159
8160         if (stream->samples_per_frame * stream->bytes_per_frame) {
8161           cur->size =
8162               (stream->samples_per_chunk * stream->n_channels) /
8163               stream->samples_per_frame * stream->bytes_per_frame;
8164         } else {
8165           cur->size = stream->samples_per_chunk;
8166         }
8167
8168         GST_DEBUG_OBJECT (qtdemux,
8169             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8170             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8171                     stream->stco_sample_index)), cur->size);
8172
8173         cur->timestamp = stream->stco_sample_index;
8174         cur->duration = stream->samples_per_chunk;
8175         cur->keyframe = TRUE;
8176         cur++;
8177
8178         stream->stco_sample_index += stream->samples_per_chunk;
8179       }
8180       stream->stsc_chunk_index = j;
8181     } else {
8182       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8183         guint32 samples_per_chunk;
8184         guint64 chunk_offset;
8185
8186         if (!stream->stsc_sample_index
8187             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8188                 &stream->chunk_offset))
8189           goto corrupt_file;
8190
8191         samples_per_chunk = stream->samples_per_chunk;
8192         chunk_offset = stream->chunk_offset;
8193
8194         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8195           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8196               G_GUINT64_FORMAT " and size %d",
8197               (guint) (cur - samples), chunk_offset, cur->size);
8198
8199           cur->offset = chunk_offset;
8200           chunk_offset += cur->size;
8201           cur++;
8202
8203           if (G_UNLIKELY (cur > last)) {
8204             /* save state */
8205             stream->stsc_sample_index = k + 1;
8206             stream->chunk_offset = chunk_offset;
8207             stream->stsc_chunk_index = j;
8208             goto done2;
8209           }
8210         }
8211         stream->stsc_sample_index = 0;
8212       }
8213       stream->stsc_chunk_index = j;
8214     }
8215     stream->stsc_index++;
8216   }
8217
8218   if (stream->chunks_are_samples)
8219     goto ctts;
8220 done2:
8221   {
8222     guint32 n_sample_times;
8223
8224     n_sample_times = stream->n_sample_times;
8225     cur = first;
8226
8227     for (i = stream->stts_index; i < n_sample_times; i++) {
8228       guint32 stts_samples;
8229       gint32 stts_duration;
8230       gint64 stts_time;
8231
8232       if (stream->stts_sample_index >= stream->stts_samples
8233           || !stream->stts_sample_index) {
8234
8235         stream->stts_samples =
8236             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8237         stream->stts_duration =
8238             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8239
8240         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8241             i, stream->stts_samples, stream->stts_duration);
8242
8243         stream->stts_sample_index = 0;
8244       }
8245
8246       stts_samples = stream->stts_samples;
8247       stts_duration = stream->stts_duration;
8248       stts_time = stream->stts_time;
8249
8250       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8251         GST_DEBUG_OBJECT (qtdemux,
8252             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8253             (guint) (cur - samples), j,
8254             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8255
8256         cur->timestamp = stts_time;
8257         cur->duration = stts_duration;
8258
8259         /* avoid 32-bit wrap-around,
8260          * but still mind possible 'negative' duration */
8261         stts_time += (gint64) stts_duration;
8262         cur++;
8263
8264         if (G_UNLIKELY (cur > last)) {
8265           /* save values */
8266           stream->stts_time = stts_time;
8267           stream->stts_sample_index = j + 1;
8268           goto done3;
8269         }
8270       }
8271       stream->stts_sample_index = 0;
8272       stream->stts_time = stts_time;
8273       stream->stts_index++;
8274     }
8275     /* fill up empty timestamps with the last timestamp, this can happen when
8276      * the last samples do not decode and so we don't have timestamps for them.
8277      * We however look at the last timestamp to estimate the track length so we
8278      * need something in here. */
8279     for (; cur < last; cur++) {
8280       GST_DEBUG_OBJECT (qtdemux,
8281           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8282           (guint) (cur - samples),
8283           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8284       cur->timestamp = stream->stts_time;
8285       cur->duration = -1;
8286     }
8287   }
8288 done3:
8289   {
8290     /* sample sync, can be NULL */
8291     if (stream->stss_present == TRUE) {
8292       guint32 n_sample_syncs;
8293
8294       n_sample_syncs = stream->n_sample_syncs;
8295
8296       if (!n_sample_syncs) {
8297         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8298         stream->all_keyframe = TRUE;
8299       } else {
8300         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8301           /* note that the first sample is index 1, not 0 */
8302           guint32 index;
8303
8304           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8305
8306           if (G_LIKELY (index > 0 && index <= n_samples)) {
8307             index -= 1;
8308             samples[index].keyframe = TRUE;
8309             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8310             /* and exit if we have enough samples */
8311             if (G_UNLIKELY (index >= n)) {
8312               i++;
8313               break;
8314             }
8315           }
8316         }
8317         /* save state */
8318         stream->stss_index = i;
8319       }
8320
8321       /* stps marks partial sync frames like open GOP I-Frames */
8322       if (stream->stps_present == TRUE) {
8323         guint32 n_sample_partial_syncs;
8324
8325         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8326
8327         /* if there are no entries, the stss table contains the real
8328          * sync samples */
8329         if (n_sample_partial_syncs) {
8330           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8331             /* note that the first sample is index 1, not 0 */
8332             guint32 index;
8333
8334             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8335
8336             if (G_LIKELY (index > 0 && index <= n_samples)) {
8337               index -= 1;
8338               samples[index].keyframe = TRUE;
8339               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8340               /* and exit if we have enough samples */
8341               if (G_UNLIKELY (index >= n)) {
8342                 i++;
8343                 break;
8344               }
8345             }
8346           }
8347           /* save state */
8348           stream->stps_index = i;
8349         }
8350       }
8351     } else {
8352       /* no stss, all samples are keyframes */
8353       stream->all_keyframe = TRUE;
8354       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8355     }
8356   }
8357
8358 ctts:
8359   /* composition time to sample */
8360   if (stream->ctts_present == TRUE) {
8361     guint32 n_composition_times;
8362     guint32 ctts_count;
8363     gint32 ctts_soffset;
8364
8365     /* Fill in the pts_offsets */
8366     cur = first;
8367     n_composition_times = stream->n_composition_times;
8368
8369     for (i = stream->ctts_index; i < n_composition_times; i++) {
8370       if (stream->ctts_sample_index >= stream->ctts_count
8371           || !stream->ctts_sample_index) {
8372         stream->ctts_count =
8373             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8374         stream->ctts_soffset =
8375             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8376         stream->ctts_sample_index = 0;
8377       }
8378
8379       ctts_count = stream->ctts_count;
8380       ctts_soffset = stream->ctts_soffset;
8381
8382       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8383         cur->pts_offset = ctts_soffset;
8384         cur++;
8385
8386         if (G_UNLIKELY (cur > last)) {
8387           /* save state */
8388           stream->ctts_sample_index = j + 1;
8389           goto done;
8390         }
8391       }
8392       stream->ctts_sample_index = 0;
8393       stream->ctts_index++;
8394     }
8395   }
8396 done:
8397   stream->stbl_index = n;
8398   /* if index has been completely parsed, free data that is no-longer needed */
8399   if (n + 1 == stream->n_samples) {
8400     gst_qtdemux_stbl_free (stream);
8401     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8402     if (qtdemux->pullbased) {
8403       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8404       while (n + 1 == stream->n_samples)
8405         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8406           break;
8407     }
8408   }
8409   GST_OBJECT_UNLOCK (qtdemux);
8410
8411   return TRUE;
8412
8413   /* SUCCESS */
8414 already_parsed:
8415   {
8416     GST_LOG_OBJECT (qtdemux,
8417         "Tried to parse up to sample %u but this sample has already been parsed",
8418         n);
8419     /* if fragmented, there may be more */
8420     if (qtdemux->fragmented && n == stream->stbl_index)
8421       goto done;
8422     GST_OBJECT_UNLOCK (qtdemux);
8423     return TRUE;
8424   }
8425   /* ERRORS */
8426 out_of_samples:
8427   {
8428     GST_LOG_OBJECT (qtdemux,
8429         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8430         stream->n_samples);
8431     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8432         (_("This file is corrupt and cannot be played.")), (NULL));
8433     return FALSE;
8434   }
8435 corrupt_file:
8436   {
8437     GST_OBJECT_UNLOCK (qtdemux);
8438     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8439         (_("This file is corrupt and cannot be played.")), (NULL));
8440     return FALSE;
8441   }
8442 }
8443
8444 /* collect all segment info for @stream.
8445  */
8446 static gboolean
8447 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8448     GNode * trak)
8449 {
8450   GNode *edts;
8451   /* accept edts if they contain gaps at start and there is only
8452    * one media segment */
8453   gboolean allow_pushbased_edts = TRUE;
8454   gint media_segments_count = 0;
8455
8456   /* parse and prepare segment info from the edit list */
8457   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8458   stream->n_segments = 0;
8459   stream->segments = NULL;
8460   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8461     GNode *elst;
8462     gint n_segments;
8463     gint i, count, entry_size;
8464     guint64 time;
8465     GstClockTime stime;
8466     guint8 *buffer;
8467     guint8 version;
8468
8469     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8470     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8471       goto done;
8472
8473     buffer = elst->data;
8474
8475     version = QT_UINT8 (buffer + 8);
8476     entry_size = (version == 1) ? 20 : 12;
8477
8478     n_segments = QT_UINT32 (buffer + 12);
8479
8480     /* we might allocate a bit too much, at least allocate 1 segment */
8481     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8482
8483     /* segments always start from 0 */
8484     time = 0;
8485     stime = 0;
8486     count = 0;
8487     for (i = 0; i < n_segments; i++) {
8488       guint64 duration;
8489       guint64 media_time;
8490       gboolean time_valid = TRUE;
8491       QtDemuxSegment *segment;
8492       guint32 rate_int;
8493       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8494
8495       if (version == 1) {
8496         media_time = QT_UINT64 (buffer + 24 + i * entry_size);
8497         duration = QT_UINT64 (buffer + 16 + i * entry_size);
8498         if (media_time == G_MAXUINT64)
8499           time_valid = FALSE;
8500       } else {
8501         media_time = QT_UINT32 (buffer + 20 + i * entry_size);
8502         duration = QT_UINT32 (buffer + 16 + i * entry_size);
8503         if (media_time == G_MAXUINT32)
8504           time_valid = FALSE;
8505       }
8506
8507       if (time_valid)
8508         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8509
8510       segment = &stream->segments[count++];
8511
8512       /* time and duration expressed in global timescale */
8513       segment->time = stime;
8514       /* add non scaled values so we don't cause roundoff errors */
8515       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8516         time += duration;
8517         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8518         segment->duration = stime - segment->time;
8519       } else {
8520         /* zero duration does not imply media_start == media_stop
8521          * but, only specify media_start.*/
8522         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8523         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8524             && stime >= media_start) {
8525           segment->duration = stime - media_start;
8526         } else {
8527           segment->duration = GST_CLOCK_TIME_NONE;
8528         }
8529       }
8530       segment->stop_time = stime;
8531
8532       segment->trak_media_start = media_time;
8533       /* media_time expressed in stream timescale */
8534       if (time_valid) {
8535         segment->media_start = media_start;
8536         segment->media_stop = segment->media_start + segment->duration;
8537         media_segments_count++;
8538       } else {
8539         segment->media_start = GST_CLOCK_TIME_NONE;
8540         segment->media_stop = GST_CLOCK_TIME_NONE;
8541       }
8542       rate_int =
8543           QT_UINT32 (buffer + ((version == 1) ? 32 : 24) + i * entry_size);
8544
8545       if (rate_int <= 1) {
8546         /* 0 is not allowed, some programs write 1 instead of the floating point
8547          * value */
8548         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8549             rate_int);
8550         segment->rate = 1;
8551       } else {
8552         segment->rate = rate_int / 65536.0;
8553       }
8554
8555       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8556           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8557           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8558           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8559           i, GST_TIME_ARGS (segment->time),
8560           GST_TIME_ARGS (segment->duration),
8561           GST_TIME_ARGS (segment->media_start), media_time,
8562           GST_TIME_ARGS (segment->media_stop),
8563           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8564           stream->timescale);
8565       if (segment->stop_time > qtdemux->segment.stop) {
8566         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8567             " extends to %" GST_TIME_FORMAT
8568             " past the end of the file duration %" GST_TIME_FORMAT
8569             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8570             GST_TIME_ARGS (qtdemux->segment.stop));
8571         qtdemux->segment.stop = segment->stop_time;
8572       }
8573     }
8574     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8575     stream->n_segments = count;
8576     if (media_segments_count != 1)
8577       allow_pushbased_edts = FALSE;
8578   }
8579 done:
8580
8581   /* push based does not handle segments, so act accordingly here,
8582    * and warn if applicable */
8583   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8584     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8585     /* remove and use default one below, we stream like it anyway */
8586     g_free (stream->segments);
8587     stream->segments = NULL;
8588     stream->n_segments = 0;
8589   }
8590
8591   /* no segments, create one to play the complete trak */
8592   if (stream->n_segments == 0) {
8593     GstClockTime stream_duration =
8594         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8595
8596     if (stream->segments == NULL)
8597       stream->segments = g_new (QtDemuxSegment, 1);
8598
8599     /* represent unknown our way */
8600     if (stream_duration == 0)
8601       stream_duration = GST_CLOCK_TIME_NONE;
8602
8603     stream->segments[0].time = 0;
8604     stream->segments[0].stop_time = stream_duration;
8605     stream->segments[0].duration = stream_duration;
8606     stream->segments[0].media_start = 0;
8607     stream->segments[0].media_stop = stream_duration;
8608     stream->segments[0].rate = 1.0;
8609     stream->segments[0].trak_media_start = 0;
8610
8611     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8612         GST_TIME_ARGS (stream_duration));
8613     stream->n_segments = 1;
8614     stream->dummy_segment = TRUE;
8615   }
8616   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8617
8618   return TRUE;
8619 }
8620
8621 /*
8622  * Parses the stsd atom of a svq3 trak looking for
8623  * the SMI and gama atoms.
8624  */
8625 static void
8626 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8627     guint8 ** gamma, GstBuffer ** seqh)
8628 {
8629   guint8 *_gamma = NULL;
8630   GstBuffer *_seqh = NULL;
8631   guint8 *stsd_data = stsd->data;
8632   guint32 length = QT_UINT32 (stsd_data);
8633   guint16 version;
8634
8635   if (length < 32) {
8636     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8637     goto end;
8638   }
8639
8640   stsd_data += 32;
8641   length -= 32;
8642   version = QT_UINT16 (stsd_data);
8643   if (version == 3) {
8644     if (length >= 70) {
8645       length -= 70;
8646       stsd_data += 70;
8647       while (length > 8) {
8648         guint32 fourcc, size;
8649         guint8 *data;
8650         size = QT_UINT32 (stsd_data);
8651         fourcc = QT_FOURCC (stsd_data + 4);
8652         data = stsd_data + 8;
8653
8654         if (size == 0) {
8655           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8656               "svq3 atom parsing");
8657           goto end;
8658         }
8659
8660         switch (fourcc) {
8661           case FOURCC_gama:{
8662             if (size == 12) {
8663               _gamma = data;
8664             } else {
8665               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8666                   " for gama atom, expected 12", size);
8667             }
8668             break;
8669           }
8670           case FOURCC_SMI_:{
8671             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8672               guint32 seqh_size;
8673               if (_seqh != NULL) {
8674                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8675                     " found, ignoring");
8676               } else {
8677                 seqh_size = QT_UINT32 (data + 4);
8678                 if (seqh_size > 0) {
8679                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8680                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8681                 }
8682               }
8683             }
8684             break;
8685           }
8686           default:{
8687             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8688                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8689           }
8690         }
8691
8692         if (size <= length) {
8693           length -= size;
8694           stsd_data += size;
8695         }
8696       }
8697     } else {
8698       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8699     }
8700   } else {
8701     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8702         G_GUINT16_FORMAT, version);
8703     goto end;
8704   }
8705
8706 end:
8707   if (gamma) {
8708     *gamma = _gamma;
8709   }
8710   if (seqh) {
8711     *seqh = _seqh;
8712   } else if (_seqh) {
8713     gst_buffer_unref (_seqh);
8714   }
8715 }
8716
8717 static gchar *
8718 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8719 {
8720   GNode *dinf;
8721   GstByteReader dref;
8722   gchar *uri = NULL;
8723
8724   /*
8725    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8726    * atom that might contain a 'data' atom with the rtsp uri.
8727    * This case was reported in bug #597497, some info about
8728    * the hndl atom can be found in TN1195
8729    */
8730   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8731   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8732
8733   if (dinf) {
8734     guint32 dref_num_entries = 0;
8735     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8736         gst_byte_reader_skip (&dref, 4) &&
8737         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8738       gint i;
8739
8740       /* search dref entries for hndl atom */
8741       for (i = 0; i < dref_num_entries; i++) {
8742         guint32 size = 0, type;
8743         guint8 string_len = 0;
8744         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8745             qt_atom_parser_get_fourcc (&dref, &type)) {
8746           if (type == FOURCC_hndl) {
8747             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8748
8749             /* skip data reference handle bytes and the
8750              * following pascal string and some extra 4
8751              * bytes I have no idea what are */
8752             if (!gst_byte_reader_skip (&dref, 4) ||
8753                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8754                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8755               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8756               break;
8757             }
8758
8759             /* iterate over the atoms to find the data atom */
8760             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8761               guint32 atom_size;
8762               guint32 atom_type;
8763
8764               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8765                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8766                 if (atom_type == FOURCC_data) {
8767                   const guint8 *uri_aux = NULL;
8768
8769                   /* found the data atom that might contain the rtsp uri */
8770                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8771                       "hndl atom, interpreting it as an URI");
8772                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8773                           &uri_aux)) {
8774                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8775                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8776                     else
8777                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8778                           "didn't contain a rtsp address");
8779                   } else {
8780                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8781                         "atom contents");
8782                   }
8783                   break;
8784                 }
8785                 /* skipping to the next entry */
8786                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8787                   break;
8788               } else {
8789                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8790                     "atom header");
8791                 break;
8792               }
8793             }
8794             break;
8795           }
8796           /* skip to the next entry */
8797           if (!gst_byte_reader_skip (&dref, size - 8))
8798             break;
8799         } else {
8800           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8801         }
8802       }
8803       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8804     }
8805   }
8806   return uri;
8807 }
8808
8809 #define AMR_NB_ALL_MODES        0x81ff
8810 #define AMR_WB_ALL_MODES        0x83ff
8811 static guint
8812 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8813 {
8814   /* The 'damr' atom is of the form:
8815    *
8816    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8817    *    32 b       8 b          16 b           8 b                 8 b
8818    *
8819    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8820    * represents the highest mode used in the stream (and thus the maximum
8821    * bitrate), with a couple of special cases as seen below.
8822    */
8823
8824   /* Map of frame type ID -> bitrate */
8825   static const guint nb_bitrates[] = {
8826     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8827   };
8828   static const guint wb_bitrates[] = {
8829     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8830   };
8831   GstMapInfo map;
8832   gsize max_mode;
8833   guint16 mode_set;
8834
8835   gst_buffer_map (buf, &map, GST_MAP_READ);
8836
8837   if (map.size != 0x11) {
8838     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8839     goto bad_data;
8840   }
8841
8842   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8843     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8844         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8845     goto bad_data;
8846   }
8847
8848   mode_set = QT_UINT16 (map.data + 13);
8849
8850   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8851     max_mode = 7 + (wb ? 1 : 0);
8852   else
8853     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8854     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8855
8856   if (max_mode == -1) {
8857     GST_DEBUG ("No mode indication was found (mode set) = %x",
8858         (guint) mode_set);
8859     goto bad_data;
8860   }
8861
8862   gst_buffer_unmap (buf, &map);
8863   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8864
8865 bad_data:
8866   gst_buffer_unmap (buf, &map);
8867   return 0;
8868 }
8869
8870 static gboolean
8871 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8872     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8873 {
8874   /*
8875    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8876    * [0 1 2]
8877    * [3 4 5]
8878    * [6 7 8]
8879    */
8880
8881   if (gst_byte_reader_get_remaining (reader) < 36)
8882     return FALSE;
8883
8884   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8885   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8886   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8887   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8888   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8889   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8890   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8891   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8892   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8893
8894   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8895   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8896       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8897       matrix[2] & 0xFF);
8898   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8899       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8900       matrix[5] & 0xFF);
8901   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8902       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8903       matrix[8] & 0xFF);
8904
8905   return TRUE;
8906 }
8907
8908 static void
8909 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8910     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8911 {
8912
8913 /* [a b c]
8914  * [d e f]
8915  * [g h i]
8916  *
8917  * This macro will only compare value abdegh, it expects cfi to have already
8918  * been checked
8919  */
8920 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8921                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8922
8923   /* only handle the cases where the last column has standard values */
8924   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8925     const gchar *rotation_tag = NULL;
8926
8927     /* no rotation needed */
8928     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8929       /* NOP */
8930     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8931       rotation_tag = "rotate-90";
8932     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8933       rotation_tag = "rotate-180";
8934     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8935       rotation_tag = "rotate-270";
8936     } else {
8937       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8938     }
8939
8940     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8941         rotation_tag);
8942     if (rotation_tag != NULL) {
8943       if (*taglist == NULL)
8944         *taglist = gst_tag_list_new_empty ();
8945       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8946           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8947     }
8948   } else {
8949     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8950   }
8951 }
8952
8953 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8954  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8955  * Common Encryption (cenc), the function will also parse the tenc box (defined
8956  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8957  * (typically an enc[v|a|t|s] sample entry); the function will set
8958  * @original_fmt to the fourcc of the original unencrypted stream format.
8959  * Returns TRUE if successful; FALSE otherwise. */
8960 static gboolean
8961 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8962     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8963 {
8964   GNode *sinf;
8965   GNode *frma;
8966   GNode *schm;
8967   GNode *schi;
8968
8969   g_return_val_if_fail (qtdemux != NULL, FALSE);
8970   g_return_val_if_fail (stream != NULL, FALSE);
8971   g_return_val_if_fail (container != NULL, FALSE);
8972   g_return_val_if_fail (original_fmt != NULL, FALSE);
8973
8974   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8975   if (G_UNLIKELY (!sinf)) {
8976     if (stream->protection_scheme_type == FOURCC_cenc) {
8977       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8978           "mandatory for Common Encryption");
8979       return FALSE;
8980     }
8981     return TRUE;
8982   }
8983
8984   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8985   if (G_UNLIKELY (!frma)) {
8986     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8987     return FALSE;
8988   }
8989
8990   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8991   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8992       GST_FOURCC_ARGS (*original_fmt));
8993
8994   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8995   if (!schm) {
8996     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8997     return FALSE;
8998   }
8999   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9000   stream->protection_scheme_version =
9001       QT_UINT32 ((const guint8 *) schm->data + 16);
9002
9003   GST_DEBUG_OBJECT (qtdemux,
9004       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9005       "protection_scheme_version: %#010x",
9006       GST_FOURCC_ARGS (stream->protection_scheme_type),
9007       stream->protection_scheme_version);
9008
9009   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9010   if (!schi) {
9011     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9012     return FALSE;
9013   }
9014   if (stream->protection_scheme_type == FOURCC_cenc) {
9015     QtDemuxCencSampleSetInfo *info;
9016     GNode *tenc;
9017     const guint8 *tenc_data;
9018     guint32 isEncrypted;
9019     guint8 iv_size;
9020     const guint8 *default_kid;
9021     GstBuffer *kid_buf;
9022
9023     if (G_UNLIKELY (!stream->protection_scheme_info))
9024       stream->protection_scheme_info =
9025           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9026
9027     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9028
9029     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9030     if (!tenc) {
9031       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9032           "which is mandatory for Common Encryption");
9033       return FALSE;
9034     }
9035     tenc_data = (const guint8 *) tenc->data + 12;
9036     isEncrypted = QT_UINT24 (tenc_data);
9037     iv_size = QT_UINT8 (tenc_data + 3);
9038     default_kid = (tenc_data + 4);
9039     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9040     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9041     if (info->default_properties)
9042       gst_structure_free (info->default_properties);
9043     info->default_properties =
9044         gst_structure_new ("application/x-cenc",
9045         "iv_size", G_TYPE_UINT, iv_size,
9046         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9047         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9048     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9049         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9050     gst_buffer_unref (kid_buf);
9051   }
9052   return TRUE;
9053 }
9054
9055 /* parse the traks.
9056  * With each track we associate a new QtDemuxStream that contains all the info
9057  * about the trak.
9058  * traks that do not decode to something (like strm traks) will not have a pad.
9059  */
9060 static gboolean
9061 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9062 {
9063   GstByteReader tkhd;
9064   int offset;
9065   GNode *mdia;
9066   GNode *mdhd;
9067   GNode *hdlr;
9068   GNode *minf;
9069   GNode *stbl;
9070   GNode *stsd;
9071   GNode *mp4a;
9072   GNode *mp4v;
9073   GNode *wave;
9074   GNode *esds;
9075   GNode *pasp;
9076   GNode *tref;
9077   GNode *udta;
9078   GNode *svmi;
9079
9080   QtDemuxStream *stream = NULL;
9081   gboolean new_stream = FALSE;
9082   gchar *codec = NULL;
9083   const guint8 *stsd_data;
9084   guint16 lang_code;            /* quicktime lang code or packed iso code */
9085   guint32 version;
9086   guint32 tkhd_flags = 0;
9087   guint8 tkhd_version = 0;
9088   guint32 fourcc;
9089   guint value_size, stsd_len, len;
9090   guint32 track_id;
9091   guint32 dummy;
9092
9093   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9094
9095   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9096       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9097       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9098     goto corrupt_file;
9099
9100   /* pick between 64 or 32 bits */
9101   value_size = tkhd_version == 1 ? 8 : 4;
9102   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9103       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9104     goto corrupt_file;
9105
9106   if (!qtdemux->got_moov) {
9107     if (qtdemux_find_stream (qtdemux, track_id))
9108       goto existing_stream;
9109     stream = _create_stream ();
9110     stream->track_id = track_id;
9111     new_stream = TRUE;
9112   } else {
9113     stream = qtdemux_find_stream (qtdemux, track_id);
9114     if (!stream) {
9115       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9116       goto skip_track;
9117     }
9118
9119     /* flush samples data from this track from previous moov */
9120     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9121     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9122   }
9123   /* need defaults for fragments */
9124   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9125
9126   if (stream->pending_tags == NULL)
9127     stream->pending_tags = gst_tag_list_new_empty ();
9128
9129   if ((tkhd_flags & 1) == 0)
9130     stream->disabled = TRUE;
9131
9132   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9133       tkhd_version, tkhd_flags, stream->track_id);
9134
9135   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9136     goto corrupt_file;
9137
9138   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9139     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9140     if (qtdemux->major_brand != FOURCC_mjp2 ||
9141         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9142       goto corrupt_file;
9143   }
9144
9145   len = QT_UINT32 ((guint8 *) mdhd->data);
9146   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9147   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9148   if (version == 0x01000000) {
9149     if (len < 38)
9150       goto corrupt_file;
9151     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9152     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9153     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9154   } else {
9155     if (len < 30)
9156       goto corrupt_file;
9157     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9158     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9159     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9160   }
9161
9162   if (lang_code < 0x400) {
9163     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9164   } else if (lang_code == 0x7fff) {
9165     stream->lang_id[0] = 0;     /* unspecified */
9166   } else {
9167     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9168     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9169     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9170     stream->lang_id[3] = 0;
9171   }
9172
9173   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9174       stream->timescale);
9175   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9176       stream->duration);
9177   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9178       lang_code, stream->lang_id);
9179
9180   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9181     goto corrupt_file;
9182
9183   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9184     /* chapters track reference */
9185     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9186     if (chap) {
9187       gsize length = GST_READ_UINT32_BE (chap->data);
9188       if (qtdemux->chapters_track_id)
9189         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9190
9191       if (length >= 12) {
9192         qtdemux->chapters_track_id =
9193             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9194       }
9195     }
9196   }
9197
9198   /* fragmented files may have bogus duration in moov */
9199   if (!qtdemux->fragmented &&
9200       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9201     guint64 tdur1, tdur2;
9202
9203     /* don't overflow */
9204     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9205     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9206
9207     /* HACK:
9208      * some of those trailers, nowadays, have prologue images that are
9209      * themselves video tracks as well. I haven't really found a way to
9210      * identify those yet, except for just looking at their duration. */
9211     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9212       GST_WARNING_OBJECT (qtdemux,
9213           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9214           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9215           "found, assuming preview image or something; skipping track",
9216           stream->duration, stream->timescale, qtdemux->duration,
9217           qtdemux->timescale);
9218       if (new_stream)
9219         gst_qtdemux_stream_free (qtdemux, stream);
9220       return TRUE;
9221     }
9222   }
9223
9224   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9225     goto corrupt_file;
9226
9227   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9228       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9229
9230   len = QT_UINT32 ((guint8 *) hdlr->data);
9231   if (len >= 20)
9232     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9233   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9234       GST_FOURCC_ARGS (stream->subtype));
9235
9236   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9237     goto corrupt_file;
9238
9239   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9240     goto corrupt_file;
9241
9242   /*parse svmi header if existing */
9243   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9244   if (svmi) {
9245     len = QT_UINT32 ((guint8 *) svmi->data);
9246     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9247     if (!version) {
9248       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9249       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9250       guint8 frame_type, frame_layout;
9251
9252       /* MPEG-A stereo video */
9253       if (qtdemux->major_brand == FOURCC_ss02)
9254         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9255
9256       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9257       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9258       switch (frame_type) {
9259         case 0:
9260           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9261           break;
9262         case 1:
9263           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9264           break;
9265         case 2:
9266           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9267           break;
9268         case 3:
9269           /* mode 3 is primary/secondary view sequence, ie
9270            * left/right views in separate tracks. See section 7.2
9271            * of ISO/IEC 23000-11:2009 */
9272           GST_FIXME_OBJECT (qtdemux,
9273               "Implement stereo video in separate streams");
9274       }
9275
9276       if ((frame_layout & 0x1) == 0)
9277         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9278
9279       GST_LOG_OBJECT (qtdemux,
9280           "StereoVideo: composition type: %u, is_left_first: %u",
9281           frame_type, frame_layout);
9282       stream->multiview_mode = mode;
9283       stream->multiview_flags = flags;
9284     }
9285   }
9286
9287   /* parse stsd */
9288   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9289     goto corrupt_file;
9290   stsd_data = (const guint8 *) stsd->data;
9291
9292   /* stsd should at least have one entry */
9293   stsd_len = QT_UINT32 (stsd_data);
9294   if (stsd_len < 24) {
9295     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9296     if (stream->subtype == FOURCC_vivo) {
9297       if (new_stream)
9298         gst_qtdemux_stream_free (qtdemux, stream);
9299       return TRUE;
9300     } else {
9301       goto corrupt_file;
9302     }
9303   }
9304
9305   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9306
9307   /* and that entry should fit within stsd */
9308   len = QT_UINT32 (stsd_data + 16);
9309   if (len > stsd_len + 16)
9310     goto corrupt_file;
9311
9312   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9313   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9314       GST_FOURCC_ARGS (stream->fourcc));
9315   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9316
9317   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9318     goto error_encrypted;
9319
9320   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9321     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9322     stream->protected = TRUE;
9323     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9324       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9325   }
9326
9327   if (stream->subtype == FOURCC_vide) {
9328     guint32 w = 0, h = 0;
9329     gboolean gray;
9330     gint depth, palette_size, palette_count;
9331     guint32 matrix[9];
9332     guint32 *palette_data = NULL;
9333
9334     stream->sampled = TRUE;
9335
9336     /* version 1 uses some 64-bit ints */
9337     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9338       goto corrupt_file;
9339
9340     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9341       goto corrupt_file;
9342
9343     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9344         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9345       goto corrupt_file;
9346
9347     stream->display_width = w >> 16;
9348     stream->display_height = h >> 16;
9349
9350     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9351         &stream->pending_tags);
9352
9353     offset = 16;
9354     if (len < 86)
9355       goto corrupt_file;
9356
9357     stream->width = QT_UINT16 (stsd_data + offset + 32);
9358     stream->height = QT_UINT16 (stsd_data + offset + 34);
9359     stream->fps_n = 0;          /* this is filled in later */
9360     stream->fps_d = 0;          /* this is filled in later */
9361     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9362     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9363
9364     /* if color_table_id is 0, ctab atom must follow; however some files
9365      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9366      * if color table is not present we'll correct the value */
9367     if (stream->color_table_id == 0 &&
9368         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9369       stream->color_table_id = -1;
9370     }
9371
9372     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9373         stream->width, stream->height, stream->bits_per_sample,
9374         stream->color_table_id);
9375
9376     depth = stream->bits_per_sample;
9377
9378     /* more than 32 bits means grayscale */
9379     gray = (depth > 32);
9380     /* low 32 bits specify the depth  */
9381     depth &= 0x1F;
9382
9383     /* different number of palette entries is determined by depth. */
9384     palette_count = 0;
9385     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9386       palette_count = (1 << depth);
9387     palette_size = palette_count * 4;
9388
9389     if (stream->color_table_id) {
9390       switch (palette_count) {
9391         case 0:
9392           break;
9393         case 2:
9394           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9395           break;
9396         case 4:
9397           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9398           break;
9399         case 16:
9400           if (gray)
9401             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9402           else
9403             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9404           break;
9405         case 256:
9406           if (gray)
9407             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9408           else
9409             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9410           break;
9411         default:
9412           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9413               (_("The video in this file might not play correctly.")),
9414               ("unsupported palette depth %d", depth));
9415           break;
9416       }
9417     } else {
9418       gint i, j, start, end;
9419
9420       if (len < 94)
9421         goto corrupt_file;
9422
9423       /* read table */
9424       start = QT_UINT32 (stsd_data + offset + 86);
9425       palette_count = QT_UINT16 (stsd_data + offset + 90);
9426       end = QT_UINT16 (stsd_data + offset + 92);
9427
9428       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9429           start, end, palette_count);
9430
9431       if (end > 255)
9432         end = 255;
9433       if (start > end)
9434         start = end;
9435
9436       if (len < 94 + (end - start) * 8)
9437         goto corrupt_file;
9438
9439       /* palette is always the same size */
9440       palette_data = g_malloc0 (256 * 4);
9441       palette_size = 256 * 4;
9442
9443       for (j = 0, i = start; i <= end; j++, i++) {
9444         guint32 a, r, g, b;
9445
9446         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9447         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9448         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9449         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9450
9451         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9452             (g & 0xff00) | (b >> 8);
9453       }
9454     }
9455
9456     if (stream->caps)
9457       gst_caps_unref (stream->caps);
9458
9459     stream->caps =
9460         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9461     if (G_UNLIKELY (!stream->caps)) {
9462       g_free (palette_data);
9463       goto unknown_stream;
9464     }
9465
9466     if (codec) {
9467       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9468           GST_TAG_VIDEO_CODEC, codec, NULL);
9469       g_free (codec);
9470       codec = NULL;
9471     }
9472
9473
9474     if (palette_data) {
9475       GstStructure *s;
9476
9477       if (stream->rgb8_palette)
9478         gst_memory_unref (stream->rgb8_palette);
9479       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9480           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9481
9482       s = gst_caps_get_structure (stream->caps, 0);
9483
9484       /* non-raw video has a palette_data property. raw video has the palette as
9485        * an extra plane that we append to the output buffers before we push
9486        * them*/
9487       if (!gst_structure_has_name (s, "video/x-raw")) {
9488         GstBuffer *palette;
9489
9490         palette = gst_buffer_new ();
9491         gst_buffer_append_memory (palette, stream->rgb8_palette);
9492         stream->rgb8_palette = NULL;
9493
9494         gst_caps_set_simple (stream->caps, "palette_data",
9495             GST_TYPE_BUFFER, palette, NULL);
9496         gst_buffer_unref (palette);
9497       }
9498     } else if (palette_count != 0) {
9499       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9500           (NULL), ("Unsupported palette depth %d", depth));
9501     }
9502
9503     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9504         QT_UINT16 (stsd_data + offset + 48));
9505
9506     esds = NULL;
9507     pasp = NULL;
9508     /* pick 'the' stsd child */
9509     if (!stream->protected)
9510       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9511     else
9512       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9513
9514     if (mp4v) {
9515       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9516       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9517     }
9518
9519     if (pasp) {
9520       const guint8 *pasp_data = (const guint8 *) pasp->data;
9521
9522       stream->par_w = QT_UINT32 (pasp_data + 8);
9523       stream->par_h = QT_UINT32 (pasp_data + 12);
9524     } else {
9525       stream->par_w = 0;
9526       stream->par_h = 0;
9527     }
9528
9529     if (esds) {
9530       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9531     } else {
9532       switch (fourcc) {
9533         case FOURCC_H264:
9534         case FOURCC_avc1:
9535         case FOURCC_avc3:
9536         {
9537           gint len = QT_UINT32 (stsd_data) - 0x66;
9538           const guint8 *avc_data = stsd_data + 0x66;
9539
9540           /* find avcC */
9541           while (len >= 0x8) {
9542             gint size;
9543
9544             if (QT_UINT32 (avc_data) <= len)
9545               size = QT_UINT32 (avc_data) - 0x8;
9546             else
9547               size = len - 0x8;
9548
9549             if (size < 1)
9550               /* No real data, so break out */
9551               break;
9552
9553             switch (QT_FOURCC (avc_data + 0x4)) {
9554               case FOURCC_avcC:
9555               {
9556                 /* parse, if found */
9557                 GstBuffer *buf;
9558
9559                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9560
9561                 /* First 4 bytes are the length of the atom, the next 4 bytes
9562                  * are the fourcc, the next 1 byte is the version, and the
9563                  * subsequent bytes are profile_tier_level structure like data. */
9564                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9565                     avc_data + 8 + 1, size - 1);
9566                 buf = gst_buffer_new_and_alloc (size);
9567                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9568                 gst_caps_set_simple (stream->caps,
9569                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9570                 gst_buffer_unref (buf);
9571
9572                 break;
9573               }
9574               case FOURCC_strf:
9575               {
9576                 GstBuffer *buf;
9577
9578                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9579
9580                 /* First 4 bytes are the length of the atom, the next 4 bytes
9581                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9582                  * next 1 byte is the version, and the
9583                  * subsequent bytes are sequence parameter set like data. */
9584
9585                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9586                 if (size > 1) {
9587                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9588                       avc_data + 8 + 40 + 1, size - 1);
9589
9590                   buf = gst_buffer_new_and_alloc (size);
9591                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9592                   gst_caps_set_simple (stream->caps,
9593                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9594                   gst_buffer_unref (buf);
9595                 }
9596                 break;
9597               }
9598               case FOURCC_btrt:
9599               {
9600                 guint avg_bitrate, max_bitrate;
9601
9602                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9603                 if (size < 12)
9604                   break;
9605
9606                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9607                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9608
9609                 if (!max_bitrate && !avg_bitrate)
9610                   break;
9611
9612                 /* Some muxers seem to swap the average and maximum bitrates
9613                  * (I'm looking at you, YouTube), so we swap for sanity. */
9614                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9615                   guint temp = avg_bitrate;
9616
9617                   avg_bitrate = max_bitrate;
9618                   max_bitrate = temp;
9619                 }
9620
9621                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9622                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9623                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9624                 }
9625                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9626                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9627                       GST_TAG_BITRATE, avg_bitrate, NULL);
9628                 }
9629
9630                 break;
9631               }
9632
9633               default:
9634                 break;
9635             }
9636
9637             len -= size + 8;
9638             avc_data += size + 8;
9639           }
9640
9641           break;
9642         }
9643         case FOURCC_H265:
9644         case FOURCC_hvc1:
9645         case FOURCC_hev1:
9646         {
9647           gint len = QT_UINT32 (stsd_data) - 0x66;
9648           const guint8 *hevc_data = stsd_data + 0x66;
9649
9650           /* find hevc */
9651           while (len >= 0x8) {
9652             gint size;
9653
9654             if (QT_UINT32 (hevc_data) <= len)
9655               size = QT_UINT32 (hevc_data) - 0x8;
9656             else
9657               size = len - 0x8;
9658
9659             if (size < 1)
9660               /* No real data, so break out */
9661               break;
9662
9663             switch (QT_FOURCC (hevc_data + 0x4)) {
9664               case FOURCC_hvcC:
9665               {
9666                 /* parse, if found */
9667                 GstBuffer *buf;
9668
9669                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9670
9671                 /* First 4 bytes are the length of the atom, the next 4 bytes
9672                  * are the fourcc, the next 1 byte is the version, and the
9673                  * subsequent bytes are sequence parameter set like data. */
9674                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9675                     (stream->caps, hevc_data + 8 + 1, size - 1);
9676
9677                 buf = gst_buffer_new_and_alloc (size);
9678                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9679                 gst_caps_set_simple (stream->caps,
9680                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9681                 gst_buffer_unref (buf);
9682                 break;
9683               }
9684               default:
9685                 break;
9686             }
9687             len -= size + 8;
9688             hevc_data += size + 8;
9689           }
9690           break;
9691         }
9692         case FOURCC_mp4v:
9693         case FOURCC_MP4V:
9694         case FOURCC_fmp4:
9695         case FOURCC_FMP4:
9696         {
9697           GNode *glbl;
9698
9699           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9700               GST_FOURCC_ARGS (fourcc));
9701
9702           /* codec data might be in glbl extension atom */
9703           glbl = mp4v ?
9704               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9705           if (glbl) {
9706             guint8 *data;
9707             GstBuffer *buf;
9708             gint len;
9709
9710             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9711             data = glbl->data;
9712             len = QT_UINT32 (data);
9713             if (len > 0x8) {
9714               len -= 0x8;
9715               buf = gst_buffer_new_and_alloc (len);
9716               gst_buffer_fill (buf, 0, data + 8, len);
9717               gst_caps_set_simple (stream->caps,
9718                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9719               gst_buffer_unref (buf);
9720             }
9721           }
9722           break;
9723         }
9724         case FOURCC_mjp2:
9725         {
9726           /* see annex I of the jpeg2000 spec */
9727           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9728           const guint8 *data;
9729           const gchar *colorspace = NULL;
9730           gint ncomp = 0;
9731           guint32 ncomp_map = 0;
9732           gint32 *comp_map = NULL;
9733           guint32 nchan_def = 0;
9734           gint32 *chan_def = NULL;
9735
9736           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9737           /* some required atoms */
9738           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9739           if (!mjp2)
9740             break;
9741           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9742           if (!jp2h)
9743             break;
9744
9745           /* number of components; redundant with info in codestream, but useful
9746              to a muxer */
9747           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9748           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9749             break;
9750           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9751
9752           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9753           if (!colr)
9754             break;
9755           GST_DEBUG_OBJECT (qtdemux, "found colr");
9756           /* extract colour space info */
9757           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9758             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9759               case 16:
9760                 colorspace = "sRGB";
9761                 break;
9762               case 17:
9763                 colorspace = "GRAY";
9764                 break;
9765               case 18:
9766                 colorspace = "sYUV";
9767                 break;
9768               default:
9769                 colorspace = NULL;
9770                 break;
9771             }
9772           }
9773           if (!colorspace)
9774             /* colr is required, and only values 16, 17, and 18 are specified,
9775                so error if we have no colorspace */
9776             break;
9777
9778           /* extract component mapping */
9779           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9780           if (cmap) {
9781             guint32 cmap_len = 0;
9782             int i;
9783             cmap_len = QT_UINT32 (cmap->data);
9784             if (cmap_len >= 8) {
9785               /* normal box, subtract off header */
9786               cmap_len -= 8;
9787               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9788               if (cmap_len % 4 == 0) {
9789                 ncomp_map = (cmap_len / 4);
9790                 comp_map = g_new0 (gint32, ncomp_map);
9791                 for (i = 0; i < ncomp_map; i++) {
9792                   guint16 cmp;
9793                   guint8 mtyp, pcol;
9794                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9795                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9796                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9797                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9798                 }
9799               }
9800             }
9801           }
9802           /* extract channel definitions */
9803           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9804           if (cdef) {
9805             guint32 cdef_len = 0;
9806             int i;
9807             cdef_len = QT_UINT32 (cdef->data);
9808             if (cdef_len >= 10) {
9809               /* normal box, subtract off header and len */
9810               cdef_len -= 10;
9811               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9812               if (cdef_len % 6 == 0) {
9813                 nchan_def = (cdef_len / 6);
9814                 chan_def = g_new0 (gint32, nchan_def);
9815                 for (i = 0; i < nchan_def; i++)
9816                   chan_def[i] = -1;
9817                 for (i = 0; i < nchan_def; i++) {
9818                   guint16 cn, typ, asoc;
9819                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9820                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9821                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9822                   if (cn < nchan_def) {
9823                     switch (typ) {
9824                       case 0:
9825                         chan_def[cn] = asoc;
9826                         break;
9827                       case 1:
9828                         chan_def[cn] = 0;       /* alpha */
9829                         break;
9830                       default:
9831                         chan_def[cn] = -typ;
9832                     }
9833                   }
9834                 }
9835               }
9836             }
9837           }
9838
9839           gst_caps_set_simple (stream->caps,
9840               "num-components", G_TYPE_INT, ncomp, NULL);
9841           gst_caps_set_simple (stream->caps,
9842               "colorspace", G_TYPE_STRING, colorspace, NULL);
9843
9844           if (comp_map) {
9845             GValue arr = { 0, };
9846             GValue elt = { 0, };
9847             int i;
9848             g_value_init (&arr, GST_TYPE_ARRAY);
9849             g_value_init (&elt, G_TYPE_INT);
9850             for (i = 0; i < ncomp_map; i++) {
9851               g_value_set_int (&elt, comp_map[i]);
9852               gst_value_array_append_value (&arr, &elt);
9853             }
9854             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9855                 "component-map", &arr);
9856             g_value_unset (&elt);
9857             g_value_unset (&arr);
9858             g_free (comp_map);
9859           }
9860
9861           if (chan_def) {
9862             GValue arr = { 0, };
9863             GValue elt = { 0, };
9864             int i;
9865             g_value_init (&arr, GST_TYPE_ARRAY);
9866             g_value_init (&elt, G_TYPE_INT);
9867             for (i = 0; i < nchan_def; i++) {
9868               g_value_set_int (&elt, chan_def[i]);
9869               gst_value_array_append_value (&arr, &elt);
9870             }
9871             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9872                 "channel-definitions", &arr);
9873             g_value_unset (&elt);
9874             g_value_unset (&arr);
9875             g_free (chan_def);
9876           }
9877
9878           /* some optional atoms */
9879           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9880           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9881
9882           /* indicate possible fields in caps */
9883           if (field) {
9884             data = (guint8 *) field->data + 8;
9885             if (*data != 1)
9886               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9887                   (gint) * data, NULL);
9888           }
9889           /* add codec_data if provided */
9890           if (prefix) {
9891             GstBuffer *buf;
9892             gint len;
9893
9894             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9895             data = prefix->data;
9896             len = QT_UINT32 (data);
9897             if (len > 0x8) {
9898               len -= 0x8;
9899               buf = gst_buffer_new_and_alloc (len);
9900               gst_buffer_fill (buf, 0, data + 8, len);
9901               gst_caps_set_simple (stream->caps,
9902                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9903               gst_buffer_unref (buf);
9904             }
9905           }
9906           break;
9907         }
9908         case FOURCC_SVQ3:
9909         case FOURCC_VP31:
9910         {
9911           GstBuffer *buf;
9912           GstBuffer *seqh = NULL;
9913           guint8 *gamma_data = NULL;
9914           gint len = QT_UINT32 (stsd_data);
9915
9916           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9917           if (gamma_data) {
9918             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9919                 QT_FP32 (gamma_data), NULL);
9920           }
9921           if (seqh) {
9922             /* sorry for the bad name, but we don't know what this is, other
9923              * than its own fourcc */
9924             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9925                 NULL);
9926           }
9927
9928           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9929           buf = gst_buffer_new_and_alloc (len);
9930           gst_buffer_fill (buf, 0, stsd_data, len);
9931           gst_caps_set_simple (stream->caps,
9932               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9933           gst_buffer_unref (buf);
9934           break;
9935         }
9936         case FOURCC_rle_:
9937         case FOURCC_WRLE:
9938         {
9939           gst_caps_set_simple (stream->caps,
9940               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9941           break;
9942         }
9943         case FOURCC_XiTh:
9944         {
9945           GNode *xith, *xdxt;
9946
9947           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9948           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9949           if (!xith)
9950             break;
9951
9952           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9953           if (!xdxt)
9954             break;
9955
9956           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9957           /* collect the headers and store them in a stream list so that we can
9958            * send them out first */
9959           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9960           break;
9961         }
9962         case FOURCC_ovc1:
9963         {
9964           GNode *ovc1;
9965           guint8 *ovc1_data;
9966           guint ovc1_len;
9967           GstBuffer *buf;
9968
9969           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9970           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9971           if (!ovc1)
9972             break;
9973           ovc1_data = ovc1->data;
9974           ovc1_len = QT_UINT32 (ovc1_data);
9975           if (ovc1_len <= 198) {
9976             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9977             break;
9978           }
9979           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9980           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9981           gst_caps_set_simple (stream->caps,
9982               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9983           gst_buffer_unref (buf);
9984           break;
9985         }
9986         case FOURCC_vc_1:
9987         {
9988           gint len = QT_UINT32 (stsd_data) - 0x66;
9989           const guint8 *vc1_data = stsd_data + 0x66;
9990
9991           /* find dvc1 */
9992           while (len >= 8) {
9993             gint size;
9994
9995             if (QT_UINT32 (vc1_data) <= len)
9996               size = QT_UINT32 (vc1_data) - 8;
9997             else
9998               size = len - 8;
9999
10000             if (size < 1)
10001               /* No real data, so break out */
10002               break;
10003
10004             switch (QT_FOURCC (vc1_data + 0x4)) {
10005               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10006               {
10007                 GstBuffer *buf;
10008
10009                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10010                 buf = gst_buffer_new_and_alloc (size);
10011                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
10012                 gst_caps_set_simple (stream->caps,
10013                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10014                 gst_buffer_unref (buf);
10015                 break;
10016               }
10017               default:
10018                 break;
10019             }
10020             len -= size + 8;
10021             vc1_data += size + 8;
10022           }
10023           break;
10024         }
10025         default:
10026           break;
10027       }
10028     }
10029
10030     GST_INFO_OBJECT (qtdemux,
10031         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10032         GST_FOURCC_ARGS (fourcc), stream->caps);
10033
10034   } else if (stream->subtype == FOURCC_soun) {
10035     int version, samplesize;
10036     guint16 compression_id;
10037     gboolean amrwb = FALSE;
10038
10039     offset = 32;
10040     /* sample description entry (16) + sound sample description v0 (20) */
10041     if (len < 36)
10042       goto corrupt_file;
10043
10044     version = QT_UINT32 (stsd_data + offset);
10045     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10046     samplesize = QT_UINT16 (stsd_data + offset + 10);
10047     compression_id = QT_UINT16 (stsd_data + offset + 12);
10048     stream->rate = QT_FP32 (stsd_data + offset + 16);
10049
10050     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10051     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10052         QT_UINT32 (stsd_data + offset + 4));
10053     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10054     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10055     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10056     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10057         QT_UINT16 (stsd_data + offset + 14));
10058     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10059
10060     if (compression_id == 0xfffe)
10061       stream->sampled = TRUE;
10062
10063     /* first assume uncompressed audio */
10064     stream->bytes_per_sample = samplesize / 8;
10065     stream->samples_per_frame = stream->n_channels;
10066     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10067     stream->samples_per_packet = stream->samples_per_frame;
10068     stream->bytes_per_packet = stream->bytes_per_sample;
10069
10070     offset = 52;
10071     switch (fourcc) {
10072         /* Yes, these have to be hard-coded */
10073       case FOURCC_MAC6:
10074       {
10075         stream->samples_per_packet = 6;
10076         stream->bytes_per_packet = 1;
10077         stream->bytes_per_frame = 1 * stream->n_channels;
10078         stream->bytes_per_sample = 1;
10079         stream->samples_per_frame = 6 * stream->n_channels;
10080         break;
10081       }
10082       case FOURCC_MAC3:
10083       {
10084         stream->samples_per_packet = 3;
10085         stream->bytes_per_packet = 1;
10086         stream->bytes_per_frame = 1 * stream->n_channels;
10087         stream->bytes_per_sample = 1;
10088         stream->samples_per_frame = 3 * stream->n_channels;
10089         break;
10090       }
10091       case FOURCC_ima4:
10092       {
10093         stream->samples_per_packet = 64;
10094         stream->bytes_per_packet = 34;
10095         stream->bytes_per_frame = 34 * stream->n_channels;
10096         stream->bytes_per_sample = 2;
10097         stream->samples_per_frame = 64 * stream->n_channels;
10098         break;
10099       }
10100       case FOURCC_ulaw:
10101       case FOURCC_alaw:
10102       {
10103         stream->samples_per_packet = 1;
10104         stream->bytes_per_packet = 1;
10105         stream->bytes_per_frame = 1 * stream->n_channels;
10106         stream->bytes_per_sample = 1;
10107         stream->samples_per_frame = 1 * stream->n_channels;
10108         break;
10109       }
10110       case FOURCC_agsm:
10111       {
10112         stream->samples_per_packet = 160;
10113         stream->bytes_per_packet = 33;
10114         stream->bytes_per_frame = 33 * stream->n_channels;
10115         stream->bytes_per_sample = 2;
10116         stream->samples_per_frame = 160 * stream->n_channels;
10117         break;
10118       }
10119       default:
10120         break;
10121     }
10122
10123     if (version == 0x00010000) {
10124       /* sample description entry (16) + sound sample description v1 (20+16) */
10125       if (len < 52)
10126         goto corrupt_file;
10127
10128       switch (fourcc) {
10129         case FOURCC_twos:
10130         case FOURCC_sowt:
10131         case FOURCC_raw_:
10132           break;
10133         default:
10134         {
10135           /* only parse extra decoding config for non-pcm audio */
10136           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10137           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10138           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10139           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10140
10141           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10142               stream->samples_per_packet);
10143           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10144               stream->bytes_per_packet);
10145           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10146               stream->bytes_per_frame);
10147           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10148               stream->bytes_per_sample);
10149
10150           if (!stream->sampled && stream->bytes_per_packet) {
10151             stream->samples_per_frame = (stream->bytes_per_frame /
10152                 stream->bytes_per_packet) * stream->samples_per_packet;
10153             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10154                 stream->samples_per_frame);
10155           }
10156           break;
10157         }
10158       }
10159     } else if (version == 0x00020000) {
10160       union
10161       {
10162         gdouble fp;
10163         guint64 val;
10164       } qtfp;
10165
10166       /* sample description entry (16) + sound sample description v2 (56) */
10167       if (len < 72)
10168         goto corrupt_file;
10169
10170       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10171       stream->rate = qtfp.fp;
10172       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10173
10174       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10175       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10176       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10177       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10178           QT_UINT32 (stsd_data + offset + 20));
10179       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10180           QT_UINT32 (stsd_data + offset + 24));
10181       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10182           QT_UINT32 (stsd_data + offset + 28));
10183       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10184           QT_UINT32 (stsd_data + offset + 32));
10185     } else if (version != 0x00000) {
10186       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10187     }
10188
10189     if (stream->caps)
10190       gst_caps_unref (stream->caps);
10191
10192     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10193         stsd_data + 32, len - 16, &codec);
10194
10195     switch (fourcc) {
10196       case FOURCC_in24:
10197       {
10198         GNode *enda;
10199         GNode *in24;
10200
10201         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10202
10203         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10204         if (!enda) {
10205           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10206           if (wave)
10207             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10208         }
10209         if (enda) {
10210           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10211           gst_caps_set_simple (stream->caps,
10212               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10213         }
10214         break;
10215       }
10216       case FOURCC_owma:
10217       {
10218         GNode *owma;
10219         const guint8 *owma_data;
10220         const gchar *codec_name = NULL;
10221         guint owma_len;
10222         GstBuffer *buf;
10223         gint version = 1;
10224         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10225         /* FIXME this should also be gst_riff_strf_auds,
10226          * but the latter one is actually missing bits-per-sample :( */
10227         typedef struct
10228         {
10229           gint16 wFormatTag;
10230           gint16 nChannels;
10231           gint32 nSamplesPerSec;
10232           gint32 nAvgBytesPerSec;
10233           gint16 nBlockAlign;
10234           gint16 wBitsPerSample;
10235           gint16 cbSize;
10236         } WAVEFORMATEX;
10237         WAVEFORMATEX *wfex;
10238
10239         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10240         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10241         if (!owma)
10242           break;
10243         owma_data = owma->data;
10244         owma_len = QT_UINT32 (owma_data);
10245         if (owma_len <= 54) {
10246           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10247           break;
10248         }
10249         wfex = (WAVEFORMATEX *) (owma_data + 36);
10250         buf = gst_buffer_new_and_alloc (owma_len - 54);
10251         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10252         if (wfex->wFormatTag == 0x0161) {
10253           codec_name = "Windows Media Audio";
10254           version = 2;
10255         } else if (wfex->wFormatTag == 0x0162) {
10256           codec_name = "Windows Media Audio 9 Pro";
10257           version = 3;
10258         } else if (wfex->wFormatTag == 0x0163) {
10259           codec_name = "Windows Media Audio 9 Lossless";
10260           /* is that correct? gstffmpegcodecmap.c is missing it, but
10261            * fluendo codec seems to support it */
10262           version = 4;
10263         }
10264
10265         gst_caps_set_simple (stream->caps,
10266             "codec_data", GST_TYPE_BUFFER, buf,
10267             "wmaversion", G_TYPE_INT, version,
10268             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10269             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10270             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10271             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10272             NULL);
10273         gst_buffer_unref (buf);
10274
10275         if (codec_name) {
10276           g_free (codec);
10277           codec = g_strdup (codec_name);
10278         }
10279         break;
10280       }
10281       case FOURCC_wma_:
10282       {
10283         gint len = QT_UINT32 (stsd_data) - offset;
10284         const guint8 *wfex_data = stsd_data + offset;
10285         const gchar *codec_name = NULL;
10286         gint version = 1;
10287         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10288         /* FIXME this should also be gst_riff_strf_auds,
10289          * but the latter one is actually missing bits-per-sample :( */
10290         typedef struct
10291         {
10292           gint16 wFormatTag;
10293           gint16 nChannels;
10294           gint32 nSamplesPerSec;
10295           gint32 nAvgBytesPerSec;
10296           gint16 nBlockAlign;
10297           gint16 wBitsPerSample;
10298           gint16 cbSize;
10299         } WAVEFORMATEX;
10300         WAVEFORMATEX wfex;
10301
10302         /* FIXME: unify with similar wavformatex parsing code above */
10303         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10304
10305         /* find wfex */
10306         while (len >= 8) {
10307           gint size;
10308
10309           if (QT_UINT32 (wfex_data) <= len)
10310             size = QT_UINT32 (wfex_data) - 8;
10311           else
10312             size = len - 8;
10313
10314           if (size < 1)
10315             /* No real data, so break out */
10316             break;
10317
10318           switch (QT_FOURCC (wfex_data + 4)) {
10319             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10320             {
10321               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10322
10323               if (size < 8 + 18)
10324                 break;
10325
10326               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10327               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10328               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10329               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10330               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10331               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10332               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10333
10334               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10335               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10336                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10337                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10338                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10339                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10340
10341               if (wfex.wFormatTag == 0x0161) {
10342                 codec_name = "Windows Media Audio";
10343                 version = 2;
10344               } else if (wfex.wFormatTag == 0x0162) {
10345                 codec_name = "Windows Media Audio 9 Pro";
10346                 version = 3;
10347               } else if (wfex.wFormatTag == 0x0163) {
10348                 codec_name = "Windows Media Audio 9 Lossless";
10349                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10350                  * fluendo codec seems to support it */
10351                 version = 4;
10352               }
10353
10354               gst_caps_set_simple (stream->caps,
10355                   "wmaversion", G_TYPE_INT, version,
10356                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10357                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10358                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10359                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10360
10361               if (size > wfex.cbSize) {
10362                 GstBuffer *buf;
10363
10364                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10365                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10366                     size - wfex.cbSize);
10367                 gst_caps_set_simple (stream->caps,
10368                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10369                 gst_buffer_unref (buf);
10370               } else {
10371                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10372               }
10373
10374               if (codec_name) {
10375                 g_free (codec);
10376                 codec = g_strdup (codec_name);
10377               }
10378               break;
10379             }
10380             default:
10381               break;
10382           }
10383           len -= size + 8;
10384           wfex_data += size + 8;
10385         }
10386         break;
10387       }
10388       case FOURCC_opus:
10389       {
10390         GNode *opus;
10391         const guint8 *opus_data;
10392         guint8 *channel_mapping = NULL;
10393         guint32 rate;
10394         guint8 channels;
10395         guint8 channel_mapping_family;
10396         guint8 stream_count;
10397         guint8 coupled_count;
10398         guint8 i;
10399
10400         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10401         opus_data = opus->data;
10402
10403         channels = GST_READ_UINT8 (opus_data + 45);
10404         rate = GST_READ_UINT32_LE (opus_data + 48);
10405         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10406         stream_count = GST_READ_UINT8 (opus_data + 55);
10407         coupled_count = GST_READ_UINT8 (opus_data + 56);
10408
10409         if (channels > 0) {
10410           channel_mapping = g_malloc (channels * sizeof (guint8));
10411           for (i = 0; i < channels; i++)
10412             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10413         }
10414
10415         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10416             channel_mapping_family, stream_count, coupled_count,
10417             channel_mapping);
10418         break;
10419       }
10420       default:
10421         break;
10422     }
10423
10424     if (codec) {
10425       GstStructure *s;
10426       gint bitrate = 0;
10427
10428       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10429           GST_TAG_AUDIO_CODEC, codec, NULL);
10430       g_free (codec);
10431       codec = NULL;
10432
10433       /* some bitrate info may have ended up in caps */
10434       s = gst_caps_get_structure (stream->caps, 0);
10435       gst_structure_get_int (s, "bitrate", &bitrate);
10436       if (bitrate > 0)
10437         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10438             GST_TAG_BITRATE, bitrate, NULL);
10439     }
10440
10441     if (stream->protected && fourcc == FOURCC_mp4a)
10442       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10443     else
10444       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10445
10446     wave = NULL;
10447     esds = NULL;
10448     if (mp4a) {
10449       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10450       if (wave)
10451         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10452       if (!esds)
10453         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10454     }
10455
10456
10457     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10458        16 bits is a byte-swapped wave-style codec identifier,
10459        and we can find a WAVE header internally to a 'wave' atom here.
10460        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10461        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10462        is big-endian).
10463      */
10464     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10465       if (len < offset + 20) {
10466         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10467       } else {
10468         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10469         const guint8 *data = stsd_data + offset + 16;
10470         GNode *wavenode;
10471         GNode *waveheadernode;
10472
10473         wavenode = g_node_new ((guint8 *) data);
10474         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10475           const guint8 *waveheader;
10476           guint32 headerlen;
10477
10478           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10479           if (waveheadernode) {
10480             waveheader = (const guint8 *) waveheadernode->data;
10481             headerlen = QT_UINT32 (waveheader);
10482
10483             if (headerlen > 8) {
10484               gst_riff_strf_auds *header = NULL;
10485               GstBuffer *headerbuf;
10486               GstBuffer *extra;
10487
10488               waveheader += 8;
10489               headerlen -= 8;
10490
10491               headerbuf = gst_buffer_new_and_alloc (headerlen);
10492               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10493
10494               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10495                       headerbuf, &header, &extra)) {
10496                 gst_caps_unref (stream->caps);
10497                 /* FIXME: Need to do something with the channel reorder map */
10498                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10499                     header, extra, NULL, NULL, NULL);
10500
10501                 if (extra)
10502                   gst_buffer_unref (extra);
10503                 g_free (header);
10504               }
10505             }
10506           } else
10507             GST_DEBUG ("Didn't find waveheadernode for this codec");
10508         }
10509         g_node_destroy (wavenode);
10510       }
10511     } else if (esds) {
10512       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10513     } else {
10514       switch (fourcc) {
10515 #if 0
10516           /* FIXME: what is in the chunk? */
10517         case FOURCC_QDMC:
10518         {
10519           gint len = QT_UINT32 (stsd_data);
10520
10521           /* seems to be always = 116 = 0x74 */
10522           break;
10523         }
10524 #endif
10525         case FOURCC_QDM2:
10526         {
10527           gint len = QT_UINT32 (stsd_data);
10528
10529           if (len > 0x4C) {
10530             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10531
10532             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10533             gst_caps_set_simple (stream->caps,
10534                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10535             gst_buffer_unref (buf);
10536           }
10537           gst_caps_set_simple (stream->caps,
10538               "samplesize", G_TYPE_INT, samplesize, NULL);
10539           break;
10540         }
10541         case FOURCC_alac:
10542         {
10543           GNode *alac, *wave = NULL;
10544
10545           /* apparently, m4a has this atom appended directly in the stsd entry,
10546            * while mov has it in a wave atom */
10547           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10548           if (alac) {
10549             /* alac now refers to stsd entry atom */
10550             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10551             if (wave)
10552               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10553             else
10554               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10555           }
10556           if (alac) {
10557             const guint8 *alac_data = alac->data;
10558             gint len = QT_UINT32 (alac->data);
10559             GstBuffer *buf;
10560
10561             if (len < 36) {
10562               GST_DEBUG_OBJECT (qtdemux,
10563                   "discarding alac atom with unexpected len %d", len);
10564             } else {
10565               /* codec-data contains alac atom size and prefix,
10566                * ffmpeg likes it that way, not quite gst-ish though ...*/
10567               buf = gst_buffer_new_and_alloc (len);
10568               gst_buffer_fill (buf, 0, alac->data, len);
10569               gst_caps_set_simple (stream->caps,
10570                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10571               gst_buffer_unref (buf);
10572
10573               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10574               stream->n_channels = QT_UINT8 (alac_data + 21);
10575               stream->rate = QT_UINT32 (alac_data + 32);
10576             }
10577           }
10578           gst_caps_set_simple (stream->caps,
10579               "samplesize", G_TYPE_INT, samplesize, NULL);
10580           break;
10581         }
10582         case FOURCC_sawb:
10583           /* Fallthrough! */
10584           amrwb = TRUE;
10585         case FOURCC_samr:
10586         {
10587           gint len = QT_UINT32 (stsd_data);
10588
10589           if (len > 0x34) {
10590             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10591             guint bitrate;
10592
10593             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10594
10595             /* If we have enough data, let's try to get the 'damr' atom. See
10596              * the 3GPP container spec (26.244) for more details. */
10597             if ((len - 0x34) > 8 &&
10598                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10599               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10600                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10601             }
10602
10603             gst_caps_set_simple (stream->caps,
10604                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10605             gst_buffer_unref (buf);
10606           }
10607           break;
10608         }
10609         case FOURCC_mp4a:
10610         {
10611           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10612           gint len = QT_UINT32 (stsd_data);
10613
10614           if (len >= 50) {
10615             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10616
10617             if (sound_version == 1) {
10618               guint16 channels = QT_UINT16 (stsd_data + 40);
10619               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10620               guint8 codec_data[2];
10621               GstBuffer *buf;
10622               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10623
10624               gint sample_rate_index =
10625                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10626
10627               /* build AAC codec data */
10628               codec_data[0] = profile << 3;
10629               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10630               codec_data[1] = (sample_rate_index & 0x01) << 7;
10631               codec_data[1] |= (channels & 0xF) << 3;
10632
10633               buf = gst_buffer_new_and_alloc (2);
10634               gst_buffer_fill (buf, 0, codec_data, 2);
10635               gst_caps_set_simple (stream->caps,
10636                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10637               gst_buffer_unref (buf);
10638             }
10639           }
10640           break;
10641         }
10642         default:
10643           GST_INFO_OBJECT (qtdemux,
10644               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10645           break;
10646       }
10647     }
10648     GST_INFO_OBJECT (qtdemux,
10649         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10650         GST_FOURCC_ARGS (fourcc), stream->caps);
10651
10652   } else if (stream->subtype == FOURCC_strm) {
10653     if (fourcc == FOURCC_rtsp) {
10654       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10655     } else {
10656       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10657           GST_FOURCC_ARGS (fourcc));
10658       goto unknown_stream;
10659     }
10660     stream->sampled = TRUE;
10661   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10662       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10663
10664     stream->sampled = TRUE;
10665     stream->sparse = TRUE;
10666
10667     stream->caps =
10668         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10669     if (codec) {
10670       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10671           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10672       g_free (codec);
10673       codec = NULL;
10674     }
10675
10676     /* hunt for sort-of codec data */
10677     switch (fourcc) {
10678       case FOURCC_mp4s:
10679       {
10680         GNode *mp4s = NULL;
10681         GNode *esds = NULL;
10682
10683         /* look for palette in a stsd->mp4s->esds sub-atom */
10684         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10685         if (mp4s)
10686           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10687         if (esds == NULL) {
10688           /* Invalid STSD */
10689           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10690           break;
10691         }
10692
10693         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10694         break;
10695       }
10696       default:
10697         GST_INFO_OBJECT (qtdemux,
10698             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10699         break;
10700     }
10701     GST_INFO_OBJECT (qtdemux,
10702         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10703         GST_FOURCC_ARGS (fourcc), stream->caps);
10704   } else {
10705     /* everything in 1 sample */
10706     stream->sampled = TRUE;
10707
10708     stream->caps =
10709         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10710
10711     if (stream->caps == NULL)
10712       goto unknown_stream;
10713
10714     if (codec) {
10715       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10716           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10717       g_free (codec);
10718       codec = NULL;
10719     }
10720   }
10721
10722   /* promote to sampled format */
10723   if (stream->fourcc == FOURCC_samr) {
10724     /* force mono 8000 Hz for AMR */
10725     stream->sampled = TRUE;
10726     stream->n_channels = 1;
10727     stream->rate = 8000;
10728   } else if (stream->fourcc == FOURCC_sawb) {
10729     /* force mono 16000 Hz for AMR-WB */
10730     stream->sampled = TRUE;
10731     stream->n_channels = 1;
10732     stream->rate = 16000;
10733   } else if (stream->fourcc == FOURCC_mp4a) {
10734     stream->sampled = TRUE;
10735   }
10736
10737   /* collect sample information */
10738   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10739     goto samples_failed;
10740
10741   if (qtdemux->fragmented) {
10742     guint64 offset;
10743
10744     /* need all moov samples as basis; probably not many if any at all */
10745     /* prevent moof parsing taking of at this time */
10746     offset = qtdemux->moof_offset;
10747     qtdemux->moof_offset = 0;
10748     if (stream->n_samples &&
10749         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10750       qtdemux->moof_offset = offset;
10751       goto samples_failed;
10752     }
10753     qtdemux->moof_offset = 0;
10754     /* movie duration more reliable in this case (e.g. mehd) */
10755     if (qtdemux->segment.duration &&
10756         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10757       stream->duration =
10758           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10759   }
10760
10761   /* configure segments */
10762   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10763     goto segments_failed;
10764
10765   /* add some language tag, if useful */
10766   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10767       strcmp (stream->lang_id, "und")) {
10768     const gchar *lang_code;
10769
10770     /* convert ISO 639-2 code to ISO 639-1 */
10771     lang_code = gst_tag_get_language_code (stream->lang_id);
10772     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10773         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10774   }
10775
10776   /* Check for UDTA tags */
10777   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10778     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10779   }
10780
10781   /* now we are ready to add the stream */
10782   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10783     goto too_many_streams;
10784
10785   if (!qtdemux->got_moov) {
10786     qtdemux->streams[qtdemux->n_streams] = stream;
10787     qtdemux->n_streams++;
10788     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10789   }
10790
10791   return TRUE;
10792
10793 /* ERRORS */
10794 skip_track:
10795   {
10796     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10797     if (new_stream)
10798       gst_qtdemux_stream_free (qtdemux, stream);
10799     return TRUE;
10800   }
10801 corrupt_file:
10802   {
10803     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10804         (_("This file is corrupt and cannot be played.")), (NULL));
10805     if (new_stream)
10806       gst_qtdemux_stream_free (qtdemux, stream);
10807     return FALSE;
10808   }
10809 error_encrypted:
10810   {
10811     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10812     if (new_stream)
10813       gst_qtdemux_stream_free (qtdemux, stream);
10814     return FALSE;
10815   }
10816 samples_failed:
10817 segments_failed:
10818   {
10819     /* we posted an error already */
10820     /* free stbl sub-atoms */
10821     gst_qtdemux_stbl_free (stream);
10822     if (new_stream)
10823       gst_qtdemux_stream_free (qtdemux, stream);
10824     return FALSE;
10825   }
10826 existing_stream:
10827   {
10828     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10829         track_id);
10830     if (new_stream)
10831       gst_qtdemux_stream_free (qtdemux, stream);
10832     return TRUE;
10833   }
10834 unknown_stream:
10835   {
10836     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10837         GST_FOURCC_ARGS (stream->subtype));
10838     if (new_stream)
10839       gst_qtdemux_stream_free (qtdemux, stream);
10840     return TRUE;
10841   }
10842 too_many_streams:
10843   {
10844     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10845         (_("This file contains too many streams. Only playing first %d"),
10846             GST_QTDEMUX_MAX_STREAMS), (NULL));
10847     return TRUE;
10848   }
10849 }
10850
10851 /* If we can estimate the overall bitrate, and don't have information about the
10852  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10853  * the overall bitrate minus the sum of the bitrates of all other streams. This
10854  * should be useful for the common case where we have one audio and one video
10855  * stream and can estimate the bitrate of one, but not the other. */
10856 static void
10857 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10858 {
10859   QtDemuxStream *stream = NULL;
10860   gint64 size, sys_bitrate, sum_bitrate = 0;
10861   GstClockTime duration;
10862   gint i;
10863   guint bitrate;
10864
10865   if (qtdemux->fragmented)
10866     return;
10867
10868   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10869
10870   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10871       || size <= 0) {
10872     GST_DEBUG_OBJECT (qtdemux,
10873         "Size in bytes of the stream not known - bailing");
10874     return;
10875   }
10876
10877   /* Subtract the header size */
10878   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10879       size, qtdemux->header_size);
10880
10881   if (size < qtdemux->header_size)
10882     return;
10883
10884   size = size - qtdemux->header_size;
10885
10886   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
10887     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10888     return;
10889   }
10890
10891   for (i = 0; i < qtdemux->n_streams; i++) {
10892     switch (qtdemux->streams[i]->subtype) {
10893       case FOURCC_soun:
10894       case FOURCC_vide:
10895         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10896             qtdemux->streams[i]->caps);
10897         /* retrieve bitrate, prefer avg then max */
10898         bitrate = 0;
10899         if (qtdemux->streams[i]->pending_tags) {
10900           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10901               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10902           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10903           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10904               GST_TAG_NOMINAL_BITRATE, &bitrate);
10905           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10906           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10907               GST_TAG_BITRATE, &bitrate);
10908           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10909         }
10910         if (bitrate)
10911           sum_bitrate += bitrate;
10912         else {
10913           if (stream) {
10914             GST_DEBUG_OBJECT (qtdemux,
10915                 ">1 stream with unknown bitrate - bailing");
10916             return;
10917           } else
10918             stream = qtdemux->streams[i];
10919         }
10920
10921       default:
10922         /* For other subtypes, we assume no significant impact on bitrate */
10923         break;
10924     }
10925   }
10926
10927   if (!stream) {
10928     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10929     return;
10930   }
10931
10932   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10933
10934   if (sys_bitrate < sum_bitrate) {
10935     /* This can happen, since sum_bitrate might be derived from maximum
10936      * bitrates and not average bitrates */
10937     GST_DEBUG_OBJECT (qtdemux,
10938         "System bitrate less than sum bitrate - bailing");
10939     return;
10940   }
10941
10942   bitrate = sys_bitrate - sum_bitrate;
10943   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10944       ", Stream bitrate = %u", sys_bitrate, bitrate);
10945
10946   if (!stream->pending_tags)
10947     stream->pending_tags = gst_tag_list_new_empty ();
10948
10949   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10950       GST_TAG_BITRATE, bitrate, NULL);
10951 }
10952
10953 static GstFlowReturn
10954 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10955 {
10956   gint i;
10957   GstFlowReturn ret = GST_FLOW_OK;
10958
10959   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10960
10961   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10962     QtDemuxStream *stream = qtdemux->streams[i];
10963     guint32 sample_num = 0;
10964
10965     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10966         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10967
10968     if (qtdemux->fragmented) {
10969       /* need all moov samples first */
10970       GST_OBJECT_LOCK (qtdemux);
10971       while (stream->n_samples == 0)
10972         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10973           break;
10974       GST_OBJECT_UNLOCK (qtdemux);
10975     } else {
10976       /* discard any stray moof */
10977       qtdemux->moof_offset = 0;
10978     }
10979
10980     /* prepare braking */
10981     if (ret != GST_FLOW_ERROR)
10982       ret = GST_FLOW_OK;
10983
10984     /* in pull mode, we should have parsed some sample info by now;
10985      * and quite some code will not handle no samples.
10986      * in push mode, we'll just have to deal with it */
10987     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10988       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10989       gst_qtdemux_remove_stream (qtdemux, i);
10990       i--;
10991       continue;
10992     }
10993
10994     /* parse the initial sample for use in setting the frame rate cap */
10995     while (sample_num == 0 && sample_num < stream->n_samples) {
10996       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10997         break;
10998       ++sample_num;
10999     }
11000     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11001       stream->first_duration = stream->samples[0].duration;
11002       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11003           stream->track_id, stream->first_duration);
11004     }
11005   }
11006
11007   return ret;
11008 }
11009
11010 static GstFlowReturn
11011 qtdemux_expose_streams (GstQTDemux * qtdemux)
11012 {
11013   gint i;
11014   GstFlowReturn ret = GST_FLOW_OK;
11015   GSList *oldpads = NULL;
11016   GSList *iter;
11017
11018   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11019
11020   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11021     QtDemuxStream *stream = qtdemux->streams[i];
11022     GstPad *oldpad = stream->pad;
11023     GstTagList *list;
11024
11025     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11026         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11027
11028     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11029         stream->track_id == qtdemux->chapters_track_id) {
11030       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11031          so that it doesn't look like a subtitle track */
11032       gst_qtdemux_remove_stream (qtdemux, i);
11033       i--;
11034       continue;
11035     }
11036
11037     /* now we have all info and can expose */
11038     list = stream->pending_tags;
11039     stream->pending_tags = NULL;
11040     if (oldpad)
11041       oldpads = g_slist_prepend (oldpads, oldpad);
11042     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11043       return GST_FLOW_ERROR;
11044   }
11045
11046   gst_qtdemux_guess_bitrate (qtdemux);
11047
11048   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11049
11050   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11051     GstPad *oldpad = iter->data;
11052     GstEvent *event;
11053
11054     event = gst_event_new_eos ();
11055     if (qtdemux->segment_seqnum)
11056       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11057
11058     gst_pad_push_event (oldpad, event);
11059     gst_pad_set_active (oldpad, FALSE);
11060     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11061     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11062     gst_object_unref (oldpad);
11063   }
11064
11065   /* check if we should post a redirect in case there is a single trak
11066    * and it is a redirecting trak */
11067   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11068     GstMessage *m;
11069
11070     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11071         "an external content");
11072     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11073         gst_structure_new ("redirect",
11074             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11075             NULL));
11076     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11077     qtdemux->posted_redirect = TRUE;
11078   }
11079
11080   for (i = 0; i < qtdemux->n_streams; i++) {
11081     QtDemuxStream *stream = qtdemux->streams[i];
11082
11083     qtdemux_do_allocation (qtdemux, stream);
11084   }
11085
11086   qtdemux->exposed = TRUE;
11087   return ret;
11088 }
11089
11090 /* check if major or compatible brand is 3GP */
11091 static inline gboolean
11092 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11093 {
11094   if (major) {
11095     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11096         FOURCC_3g__);
11097   } else if (qtdemux->comp_brands != NULL) {
11098     GstMapInfo map;
11099     guint8 *data;
11100     gsize size;
11101     gboolean res = FALSE;
11102
11103     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11104     data = map.data;
11105     size = map.size;
11106     while (size >= 4) {
11107       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11108           FOURCC_3g__);
11109       data += 4;
11110       size -= 4;
11111     }
11112     gst_buffer_unmap (qtdemux->comp_brands, &map);
11113     return res;
11114   } else {
11115     return FALSE;
11116   }
11117 }
11118
11119 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11120 static inline gboolean
11121 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11122 {
11123   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11124       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11125       || fourcc == FOURCC_albm;
11126 }
11127
11128 static void
11129 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11130     const char *tag, const char *dummy, GNode * node)
11131 {
11132   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11133   int offset;
11134   char *name;
11135   gchar *data;
11136   gdouble longitude, latitude, altitude;
11137   gint len;
11138
11139   len = QT_UINT32 (node->data);
11140   if (len <= 14)
11141     goto short_read;
11142
11143   data = node->data;
11144   offset = 14;
11145
11146   /* TODO: language code skipped */
11147
11148   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11149
11150   if (!name) {
11151     /* do not alarm in trivial case, but bail out otherwise */
11152     if (*(data + offset) != 0) {
11153       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11154           "giving up", tag);
11155     }
11156   } else {
11157     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11158         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11159     offset += strlen (name);
11160     g_free (name);
11161   }
11162
11163   if (len < offset + 2 + 4 + 4 + 4)
11164     goto short_read;
11165
11166   /* +1 +1 = skip null-terminator and location role byte */
11167   offset += 1 + 1;
11168   /* table in spec says unsigned, semantics say negative has meaning ... */
11169   longitude = QT_SFP32 (data + offset);
11170
11171   offset += 4;
11172   latitude = QT_SFP32 (data + offset);
11173
11174   offset += 4;
11175   altitude = QT_SFP32 (data + offset);
11176
11177   /* one invalid means all are invalid */
11178   if (longitude >= -180.0 && longitude <= 180.0 &&
11179       latitude >= -90.0 && latitude <= 90.0) {
11180     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11181         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11182         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11183         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11184   }
11185
11186   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11187
11188   return;
11189
11190   /* ERRORS */
11191 short_read:
11192   {
11193     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11194     return;
11195   }
11196 }
11197
11198
11199 static void
11200 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11201     const char *tag, const char *dummy, GNode * node)
11202 {
11203   guint16 y;
11204   GDate *date;
11205   gint len;
11206
11207   len = QT_UINT32 (node->data);
11208   if (len < 14)
11209     return;
11210
11211   y = QT_UINT16 ((guint8 *) node->data + 12);
11212   if (y == 0) {
11213     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11214     return;
11215   }
11216   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11217
11218   date = g_date_new_dmy (1, 1, y);
11219   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11220   g_date_free (date);
11221 }
11222
11223 static void
11224 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11225     const char *tag, const char *dummy, GNode * node)
11226 {
11227   int offset;
11228   char *tag_str = NULL;
11229   guint8 *entity;
11230   guint16 table;
11231   gint len;
11232
11233   len = QT_UINT32 (node->data);
11234   if (len <= 20)
11235     goto short_read;
11236
11237   offset = 12;
11238   entity = (guint8 *) node->data + offset;
11239   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11240     GST_DEBUG_OBJECT (qtdemux,
11241         "classification info: %c%c%c%c invalid classification entity",
11242         entity[0], entity[1], entity[2], entity[3]);
11243     return;
11244   }
11245
11246   offset += 4;
11247   table = QT_UINT16 ((guint8 *) node->data + offset);
11248
11249   /* Language code skipped */
11250
11251   offset += 4;
11252
11253   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11254    * XXXX: classification entity, fixed length 4 chars.
11255    * Y[YYYY]: classification table, max 5 chars.
11256    */
11257   tag_str = g_strdup_printf ("----://%u/%s",
11258       table, (char *) node->data + offset);
11259
11260   /* memcpy To be sure we're preserving byte order */
11261   memcpy (tag_str, entity, 4);
11262   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11263
11264   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11265
11266   g_free (tag_str);
11267
11268   return;
11269
11270   /* ERRORS */
11271 short_read:
11272   {
11273     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11274     return;
11275   }
11276 }
11277
11278 static gboolean
11279 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11280     const char *tag, const char *dummy, GNode * node)
11281 {
11282   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11283   GNode *data;
11284   char *s;
11285   int len;
11286   guint32 type;
11287   int offset;
11288   gboolean ret = TRUE;
11289   const gchar *charset = NULL;
11290
11291   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11292   if (data) {
11293     len = QT_UINT32 (data->data);
11294     type = QT_UINT32 ((guint8 *) data->data + 8);
11295     if (type == 0x00000001 && len > 16) {
11296       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11297           env_vars);
11298       if (s) {
11299         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11300         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11301         g_free (s);
11302       } else {
11303         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11304       }
11305     }
11306   } else {
11307     len = QT_UINT32 (node->data);
11308     type = QT_UINT32 ((guint8 *) node->data + 4);
11309     if ((type >> 24) == 0xa9) {
11310       gint str_len;
11311       gint lang_code;
11312
11313       /* Type starts with the (C) symbol, so the next data is a list
11314        * of (string size(16), language code(16), string) */
11315
11316       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11317       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11318
11319       /* the string + fourcc + size + 2 16bit fields,
11320        * means that there are more tags in this atom */
11321       if (len > str_len + 8 + 4) {
11322         /* TODO how to represent the same tag in different languages? */
11323         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11324             "text alternatives, reading only first one");
11325       }
11326
11327       offset = 12;
11328       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
11329       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11330
11331       if (lang_code < 0x800) {  /* MAC encoded string */
11332         charset = "mac";
11333       }
11334     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11335             QT_FOURCC ((guint8 *) node->data + 4))) {
11336       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11337
11338       /* we go for 3GP style encoding if major brands claims so,
11339        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11340       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11341           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11342               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11343         offset = 14;
11344         /* 16-bit Language code is ignored here as well */
11345         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11346       } else {
11347         goto normal;
11348       }
11349     } else {
11350     normal:
11351       offset = 8;
11352       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11353       ret = FALSE;              /* may have to fallback */
11354     }
11355     if (charset) {
11356       GError *err = NULL;
11357
11358       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11359           charset, NULL, NULL, &err);
11360       if (err) {
11361         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11362             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11363             err->message);
11364         g_error_free (err);
11365       }
11366     } else {
11367       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11368           len - offset, env_vars);
11369     }
11370     if (s) {
11371       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11372       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11373       g_free (s);
11374       ret = TRUE;
11375     } else {
11376       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11377     }
11378   }
11379   return ret;
11380 }
11381
11382 static void
11383 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11384     const char *tag, const char *dummy, GNode * node)
11385 {
11386   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11387 }
11388
11389 static void
11390 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11391     const char *tag, const char *dummy, GNode * node)
11392 {
11393   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11394   guint8 *data;
11395   char *s, *t, *k = NULL;
11396   int len;
11397   int offset;
11398   int count;
11399
11400   /* first try normal string tag if major brand not 3GP */
11401   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11402     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11403       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11404        * let's try it 3gpp way after minor safety check */
11405       data = node->data;
11406       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11407         return;
11408     } else
11409       return;
11410   }
11411
11412   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11413
11414   data = node->data;
11415
11416   len = QT_UINT32 (data);
11417   if (len < 15)
11418     goto short_read;
11419
11420   count = QT_UINT8 (data + 14);
11421   offset = 15;
11422   for (; count; count--) {
11423     gint slen;
11424
11425     if (offset + 1 > len)
11426       goto short_read;
11427     slen = QT_UINT8 (data + offset);
11428     offset += 1;
11429     if (offset + slen > len)
11430       goto short_read;
11431     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11432         slen, env_vars);
11433     if (s) {
11434       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11435       if (k) {
11436         t = g_strjoin (",", k, s, NULL);
11437         g_free (s);
11438         g_free (k);
11439         k = t;
11440       } else {
11441         k = s;
11442       }
11443     } else {
11444       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11445     }
11446     offset += slen;
11447   }
11448
11449 done:
11450   if (k) {
11451     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11452     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11453   }
11454   g_free (k);
11455
11456   return;
11457
11458   /* ERRORS */
11459 short_read:
11460   {
11461     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11462     goto done;
11463   }
11464 }
11465
11466 static void
11467 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11468     const char *tag1, const char *tag2, GNode * node)
11469 {
11470   GNode *data;
11471   int len;
11472   int type;
11473   int n1, n2;
11474
11475   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11476   if (data) {
11477     len = QT_UINT32 (data->data);
11478     type = QT_UINT32 ((guint8 *) data->data + 8);
11479     if (type == 0x00000000 && len >= 22) {
11480       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11481       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11482       if (n1 > 0) {
11483         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11484         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11485       }
11486       if (n2 > 0) {
11487         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11488         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11489       }
11490     }
11491   }
11492 }
11493
11494 static void
11495 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11496     const char *tag1, const char *dummy, GNode * node)
11497 {
11498   GNode *data;
11499   int len;
11500   int type;
11501   int n1;
11502
11503   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11504   if (data) {
11505     len = QT_UINT32 (data->data);
11506     type = QT_UINT32 ((guint8 *) data->data + 8);
11507     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11508     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11509     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11510       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11511       if (n1) {
11512         /* do not add bpm=0 */
11513         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11514         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11515             NULL);
11516       }
11517     }
11518   }
11519 }
11520
11521 static void
11522 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11523     const char *tag1, const char *dummy, GNode * node)
11524 {
11525   GNode *data;
11526   int len;
11527   int type;
11528   guint32 num;
11529
11530   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11531   if (data) {
11532     len = QT_UINT32 (data->data);
11533     type = QT_UINT32 ((guint8 *) data->data + 8);
11534     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11535     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11536     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11537       num = QT_UINT32 ((guint8 *) data->data + 16);
11538       if (num) {
11539         /* do not add num=0 */
11540         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11541         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11542       }
11543     }
11544   }
11545 }
11546
11547 static void
11548 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11549     const char *tag1, const char *dummy, GNode * node)
11550 {
11551   GNode *data;
11552   int len;
11553   int type;
11554   GstSample *sample;
11555
11556   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11557   if (data) {
11558     len = QT_UINT32 (data->data);
11559     type = QT_UINT32 ((guint8 *) data->data + 8);
11560     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11561     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11562       if ((sample =
11563               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11564                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11565         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11566         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11567         gst_sample_unref (sample);
11568       }
11569     }
11570   }
11571 }
11572
11573 static void
11574 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11575     const char *tag, const char *dummy, GNode * node)
11576 {
11577   GNode *data;
11578   char *s;
11579   int len;
11580   int type;
11581
11582   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11583   if (data) {
11584     len = QT_UINT32 (data->data);
11585     type = QT_UINT32 ((guint8 *) data->data + 8);
11586     if (type == 0x00000001 && len > 16) {
11587       guint y, m = 1, d = 1;
11588       gint ret;
11589
11590       s = g_strndup ((char *) data->data + 16, len - 16);
11591       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11592       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11593       if (ret >= 1 && y > 1500 && y < 3000) {
11594         GDate *date;
11595
11596         date = g_date_new_dmy (d, m, y);
11597         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11598         g_date_free (date);
11599       } else {
11600         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11601       }
11602       g_free (s);
11603     }
11604   }
11605 }
11606
11607 static void
11608 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11609     const char *tag, const char *dummy, GNode * node)
11610 {
11611   GNode *data;
11612
11613   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11614
11615   /* re-route to normal string tag if major brand says so
11616    * or no data atom and compatible brand suggests so */
11617   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11618       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11619     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11620     return;
11621   }
11622
11623   if (data) {
11624     guint len, type, n;
11625
11626     len = QT_UINT32 (data->data);
11627     type = QT_UINT32 ((guint8 *) data->data + 8);
11628     if (type == 0x00000000 && len >= 18) {
11629       n = QT_UINT16 ((guint8 *) data->data + 16);
11630       if (n > 0) {
11631         const gchar *genre;
11632
11633         genre = gst_tag_id3_genre_get (n - 1);
11634         if (genre != NULL) {
11635           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11636           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11637         }
11638       }
11639     }
11640   }
11641 }
11642
11643 static void
11644 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11645     const gchar * tag, guint8 * data, guint32 datasize)
11646 {
11647   gdouble value;
11648   gchar *datacopy;
11649
11650   /* make a copy to have \0 at the end */
11651   datacopy = g_strndup ((gchar *) data, datasize);
11652
11653   /* convert the str to double */
11654   if (sscanf (datacopy, "%lf", &value) == 1) {
11655     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11656     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11657   } else {
11658     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11659         datacopy);
11660   }
11661   g_free (datacopy);
11662 }
11663
11664
11665 static void
11666 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11667     const char *tag, const char *tag_bis, GNode * node)
11668 {
11669   GNode *mean;
11670   GNode *name;
11671   GNode *data;
11672   guint32 meansize;
11673   guint32 namesize;
11674   guint32 datatype;
11675   guint32 datasize;
11676   const gchar *meanstr;
11677   const gchar *namestr;
11678
11679   /* checking the whole ---- atom size for consistency */
11680   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11681     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11682     return;
11683   }
11684
11685   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11686   if (!mean) {
11687     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11688     return;
11689   }
11690
11691   meansize = QT_UINT32 (mean->data);
11692   if (meansize <= 12) {
11693     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11694     return;
11695   }
11696   meanstr = ((gchar *) mean->data) + 12;
11697   meansize -= 12;
11698
11699   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11700   if (!name) {
11701     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11702     return;
11703   }
11704
11705   namesize = QT_UINT32 (name->data);
11706   if (namesize <= 12) {
11707     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11708     return;
11709   }
11710   namestr = ((gchar *) name->data) + 12;
11711   namesize -= 12;
11712
11713   /*
11714    * Data atom is:
11715    * uint32 - size
11716    * uint32 - name
11717    * uint8  - version
11718    * uint24 - data type
11719    * uint32 - all 0
11720    * rest   - the data
11721    */
11722   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11723   if (!data) {
11724     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11725     return;
11726   }
11727   datasize = QT_UINT32 (data->data);
11728   if (datasize <= 16) {
11729     GST_WARNING_OBJECT (demux, "Data atom too small");
11730     return;
11731   }
11732   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11733
11734   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11735       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11736     static const struct
11737     {
11738       const gchar name[28];
11739       const gchar tag[28];
11740     } tags[] = {
11741       {
11742       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11743       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11744       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11745       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11746       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11747       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11748       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11749       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11750     };
11751     int i;
11752
11753     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11754       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11755         switch (gst_tag_get_type (tags[i].tag)) {
11756           case G_TYPE_DOUBLE:
11757             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11758                 ((guint8 *) data->data) + 16, datasize - 16);
11759             break;
11760           case G_TYPE_STRING:
11761             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11762             break;
11763           default:
11764             /* not reached */
11765             break;
11766         }
11767         break;
11768       }
11769     }
11770     if (i == G_N_ELEMENTS (tags))
11771       goto unknown_tag;
11772   } else {
11773     goto unknown_tag;
11774   }
11775
11776   return;
11777
11778 /* errors */
11779 unknown_tag:
11780 #ifndef GST_DISABLE_GST_DEBUG
11781   {
11782     gchar *namestr_dbg;
11783     gchar *meanstr_dbg;
11784
11785     meanstr_dbg = g_strndup (meanstr, meansize);
11786     namestr_dbg = g_strndup (namestr, namesize);
11787
11788     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11789         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11790
11791     g_free (namestr_dbg);
11792     g_free (meanstr_dbg);
11793   }
11794 #endif
11795   return;
11796 }
11797
11798 static void
11799 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11800     const char *tag_bis, GNode * node)
11801 {
11802   guint8 *data;
11803   GstBuffer *buf;
11804   guint len;
11805   GstTagList *id32_taglist = NULL;
11806
11807   GST_LOG_OBJECT (demux, "parsing ID32");
11808
11809   data = node->data;
11810   len = GST_READ_UINT32_BE (data);
11811
11812   /* need at least full box and language tag */
11813   if (len < 12 + 2)
11814     return;
11815
11816   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11817   gst_buffer_fill (buf, 0, data + 14, len - 14);
11818
11819   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11820   if (id32_taglist) {
11821     GST_LOG_OBJECT (demux, "parsing ok");
11822     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11823     gst_tag_list_unref (id32_taglist);
11824   } else {
11825     GST_LOG_OBJECT (demux, "parsing failed");
11826   }
11827
11828   gst_buffer_unref (buf);
11829 }
11830
11831 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11832     const char *tag, const char *tag_bis, GNode * node);
11833
11834 /* unmapped tags
11835 FOURCC_pcst -> if media is a podcast -> bool
11836 FOURCC_cpil -> if media is part of a compilation -> bool
11837 FOURCC_pgap -> if media is part of a gapless context -> bool
11838 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11839 */
11840
11841 static const struct
11842 {
11843   guint32 fourcc;
11844   const gchar *gst_tag;
11845   const gchar *gst_tag_bis;
11846   const GstQTDemuxAddTagFunc func;
11847 } add_funcs[] = {
11848   {
11849   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11850   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11851   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11852   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11853   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11854   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11855   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11856   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11857   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11858   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11859   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11860   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11861   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11862   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11863   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11864   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11865   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11866   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11867   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11868   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11869   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11870   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11871   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11872         qtdemux_tag_add_num}, {
11873   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11874         qtdemux_tag_add_num}, {
11875   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11876   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11877   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11878   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11879   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11880   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11881   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11882   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11883   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11884   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11885   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11886   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11887   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11888   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11889   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11890   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11891   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11892   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11893         qtdemux_tag_add_classification}, {
11894   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11895   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11896   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11897
11898     /* This is a special case, some tags are stored in this
11899      * 'reverse dns naming', according to:
11900      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11901      * bug #614471
11902      */
11903   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11904     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11905   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11906 };
11907
11908 struct _GstQtDemuxTagList
11909 {
11910   GstQTDemux *demux;
11911   GstTagList *taglist;
11912 };
11913 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11914
11915 static void
11916 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11917 {
11918   gint len;
11919   guint8 *data;
11920   GstBuffer *buf;
11921   gchar *media_type;
11922   const gchar *style;
11923   GstSample *sample;
11924   GstStructure *s;
11925   guint i;
11926   guint8 ndata[4];
11927   GstQTDemux *demux = qtdemuxtaglist->demux;
11928   GstTagList *taglist = qtdemuxtaglist->taglist;
11929
11930   data = node->data;
11931   len = QT_UINT32 (data);
11932   buf = gst_buffer_new_and_alloc (len);
11933   gst_buffer_fill (buf, 0, data, len);
11934
11935   /* heuristic to determine style of tag */
11936   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11937       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11938     style = "itunes";
11939   else if (demux->major_brand == FOURCC_qt__)
11940     style = "quicktime";
11941   /* fall back to assuming iso/3gp tag style */
11942   else
11943     style = "iso";
11944
11945   /* santize the name for the caps. */
11946   for (i = 0; i < 4; i++) {
11947     guint8 d = data[4 + i];
11948     if (g_ascii_isalnum (d))
11949       ndata[i] = g_ascii_tolower (d);
11950     else
11951       ndata[i] = '_';
11952   }
11953
11954   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11955       ndata[0], ndata[1], ndata[2], ndata[3]);
11956   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11957
11958   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11959   sample = gst_sample_new (buf, NULL, NULL, s);
11960   gst_buffer_unref (buf);
11961   g_free (media_type);
11962
11963   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11964       len, s);
11965
11966   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11967       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11968
11969   gst_sample_unref (sample);
11970 }
11971
11972 static void
11973 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11974 {
11975   GNode *meta;
11976   GNode *ilst;
11977   GNode *xmp_;
11978   GNode *node;
11979   gint i;
11980   GstQtDemuxTagList demuxtaglist;
11981
11982   demuxtaglist.demux = qtdemux;
11983   demuxtaglist.taglist = taglist;
11984
11985   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11986   if (meta != NULL) {
11987     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11988     if (ilst == NULL) {
11989       GST_LOG_OBJECT (qtdemux, "no ilst");
11990       return;
11991     }
11992   } else {
11993     ilst = udta;
11994     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11995   }
11996
11997   i = 0;
11998   while (i < G_N_ELEMENTS (add_funcs)) {
11999     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12000     if (node) {
12001       gint len;
12002
12003       len = QT_UINT32 (node->data);
12004       if (len < 12) {
12005         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12006             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12007       } else {
12008         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12009             add_funcs[i].gst_tag_bis, node);
12010       }
12011       g_node_destroy (node);
12012     } else {
12013       i++;
12014     }
12015   }
12016
12017   /* parsed nodes have been removed, pass along remainder as blob */
12018   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12019       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12020
12021   /* parse up XMP_ node if existing */
12022   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12023   if (xmp_ != NULL) {
12024     GstBuffer *buf;
12025     GstTagList *xmptaglist;
12026
12027     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12028         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12029     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12030     gst_buffer_unref (buf);
12031
12032     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12033   } else {
12034     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12035   }
12036 }
12037
12038 typedef struct
12039 {
12040   GstStructure *structure;      /* helper for sort function */
12041   gchar *location;
12042   guint min_req_bitrate;
12043   guint min_req_qt_version;
12044 } GstQtReference;
12045
12046 static gint
12047 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12048 {
12049   GstQtReference *ref_a = (GstQtReference *) a;
12050   GstQtReference *ref_b = (GstQtReference *) b;
12051
12052   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12053     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12054
12055   /* known bitrates go before unknown; higher bitrates go first */
12056   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12057 }
12058
12059 /* sort the redirects and post a message for the application.
12060  */
12061 static void
12062 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12063 {
12064   GstQtReference *best;
12065   GstStructure *s;
12066   GstMessage *msg;
12067   GValue list_val = { 0, };
12068   GList *l;
12069
12070   g_assert (references != NULL);
12071
12072   references = g_list_sort (references, qtdemux_redirects_sort_func);
12073
12074   best = (GstQtReference *) references->data;
12075
12076   g_value_init (&list_val, GST_TYPE_LIST);
12077
12078   for (l = references; l != NULL; l = l->next) {
12079     GstQtReference *ref = (GstQtReference *) l->data;
12080     GValue struct_val = { 0, };
12081
12082     ref->structure = gst_structure_new ("redirect",
12083         "new-location", G_TYPE_STRING, ref->location, NULL);
12084
12085     if (ref->min_req_bitrate > 0) {
12086       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12087           ref->min_req_bitrate, NULL);
12088     }
12089
12090     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12091     g_value_set_boxed (&struct_val, ref->structure);
12092     gst_value_list_append_value (&list_val, &struct_val);
12093     g_value_unset (&struct_val);
12094     /* don't free anything here yet, since we need best->structure below */
12095   }
12096
12097   g_assert (best != NULL);
12098   s = gst_structure_copy (best->structure);
12099
12100   if (g_list_length (references) > 1) {
12101     gst_structure_set_value (s, "locations", &list_val);
12102   }
12103
12104   g_value_unset (&list_val);
12105
12106   for (l = references; l != NULL; l = l->next) {
12107     GstQtReference *ref = (GstQtReference *) l->data;
12108
12109     gst_structure_free (ref->structure);
12110     g_free (ref->location);
12111     g_free (ref);
12112   }
12113   g_list_free (references);
12114
12115   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12116   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12117   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12118   qtdemux->posted_redirect = TRUE;
12119 }
12120
12121 /* look for redirect nodes, collect all redirect information and
12122  * process it.
12123  */
12124 static gboolean
12125 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12126 {
12127   GNode *rmra, *rmda, *rdrf;
12128
12129   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12130   if (rmra) {
12131     GList *redirects = NULL;
12132
12133     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12134     while (rmda) {
12135       GstQtReference ref = { NULL, NULL, 0, 0 };
12136       GNode *rmdr, *rmvc;
12137
12138       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12139         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12140         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12141             ref.min_req_bitrate);
12142       }
12143
12144       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12145         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12146         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12147
12148 #ifndef GST_DISABLE_GST_DEBUG
12149         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12150 #endif
12151         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12152
12153         GST_LOG_OBJECT (qtdemux,
12154             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12155             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12156             bitmask, check_type);
12157         if (package == FOURCC_qtim && check_type == 0) {
12158           ref.min_req_qt_version = version;
12159         }
12160       }
12161
12162       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12163       if (rdrf) {
12164         guint32 ref_type;
12165         guint8 *ref_data;
12166         guint ref_len;
12167
12168         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12169         if (ref_len > 20) {
12170           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12171           ref_data = (guint8 *) rdrf->data + 20;
12172           if (ref_type == FOURCC_alis) {
12173             guint record_len, record_version, fn_len;
12174
12175             if (ref_len > 70) {
12176               /* MacOSX alias record, google for alias-layout.txt */
12177               record_len = QT_UINT16 (ref_data + 4);
12178               record_version = QT_UINT16 (ref_data + 4 + 2);
12179               fn_len = QT_UINT8 (ref_data + 50);
12180               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12181                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12182               }
12183             } else {
12184               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12185                   ref_len);
12186             }
12187           } else if (ref_type == FOURCC_url_) {
12188             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12189           } else {
12190             GST_DEBUG_OBJECT (qtdemux,
12191                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12192                 GST_FOURCC_ARGS (ref_type));
12193           }
12194           if (ref.location != NULL) {
12195             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12196             redirects =
12197                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12198           } else {
12199             GST_WARNING_OBJECT (qtdemux,
12200                 "Failed to extract redirect location from rdrf atom");
12201           }
12202         } else {
12203           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12204         }
12205       }
12206
12207       /* look for others */
12208       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12209     }
12210
12211     if (redirects != NULL) {
12212       qtdemux_process_redirects (qtdemux, redirects);
12213     }
12214   }
12215   return TRUE;
12216 }
12217
12218 static GstTagList *
12219 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12220 {
12221   const gchar *fmt;
12222
12223   if (tags == NULL) {
12224     tags = gst_tag_list_new_empty ();
12225     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12226   }
12227
12228   if (qtdemux->major_brand == FOURCC_mjp2)
12229     fmt = "Motion JPEG 2000";
12230   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12231     fmt = "3GP";
12232   else if (qtdemux->major_brand == FOURCC_qt__)
12233     fmt = "Quicktime";
12234   else if (qtdemux->fragmented)
12235     fmt = "ISO fMP4";
12236   else
12237     fmt = "ISO MP4/M4A";
12238
12239   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12240       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12241
12242   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12243       fmt, NULL);
12244
12245   return tags;
12246 }
12247
12248 /* we have read the complete moov node now.
12249  * This function parses all of the relevant info, creates the traks and
12250  * prepares all data structures for playback
12251  */
12252 static gboolean
12253 qtdemux_parse_tree (GstQTDemux * qtdemux)
12254 {
12255   GNode *mvhd;
12256   GNode *trak;
12257   GNode *udta;
12258   GNode *mvex;
12259   GstClockTime duration;
12260   GNode *pssh;
12261   guint64 creation_time;
12262   GstDateTime *datetime = NULL;
12263   gint version;
12264
12265   /* make sure we have a usable taglist */
12266   if (!qtdemux->tag_list) {
12267     qtdemux->tag_list = gst_tag_list_new_empty ();
12268     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12269   } else {
12270     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12271   }
12272
12273   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12274   if (mvhd == NULL) {
12275     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12276     return qtdemux_parse_redirects (qtdemux);
12277   }
12278
12279   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12280   if (version == 1) {
12281     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12282     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12283     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12284   } else if (version == 0) {
12285     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12286     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12287     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12288   } else {
12289     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12290     return FALSE;
12291   }
12292
12293   /* Moving qt creation time (secs since 1904) to unix time */
12294   if (creation_time != 0) {
12295     /* Try to use epoch first as it should be faster and more commonly found */
12296     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12297       GTimeVal now;
12298
12299       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12300       /* some data cleansing sanity */
12301       g_get_current_time (&now);
12302       if (now.tv_sec + 24 * 3600 < creation_time) {
12303         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12304       } else {
12305         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12306       }
12307     } else {
12308       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12309       GDateTime *dt, *dt_local;
12310
12311       dt = g_date_time_add_seconds (base_dt, creation_time);
12312       dt_local = g_date_time_to_local (dt);
12313       datetime = gst_date_time_new_from_g_date_time (dt_local);
12314
12315       g_date_time_unref (base_dt);
12316       g_date_time_unref (dt);
12317     }
12318   }
12319   if (datetime) {
12320     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12321     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12322         datetime, NULL);
12323     gst_date_time_unref (datetime);
12324   }
12325
12326   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12327   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12328
12329   /* check for fragmented file and get some (default) data */
12330   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12331   if (mvex) {
12332     GNode *mehd;
12333     GstByteReader mehd_data;
12334
12335     /* let track parsing or anyone know weird stuff might happen ... */
12336     qtdemux->fragmented = TRUE;
12337
12338     /* compensate for total duration */
12339     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12340     if (mehd)
12341       qtdemux_parse_mehd (qtdemux, &mehd_data);
12342   }
12343
12344   /* set duration in the segment info */
12345   gst_qtdemux_get_duration (qtdemux, &duration);
12346   if (duration) {
12347     qtdemux->segment.duration = duration;
12348     /* also do not exceed duration; stop is set that way post seek anyway,
12349      * and segment activation falls back to duration,
12350      * whereas loop only checks stop, so let's align this here as well */
12351     qtdemux->segment.stop = duration;
12352   }
12353
12354   /* parse all traks */
12355   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12356   while (trak) {
12357     qtdemux_parse_trak (qtdemux, trak);
12358     /* iterate all siblings */
12359     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12360   }
12361
12362   if (!qtdemux->tag_list) {
12363     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12364     qtdemux->tag_list = gst_tag_list_new_empty ();
12365     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12366   } else {
12367     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12368   }
12369
12370   /* find tags */
12371   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12372   if (udta) {
12373     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12374   } else {
12375     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12376   }
12377
12378   /* maybe also some tags in meta box */
12379   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12380   if (udta) {
12381     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12382     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12383   } else {
12384     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12385   }
12386
12387   /* parse any protection system info */
12388   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12389   while (pssh) {
12390     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12391     qtdemux_parse_pssh (qtdemux, pssh);
12392     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12393   }
12394
12395   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12396
12397   return TRUE;
12398 }
12399
12400 /* taken from ffmpeg */
12401 static int
12402 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12403 {
12404   int count = 4;
12405   int len = 0;
12406
12407   while (count--) {
12408     int c;
12409
12410     if (ptr >= end)
12411       return -1;
12412
12413     c = *ptr++;
12414     len = (len << 7) | (c & 0x7f);
12415     if (!(c & 0x80))
12416       break;
12417   }
12418   *end_out = ptr;
12419   return len;
12420 }
12421
12422 /* this can change the codec originally present in @list */
12423 static void
12424 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12425     GNode * esds, GstTagList * list)
12426 {
12427   int len = QT_UINT32 (esds->data);
12428   guint8 *ptr = esds->data;
12429   guint8 *end = ptr + len;
12430   int tag;
12431   guint8 *data_ptr = NULL;
12432   int data_len = 0;
12433   guint8 object_type_id = 0;
12434   const char *codec_name = NULL;
12435   GstCaps *caps = NULL;
12436
12437   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12438   ptr += 8;
12439   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12440   ptr += 4;
12441   while (ptr + 1 < end) {
12442     tag = QT_UINT8 (ptr);
12443     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12444     ptr++;
12445     len = read_descr_size (ptr, end, &ptr);
12446     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12447
12448     /* Check the stated amount of data is available for reading */
12449     if (len < 0 || ptr + len > end)
12450       break;
12451
12452     switch (tag) {
12453       case ES_DESCRIPTOR_TAG:
12454         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12455         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12456         ptr += 3;
12457         break;
12458       case DECODER_CONFIG_DESC_TAG:{
12459         guint max_bitrate, avg_bitrate;
12460
12461         object_type_id = QT_UINT8 (ptr);
12462         max_bitrate = QT_UINT32 (ptr + 5);
12463         avg_bitrate = QT_UINT32 (ptr + 9);
12464         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12465         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12466         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12467         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12468         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12469         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12470           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12471               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12472         }
12473         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12474           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12475               avg_bitrate, NULL);
12476         }
12477         ptr += 13;
12478         break;
12479       }
12480       case DECODER_SPECIFIC_INFO_TAG:
12481         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12482         if (object_type_id == 0xe0 && len == 0x40) {
12483           guint8 *data;
12484           GstStructure *s;
12485           guint32 clut[16];
12486           gint i;
12487
12488           GST_DEBUG_OBJECT (qtdemux,
12489               "Have VOBSUB palette. Creating palette event");
12490           /* move to decConfigDescr data and read palette */
12491           data = ptr;
12492           for (i = 0; i < 16; i++) {
12493             clut[i] = QT_UINT32 (data);
12494             data += 4;
12495           }
12496
12497           s = gst_structure_new ("application/x-gst-dvd", "event",
12498               G_TYPE_STRING, "dvd-spu-clut-change",
12499               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12500               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12501               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12502               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12503               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12504               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12505               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12506               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12507               NULL);
12508
12509           /* store event and trigger custom processing */
12510           stream->pending_event =
12511               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12512         } else {
12513           /* Generic codec_data handler puts it on the caps */
12514           data_ptr = ptr;
12515           data_len = len;
12516         }
12517
12518         ptr += len;
12519         break;
12520       case SL_CONFIG_DESC_TAG:
12521         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12522         ptr += 1;
12523         break;
12524       default:
12525         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12526             tag);
12527         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12528         ptr += len;
12529         break;
12530     }
12531   }
12532
12533   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12534    * in use, and should also be used to override some other parameters for some
12535    * codecs. */
12536   switch (object_type_id) {
12537     case 0x20:                 /* MPEG-4 */
12538       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12539        * profile_and_level_indication */
12540       if (data_ptr != NULL && data_len >= 5 &&
12541           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12542         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12543             data_ptr + 4, data_len - 4);
12544       }
12545       break;                    /* Nothing special needed here */
12546     case 0x21:                 /* H.264 */
12547       codec_name = "H.264 / AVC";
12548       caps = gst_caps_new_simple ("video/x-h264",
12549           "stream-format", G_TYPE_STRING, "avc",
12550           "alignment", G_TYPE_STRING, "au", NULL);
12551       break;
12552     case 0x40:                 /* AAC (any) */
12553     case 0x66:                 /* AAC Main */
12554     case 0x67:                 /* AAC LC */
12555     case 0x68:                 /* AAC SSR */
12556       /* Override channels and rate based on the codec_data, as it's often
12557        * wrong. */
12558       /* Only do so for basic setup without HE-AAC extension */
12559       if (data_ptr && data_len == 2) {
12560         guint channels, rate;
12561
12562         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
12563         if (channels > 0)
12564           stream->n_channels = channels;
12565
12566         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
12567         if (rate > 0)
12568           stream->rate = rate;
12569       }
12570
12571       /* Set level and profile if possible */
12572       if (data_ptr != NULL && data_len >= 2) {
12573         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12574             data_ptr, data_len);
12575       }
12576       break;
12577     case 0x60:                 /* MPEG-2, various profiles */
12578     case 0x61:
12579     case 0x62:
12580     case 0x63:
12581     case 0x64:
12582     case 0x65:
12583       codec_name = "MPEG-2 video";
12584       caps = gst_caps_new_simple ("video/mpeg",
12585           "mpegversion", G_TYPE_INT, 2,
12586           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12587       break;
12588     case 0x69:                 /* MPEG-2 BC audio */
12589     case 0x6B:                 /* MPEG-1 audio */
12590       caps = gst_caps_new_simple ("audio/mpeg",
12591           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12592       codec_name = "MPEG-1 audio";
12593       break;
12594     case 0x6A:                 /* MPEG-1 */
12595       codec_name = "MPEG-1 video";
12596       caps = gst_caps_new_simple ("video/mpeg",
12597           "mpegversion", G_TYPE_INT, 1,
12598           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12599       break;
12600     case 0x6C:                 /* MJPEG */
12601       caps =
12602           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12603           NULL);
12604       codec_name = "Motion-JPEG";
12605       break;
12606     case 0x6D:                 /* PNG */
12607       caps =
12608           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12609           NULL);
12610       codec_name = "PNG still images";
12611       break;
12612     case 0x6E:                 /* JPEG2000 */
12613       codec_name = "JPEG-2000";
12614       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12615       break;
12616     case 0xA4:                 /* Dirac */
12617       codec_name = "Dirac";
12618       caps = gst_caps_new_empty_simple ("video/x-dirac");
12619       break;
12620     case 0xA5:                 /* AC3 */
12621       codec_name = "AC-3 audio";
12622       caps = gst_caps_new_simple ("audio/x-ac3",
12623           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12624       break;
12625     case 0xA9:                 /* AC3 */
12626       codec_name = "DTS audio";
12627       caps = gst_caps_new_simple ("audio/x-dts",
12628           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12629       break;
12630     case 0xE1:                 /* QCELP */
12631       /* QCELP, the codec_data is a riff tag (little endian) with
12632        * 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). */
12633       caps = gst_caps_new_empty_simple ("audio/qcelp");
12634       codec_name = "QCELP";
12635       break;
12636     default:
12637       break;
12638   }
12639
12640   /* If we have a replacement caps, then change our caps for this stream */
12641   if (caps) {
12642     gst_caps_unref (stream->caps);
12643     stream->caps = caps;
12644   }
12645
12646   if (codec_name && list)
12647     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12648         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12649
12650   /* Add the codec_data attribute to caps, if we have it */
12651   if (data_ptr) {
12652     GstBuffer *buffer;
12653
12654     buffer = gst_buffer_new_and_alloc (data_len);
12655     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12656
12657     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12658     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12659
12660     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12661         buffer, NULL);
12662     gst_buffer_unref (buffer);
12663   }
12664
12665 }
12666
12667 #define _codec(name) \
12668   do { \
12669     if (codec_name) { \
12670       *codec_name = g_strdup (name); \
12671     } \
12672   } while (0)
12673
12674 static GstCaps *
12675 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12676     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12677 {
12678   GstCaps *caps = NULL;
12679   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12680
12681   switch (fourcc) {
12682     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12683       _codec ("PNG still images");
12684       caps = gst_caps_new_empty_simple ("image/png");
12685       break;
12686     case FOURCC_jpeg:
12687       _codec ("JPEG still images");
12688       caps =
12689           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12690           NULL);
12691       break;
12692     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12693     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12694     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12695     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12696       _codec ("Motion-JPEG");
12697       caps =
12698           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12699           NULL);
12700       break;
12701     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12702       _codec ("Motion-JPEG format B");
12703       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12704       break;
12705     case FOURCC_mjp2:
12706       _codec ("JPEG-2000");
12707       /* override to what it should be according to spec, avoid palette_data */
12708       stream->bits_per_sample = 24;
12709       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12710       break;
12711     case FOURCC_SVQ3:
12712       _codec ("Sorensen video v.3");
12713       caps = gst_caps_new_simple ("video/x-svq",
12714           "svqversion", G_TYPE_INT, 3, NULL);
12715       break;
12716     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12717     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12718       _codec ("Sorensen video v.1");
12719       caps = gst_caps_new_simple ("video/x-svq",
12720           "svqversion", G_TYPE_INT, 1, NULL);
12721       break;
12722     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12723       caps = gst_caps_new_empty_simple ("video/x-raw");
12724       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12725       _codec ("Windows Raw RGB");
12726       break;
12727     case FOURCC_raw_:
12728     {
12729       guint16 bps;
12730
12731       bps = QT_UINT16 (stsd_data + 98);
12732       switch (bps) {
12733         case 15:
12734           format = GST_VIDEO_FORMAT_RGB15;
12735           break;
12736         case 16:
12737           format = GST_VIDEO_FORMAT_RGB16;
12738           break;
12739         case 24:
12740           format = GST_VIDEO_FORMAT_RGB;
12741           break;
12742         case 32:
12743           format = GST_VIDEO_FORMAT_ARGB;
12744           break;
12745         default:
12746           /* unknown */
12747           break;
12748       }
12749       break;
12750     }
12751     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12752       format = GST_VIDEO_FORMAT_I420;
12753       break;
12754     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12755     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12756       format = GST_VIDEO_FORMAT_I420;
12757       break;
12758     case FOURCC_2vuy:
12759     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12760       format = GST_VIDEO_FORMAT_UYVY;
12761       break;
12762     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12763       format = GST_VIDEO_FORMAT_v308;
12764       break;
12765     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12766       format = GST_VIDEO_FORMAT_v216;
12767       break;
12768     case FOURCC_v210:
12769       format = GST_VIDEO_FORMAT_v210;
12770       break;
12771     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12772       format = GST_VIDEO_FORMAT_r210;
12773       break;
12774       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12775          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12776          format = GST_VIDEO_FORMAT_v410;
12777          break;
12778        */
12779       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12780        * but different order than AYUV
12781        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12782        format = GST_VIDEO_FORMAT_v408;
12783        break;
12784        */
12785     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12786     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12787       _codec ("MPEG-1 video");
12788       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12789           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12790       break;
12791     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12792     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12793     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12794     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12795     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12796     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12797     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12798     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12799     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12800     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12801     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12802     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12803     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12804     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12805     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12806     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12807     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12808     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12809     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12810     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12811     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12812     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12813     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12814     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12815     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12816     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12817     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12818     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12819     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12820     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12821     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12822     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12823     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12824     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12825     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12826     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12827     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12828     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12829     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12830     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12831     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12832     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12833     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12834     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12835     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12836     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12837       _codec ("MPEG-2 video");
12838       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12839           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12840       break;
12841     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12842       _codec ("GIF still images");
12843       caps = gst_caps_new_empty_simple ("image/gif");
12844       break;
12845     case FOURCC_h263:
12846     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12847     case FOURCC_s263:
12848     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12849       _codec ("H.263");
12850       /* ffmpeg uses the height/width props, don't know why */
12851       caps = gst_caps_new_simple ("video/x-h263",
12852           "variant", G_TYPE_STRING, "itu", NULL);
12853       break;
12854     case FOURCC_mp4v:
12855     case FOURCC_MP4V:
12856       _codec ("MPEG-4 video");
12857       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12858           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12859       break;
12860     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12861     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12862       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12863       caps = gst_caps_new_simple ("video/x-msmpeg",
12864           "msmpegversion", G_TYPE_INT, 43, NULL);
12865       break;
12866     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12867       _codec ("DivX 3");
12868       caps = gst_caps_new_simple ("video/x-divx",
12869           "divxversion", G_TYPE_INT, 3, NULL);
12870       break;
12871     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12872     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12873       _codec ("DivX 4");
12874       caps = gst_caps_new_simple ("video/x-divx",
12875           "divxversion", G_TYPE_INT, 4, NULL);
12876       break;
12877     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12878       _codec ("DivX 5");
12879       caps = gst_caps_new_simple ("video/x-divx",
12880           "divxversion", G_TYPE_INT, 5, NULL);
12881       break;
12882
12883     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
12884       _codec ("FFV1");
12885       caps = gst_caps_new_simple ("video/x-ffv",
12886           "ffvversion", G_TYPE_INT, 1, NULL);
12887       break;
12888
12889     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12890     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12891     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12892     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12893     case FOURCC_FMP4:
12894     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12895       caps = gst_caps_new_simple ("video/mpeg",
12896           "mpegversion", G_TYPE_INT, 4, NULL);
12897       _codec ("MPEG-4");
12898       break;
12899
12900     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12901       _codec ("Cinepak");
12902       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12903       break;
12904     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12905       _codec ("Apple QuickDraw");
12906       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12907       break;
12908     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12909       _codec ("Apple video");
12910       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12911       break;
12912     case FOURCC_H264:
12913     case FOURCC_avc1:
12914       _codec ("H.264 / AVC");
12915       caps = gst_caps_new_simple ("video/x-h264",
12916           "stream-format", G_TYPE_STRING, "avc",
12917           "alignment", G_TYPE_STRING, "au", NULL);
12918       break;
12919     case FOURCC_avc3:
12920       _codec ("H.264 / AVC");
12921       caps = gst_caps_new_simple ("video/x-h264",
12922           "stream-format", G_TYPE_STRING, "avc3",
12923           "alignment", G_TYPE_STRING, "au", NULL);
12924       break;
12925     case FOURCC_H265:
12926     case FOURCC_hvc1:
12927       _codec ("H.265 / HEVC");
12928       caps = gst_caps_new_simple ("video/x-h265",
12929           "stream-format", G_TYPE_STRING, "hvc1",
12930           "alignment", G_TYPE_STRING, "au", NULL);
12931       break;
12932     case FOURCC_hev1:
12933       _codec ("H.265 / HEVC");
12934       caps = gst_caps_new_simple ("video/x-h265",
12935           "stream-format", G_TYPE_STRING, "hev1",
12936           "alignment", G_TYPE_STRING, "au", NULL);
12937       break;
12938     case FOURCC_rle_:
12939       _codec ("Run-length encoding");
12940       caps = gst_caps_new_simple ("video/x-rle",
12941           "layout", G_TYPE_STRING, "quicktime", NULL);
12942       break;
12943     case FOURCC_WRLE:
12944       _codec ("Run-length encoding");
12945       caps = gst_caps_new_simple ("video/x-rle",
12946           "layout", G_TYPE_STRING, "microsoft", NULL);
12947       break;
12948     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12949     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12950       _codec ("Indeo Video 3");
12951       caps = gst_caps_new_simple ("video/x-indeo",
12952           "indeoversion", G_TYPE_INT, 3, NULL);
12953       break;
12954     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12955     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12956       _codec ("Intel Video 4");
12957       caps = gst_caps_new_simple ("video/x-indeo",
12958           "indeoversion", G_TYPE_INT, 4, NULL);
12959       break;
12960     case FOURCC_dvcp:
12961     case FOURCC_dvc_:
12962     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12963     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12964     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12965     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12966     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12967     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12968       _codec ("DV Video");
12969       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12970           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12971       break;
12972     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
12973     case FOURCC_dv5p:          /* DVCPRO50 PAL */
12974       _codec ("DVCPro50 Video");
12975       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12976           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12977       break;
12978     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12979     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12980       _codec ("DVCProHD Video");
12981       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12982           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12983       break;
12984     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12985       _codec ("Apple Graphics (SMC)");
12986       caps = gst_caps_new_empty_simple ("video/x-smc");
12987       break;
12988     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12989       _codec ("VP3");
12990       caps = gst_caps_new_empty_simple ("video/x-vp3");
12991       break;
12992     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12993       _codec ("VP6 Flash");
12994       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12995       break;
12996     case FOURCC_XiTh:
12997       _codec ("Theora");
12998       caps = gst_caps_new_empty_simple ("video/x-theora");
12999       /* theora uses one byte of padding in the data stream because it does not
13000        * allow 0 sized packets while theora does */
13001       stream->padding = 1;
13002       break;
13003     case FOURCC_drac:
13004       _codec ("Dirac");
13005       caps = gst_caps_new_empty_simple ("video/x-dirac");
13006       break;
13007     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13008       _codec ("TIFF still images");
13009       caps = gst_caps_new_empty_simple ("image/tiff");
13010       break;
13011     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13012       _codec ("Apple Intermediate Codec");
13013       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13014       break;
13015     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13016       _codec ("AVID DNxHD");
13017       caps = gst_caps_from_string ("video/x-dnxhd");
13018       break;
13019     case FOURCC_VP80:
13020       _codec ("On2 VP8");
13021       caps = gst_caps_from_string ("video/x-vp8");
13022       break;
13023     case FOURCC_apcs:
13024       _codec ("Apple ProRes LT");
13025       caps =
13026           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13027           NULL);
13028       break;
13029     case FOURCC_apch:
13030       _codec ("Apple ProRes HQ");
13031       caps =
13032           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13033           NULL);
13034       break;
13035     case FOURCC_apcn:
13036       _codec ("Apple ProRes");
13037       caps =
13038           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13039           "standard", NULL);
13040       break;
13041     case FOURCC_apco:
13042       _codec ("Apple ProRes Proxy");
13043       caps =
13044           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13045           "proxy", NULL);
13046       break;
13047     case FOURCC_ap4h:
13048       _codec ("Apple ProRes 4444");
13049       caps =
13050           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13051           "4444", NULL);
13052       break;
13053     case FOURCC_vc_1:
13054     case FOURCC_ovc1:
13055       _codec ("VC-1");
13056       caps = gst_caps_new_simple ("video/x-wmv",
13057           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13058       break;
13059     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13060     default:
13061     {
13062       char *s, fourstr[5];
13063
13064       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13065       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
13066       caps = gst_caps_new_empty_simple (s);
13067       g_free (s);
13068       break;
13069     }
13070   }
13071
13072   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13073     GstVideoInfo info;
13074
13075     gst_video_info_init (&info);
13076     gst_video_info_set_format (&info, format, stream->width, stream->height);
13077
13078     caps = gst_video_info_to_caps (&info);
13079     *codec_name = gst_pb_utils_get_codec_description (caps);
13080
13081     /* enable clipping for raw video streams */
13082     stream->need_clip = TRUE;
13083   }
13084
13085   return caps;
13086 }
13087
13088 static GstCaps *
13089 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13090     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13091 {
13092   GstCaps *caps;
13093   const GstStructure *s;
13094   const gchar *name;
13095   gint endian = 0;
13096   GstAudioFormat format = 0;
13097   gint depth;
13098
13099   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13100
13101   depth = stream->bytes_per_packet * 8;
13102
13103   switch (fourcc) {
13104     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13105     case FOURCC_raw_:
13106       /* 8-bit audio is unsigned */
13107       if (depth == 8)
13108         format = GST_AUDIO_FORMAT_U8;
13109       /* otherwise it's signed and big-endian just like 'twos' */
13110     case FOURCC_twos:
13111       endian = G_BIG_ENDIAN;
13112       /* fall-through */
13113     case FOURCC_sowt:
13114     {
13115       gchar *str;
13116
13117       if (!endian)
13118         endian = G_LITTLE_ENDIAN;
13119
13120       if (!format)
13121         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13122
13123       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13124       _codec (str);
13125       g_free (str);
13126
13127       caps = gst_caps_new_simple ("audio/x-raw",
13128           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13129           "layout", G_TYPE_STRING, "interleaved", NULL);
13130       break;
13131     }
13132     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13133       _codec ("Raw 64-bit floating-point audio");
13134       caps = gst_caps_new_simple ("audio/x-raw",
13135           "format", G_TYPE_STRING, "F64BE",
13136           "layout", G_TYPE_STRING, "interleaved", NULL);
13137       break;
13138     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13139       _codec ("Raw 32-bit floating-point audio");
13140       caps = gst_caps_new_simple ("audio/x-raw",
13141           "format", G_TYPE_STRING, "F32BE",
13142           "layout", G_TYPE_STRING, "interleaved", NULL);
13143       break;
13144     case FOURCC_in24:
13145       _codec ("Raw 24-bit PCM audio");
13146       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13147        * endian later */
13148       caps = gst_caps_new_simple ("audio/x-raw",
13149           "format", G_TYPE_STRING, "S24BE",
13150           "layout", G_TYPE_STRING, "interleaved", NULL);
13151       break;
13152     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13153       _codec ("Raw 32-bit PCM audio");
13154       caps = gst_caps_new_simple ("audio/x-raw",
13155           "format", G_TYPE_STRING, "S32BE",
13156           "layout", G_TYPE_STRING, "interleaved", NULL);
13157       break;
13158     case FOURCC_ulaw:
13159       _codec ("Mu-law audio");
13160       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13161       break;
13162     case FOURCC_alaw:
13163       _codec ("A-law audio");
13164       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13165       break;
13166     case 0x0200736d:
13167     case 0x6d730002:
13168       _codec ("Microsoft ADPCM");
13169       /* Microsoft ADPCM-ACM code 2 */
13170       caps = gst_caps_new_simple ("audio/x-adpcm",
13171           "layout", G_TYPE_STRING, "microsoft", NULL);
13172       break;
13173     case 0x1100736d:
13174     case 0x6d730011:
13175       _codec ("DVI/IMA ADPCM");
13176       caps = gst_caps_new_simple ("audio/x-adpcm",
13177           "layout", G_TYPE_STRING, "dvi", NULL);
13178       break;
13179     case 0x1700736d:
13180     case 0x6d730017:
13181       _codec ("DVI/Intel IMA ADPCM");
13182       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13183       caps = gst_caps_new_simple ("audio/x-adpcm",
13184           "layout", G_TYPE_STRING, "quicktime", NULL);
13185       break;
13186     case 0x5500736d:
13187     case 0x6d730055:
13188       /* MPEG layer 3, CBR only (pre QT4.1) */
13189     case FOURCC__mp3:
13190       _codec ("MPEG-1 layer 3");
13191       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13192       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13193           "mpegversion", G_TYPE_INT, 1, NULL);
13194       break;
13195     case 0x20736d:
13196     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13197       _codec ("EAC-3 audio");
13198       caps = gst_caps_new_simple ("audio/x-eac3",
13199           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13200       stream->sampled = TRUE;
13201       break;
13202     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13203     case FOURCC_ac_3:
13204       _codec ("AC-3 audio");
13205       caps = gst_caps_new_simple ("audio/x-ac3",
13206           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13207       stream->sampled = TRUE;
13208       break;
13209     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13210     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13211       _codec ("DTS audio");
13212       caps = gst_caps_new_simple ("audio/x-dts",
13213           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13214       stream->sampled = TRUE;
13215       break;
13216     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13217     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13218       _codec ("DTS-HD audio");
13219       caps = gst_caps_new_simple ("audio/x-dts",
13220           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13221       stream->sampled = TRUE;
13222       break;
13223     case FOURCC_MAC3:
13224       _codec ("MACE-3");
13225       caps = gst_caps_new_simple ("audio/x-mace",
13226           "maceversion", G_TYPE_INT, 3, NULL);
13227       break;
13228     case FOURCC_MAC6:
13229       _codec ("MACE-6");
13230       caps = gst_caps_new_simple ("audio/x-mace",
13231           "maceversion", G_TYPE_INT, 6, NULL);
13232       break;
13233     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13234       /* ogg/vorbis */
13235       caps = gst_caps_new_empty_simple ("application/ogg");
13236       break;
13237     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13238       _codec ("DV audio");
13239       caps = gst_caps_new_empty_simple ("audio/x-dv");
13240       break;
13241     case FOURCC_mp4a:
13242       _codec ("MPEG-4 AAC audio");
13243       caps = gst_caps_new_simple ("audio/mpeg",
13244           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13245           "stream-format", G_TYPE_STRING, "raw", NULL);
13246       break;
13247     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13248       _codec ("QDesign Music");
13249       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13250       break;
13251     case FOURCC_QDM2:
13252       _codec ("QDesign Music v.2");
13253       /* FIXME: QDesign music version 2 (no constant) */
13254       if (FALSE && data) {
13255         caps = gst_caps_new_simple ("audio/x-qdm2",
13256             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13257             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13258             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13259       } else {
13260         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13261       }
13262       break;
13263     case FOURCC_agsm:
13264       _codec ("GSM audio");
13265       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13266       break;
13267     case FOURCC_samr:
13268       _codec ("AMR audio");
13269       caps = gst_caps_new_empty_simple ("audio/AMR");
13270       break;
13271     case FOURCC_sawb:
13272       _codec ("AMR-WB audio");
13273       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13274       break;
13275     case FOURCC_ima4:
13276       _codec ("Quicktime IMA ADPCM");
13277       caps = gst_caps_new_simple ("audio/x-adpcm",
13278           "layout", G_TYPE_STRING, "quicktime", NULL);
13279       break;
13280     case FOURCC_alac:
13281       _codec ("Apple lossless audio");
13282       caps = gst_caps_new_empty_simple ("audio/x-alac");
13283       break;
13284     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13285       _codec ("QualComm PureVoice");
13286       caps = gst_caps_from_string ("audio/qcelp");
13287       break;
13288     case FOURCC_wma_:
13289     case FOURCC_owma:
13290       _codec ("WMA");
13291       caps = gst_caps_new_empty_simple ("audio/x-wma");
13292       break;
13293     case FOURCC_opus:
13294       _codec ("Opus");
13295       caps = gst_caps_new_empty_simple ("audio/x-opus");
13296       break;
13297     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13298     {
13299       guint32 flags = 0;
13300       guint32 depth = 0;
13301       guint32 width = 0;
13302       GstAudioFormat format;
13303       enum
13304       {
13305         FLAG_IS_FLOAT = 0x1,
13306         FLAG_IS_BIG_ENDIAN = 0x2,
13307         FLAG_IS_SIGNED = 0x4,
13308         FLAG_IS_PACKED = 0x8,
13309         FLAG_IS_ALIGNED_HIGH = 0x10,
13310         FLAG_IS_NON_INTERLEAVED = 0x20
13311       };
13312       _codec ("Raw LPCM audio");
13313
13314       if (data && len >= 56) {
13315         depth = QT_UINT32 (data + 40);
13316         flags = QT_UINT32 (data + 44);
13317         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13318       }
13319       if ((flags & FLAG_IS_FLOAT) == 0) {
13320         if (depth == 0)
13321           depth = 16;
13322         if (width == 0)
13323           width = 16;
13324         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13325             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13326             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13327         caps = gst_caps_new_simple ("audio/x-raw",
13328             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13329             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13330             "non-interleaved" : "interleaved", NULL);
13331       } else {
13332         if (width == 0)
13333           width = 32;
13334         if (width == 64) {
13335           if (flags & FLAG_IS_BIG_ENDIAN)
13336             format = GST_AUDIO_FORMAT_F64BE;
13337           else
13338             format = GST_AUDIO_FORMAT_F64LE;
13339         } else {
13340           if (flags & FLAG_IS_BIG_ENDIAN)
13341             format = GST_AUDIO_FORMAT_F32BE;
13342           else
13343             format = GST_AUDIO_FORMAT_F32LE;
13344         }
13345         caps = gst_caps_new_simple ("audio/x-raw",
13346             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13347             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13348             "non-interleaved" : "interleaved", NULL);
13349       }
13350       break;
13351     }
13352     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
13353       /* ? */
13354     default:
13355     {
13356       char *s, fourstr[5];
13357
13358       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13359       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
13360       caps = gst_caps_new_empty_simple (s);
13361       g_free (s);
13362       break;
13363     }
13364   }
13365
13366   if (caps) {
13367     GstCaps *templ_caps =
13368         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
13369     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
13370     gst_caps_unref (caps);
13371     gst_caps_unref (templ_caps);
13372     caps = intersection;
13373   }
13374
13375   /* enable clipping for raw audio streams */
13376   s = gst_caps_get_structure (caps, 0);
13377   name = gst_structure_get_name (s);
13378   if (g_str_has_prefix (name, "audio/x-raw")) {
13379     stream->need_clip = TRUE;
13380     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
13381     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
13382   }
13383   return caps;
13384 }
13385
13386 static GstCaps *
13387 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13388     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13389 {
13390   GstCaps *caps;
13391
13392   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13393
13394   switch (fourcc) {
13395     case FOURCC_mp4s:
13396       _codec ("DVD subtitle");
13397       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
13398       stream->need_process = TRUE;
13399       break;
13400     case FOURCC_text:
13401       _codec ("Quicktime timed text");
13402       goto text;
13403     case FOURCC_tx3g:
13404       _codec ("3GPP timed text");
13405     text:
13406       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
13407           "utf8", NULL);
13408       /* actual text piece needs to be extracted */
13409       stream->need_process = TRUE;
13410       break;
13411     case FOURCC_stpp:
13412       _codec ("XML subtitles");
13413       caps = gst_caps_new_empty_simple ("application/ttml+xml");
13414       break;
13415     default:
13416     {
13417       char *s, fourstr[5];
13418
13419       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13420       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
13421       caps = gst_caps_new_empty_simple (s);
13422       g_free (s);
13423       break;
13424     }
13425   }
13426   return caps;
13427 }
13428
13429 static GstCaps *
13430 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13431     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13432 {
13433   GstCaps *caps;
13434
13435   switch (fourcc) {
13436     case FOURCC_m1v:
13437       _codec ("MPEG 1 video");
13438       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13439           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13440       break;
13441     default:
13442       caps = NULL;
13443       break;
13444   }
13445   return caps;
13446 }
13447
13448 static void
13449 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
13450     const gchar * system_id)
13451 {
13452   gint i;
13453
13454   if (!qtdemux->protection_system_ids)
13455     qtdemux->protection_system_ids =
13456         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13457   /* Check whether we already have an entry for this system ID. */
13458   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13459     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13460     if (g_ascii_strcasecmp (system_id, id) == 0) {
13461       return;
13462     }
13463   }
13464   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13465   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13466           -1));
13467 }