bd294a5222af55228f4947e4855e6a683d7c4a75
[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     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7473     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7474     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7475     gst_pad_set_active (stream->pad, TRUE);
7476
7477     gst_pad_use_fixed_caps (stream->pad);
7478
7479     if (stream->protected) {
7480       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7481         GST_ERROR_OBJECT (qtdemux,
7482             "Failed to configure protected stream caps.");
7483         return FALSE;
7484       }
7485     }
7486
7487     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7488     if (stream->new_stream) {
7489       gchar *stream_id;
7490       GstEvent *event;
7491       GstStreamFlags stream_flags;
7492
7493       event =
7494           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7495           0);
7496       if (event) {
7497         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7498           qtdemux->have_group_id = TRUE;
7499         else
7500           qtdemux->have_group_id = FALSE;
7501         gst_event_unref (event);
7502       } else if (!qtdemux->have_group_id) {
7503         qtdemux->have_group_id = TRUE;
7504         qtdemux->group_id = gst_util_group_id_next ();
7505       }
7506
7507       stream->new_stream = FALSE;
7508       stream_id =
7509           gst_pad_create_stream_id_printf (stream->pad,
7510           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7511       event = gst_event_new_stream_start (stream_id);
7512       if (qtdemux->have_group_id)
7513         gst_event_set_group_id (event, qtdemux->group_id);
7514       stream_flags = GST_STREAM_FLAG_NONE;
7515       if (stream->disabled)
7516         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7517       if (stream->sparse)
7518         stream_flags |= GST_STREAM_FLAG_SPARSE;
7519       gst_event_set_stream_flags (event, stream_flags);
7520       gst_pad_push_event (stream->pad, event);
7521       g_free (stream_id);
7522     }
7523     gst_pad_set_caps (stream->pad, stream->caps);
7524     stream->new_caps = FALSE;
7525   }
7526   return TRUE;
7527 }
7528
7529 static gboolean
7530 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7531     QtDemuxStream * stream, GstTagList * list)
7532 {
7533   gboolean ret = TRUE;
7534   /* consistent default for push based mode */
7535   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7536
7537   if (stream->subtype == FOURCC_vide) {
7538     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7539
7540     stream->pad =
7541         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7542     g_free (name);
7543
7544     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7545       gst_object_unref (stream->pad);
7546       stream->pad = NULL;
7547       ret = FALSE;
7548       goto done;
7549     }
7550
7551     qtdemux->n_video_streams++;
7552   } else if (stream->subtype == FOURCC_soun) {
7553     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7554
7555     stream->pad =
7556         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7557     g_free (name);
7558     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7559       gst_object_unref (stream->pad);
7560       stream->pad = NULL;
7561       ret = FALSE;
7562       goto done;
7563     }
7564     qtdemux->n_audio_streams++;
7565   } else if (stream->subtype == FOURCC_strm) {
7566     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7567   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7568       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7569     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7570
7571     stream->pad =
7572         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7573     g_free (name);
7574     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7575       gst_object_unref (stream->pad);
7576       stream->pad = NULL;
7577       ret = FALSE;
7578       goto done;
7579     }
7580     qtdemux->n_sub_streams++;
7581   } else if (stream->caps) {
7582     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7583
7584     stream->pad =
7585         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7586     g_free (name);
7587     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7588       gst_object_unref (stream->pad);
7589       stream->pad = NULL;
7590       ret = FALSE;
7591       goto done;
7592     }
7593     qtdemux->n_video_streams++;
7594   } else {
7595     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7596     goto done;
7597   }
7598
7599   if (stream->pad) {
7600     GList *l;
7601
7602     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7603         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7604     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7605     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7606
7607     if (stream->pending_tags)
7608       gst_tag_list_unref (stream->pending_tags);
7609     stream->pending_tags = list;
7610     list = NULL;
7611     /* global tags go on each pad anyway */
7612     stream->send_global_tags = TRUE;
7613     /* send upstream GST_EVENT_PROTECTION events that were received before
7614        this source pad was created */
7615     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7616       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7617   }
7618 done:
7619   if (list)
7620     gst_tag_list_unref (list);
7621   return ret;
7622 }
7623
7624 /* find next atom with @fourcc starting at @offset */
7625 static GstFlowReturn
7626 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7627     guint64 * length, guint32 fourcc)
7628 {
7629   GstFlowReturn ret;
7630   guint32 lfourcc;
7631   GstBuffer *buf;
7632
7633   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7634       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7635
7636   while (TRUE) {
7637     GstMapInfo map;
7638
7639     buf = NULL;
7640     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7641     if (G_UNLIKELY (ret != GST_FLOW_OK))
7642       goto locate_failed;
7643     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7644       /* likely EOF */
7645       ret = GST_FLOW_EOS;
7646       gst_buffer_unref (buf);
7647       goto locate_failed;
7648     }
7649     gst_buffer_map (buf, &map, GST_MAP_READ);
7650     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7651     gst_buffer_unmap (buf, &map);
7652     gst_buffer_unref (buf);
7653
7654     if (G_UNLIKELY (*length == 0)) {
7655       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7656       ret = GST_FLOW_ERROR;
7657       goto locate_failed;
7658     }
7659
7660     if (lfourcc == fourcc) {
7661       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7662           *offset);
7663       break;
7664     } else {
7665       GST_LOG_OBJECT (qtdemux,
7666           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7667           GST_FOURCC_ARGS (fourcc), *offset);
7668       *offset += *length;
7669     }
7670   }
7671
7672   return GST_FLOW_OK;
7673
7674 locate_failed:
7675   {
7676     /* might simply have had last one */
7677     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7678     return ret;
7679   }
7680 }
7681
7682 /* should only do something in pull mode */
7683 /* call with OBJECT lock */
7684 static GstFlowReturn
7685 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7686 {
7687   guint64 length, offset;
7688   GstBuffer *buf = NULL;
7689   GstFlowReturn ret = GST_FLOW_OK;
7690   GstFlowReturn res = GST_FLOW_OK;
7691   GstMapInfo map;
7692
7693   offset = qtdemux->moof_offset;
7694   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7695
7696   if (!offset) {
7697     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7698     return GST_FLOW_EOS;
7699   }
7700
7701   /* best not do pull etc with lock held */
7702   GST_OBJECT_UNLOCK (qtdemux);
7703
7704   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7705   if (ret != GST_FLOW_OK)
7706     goto flow_failed;
7707
7708   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7709   if (G_UNLIKELY (ret != GST_FLOW_OK))
7710     goto flow_failed;
7711   gst_buffer_map (buf, &map, GST_MAP_READ);
7712   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7713     gst_buffer_unmap (buf, &map);
7714     gst_buffer_unref (buf);
7715     buf = NULL;
7716     goto parse_failed;
7717   }
7718
7719   gst_buffer_unmap (buf, &map);
7720   gst_buffer_unref (buf);
7721   buf = NULL;
7722
7723   offset += length;
7724   /* look for next moof */
7725   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7726   if (G_UNLIKELY (ret != GST_FLOW_OK))
7727     goto flow_failed;
7728
7729 exit:
7730   GST_OBJECT_LOCK (qtdemux);
7731
7732   qtdemux->moof_offset = offset;
7733
7734   return res;
7735
7736 parse_failed:
7737   {
7738     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7739     offset = 0;
7740     res = GST_FLOW_ERROR;
7741     goto exit;
7742   }
7743 flow_failed:
7744   {
7745     /* maybe upstream temporarily flushing */
7746     if (ret != GST_FLOW_FLUSHING) {
7747       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7748       offset = 0;
7749     } else {
7750       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7751       /* resume at current position next time */
7752     }
7753     res = ret;
7754     goto exit;
7755   }
7756 }
7757
7758 /* initialise bytereaders for stbl sub-atoms */
7759 static gboolean
7760 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7761 {
7762   stream->stbl_index = -1;      /* no samples have yet been parsed */
7763   stream->sample_index = -1;
7764
7765   /* time-to-sample atom */
7766   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7767     goto corrupt_file;
7768
7769   /* copy atom data into a new buffer for later use */
7770   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7771
7772   /* skip version + flags */
7773   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7774       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7775     goto corrupt_file;
7776   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7777
7778   /* make sure there's enough data */
7779   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7780     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7781     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7782         stream->n_sample_times);
7783     if (!stream->n_sample_times)
7784       goto corrupt_file;
7785   }
7786
7787   /* sync sample atom */
7788   stream->stps_present = FALSE;
7789   if ((stream->stss_present =
7790           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7791               &stream->stss) ? TRUE : FALSE) == TRUE) {
7792     /* copy atom data into a new buffer for later use */
7793     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7794
7795     /* skip version + flags */
7796     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7797         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7798       goto corrupt_file;
7799
7800     if (stream->n_sample_syncs) {
7801       /* make sure there's enough data */
7802       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7803         goto corrupt_file;
7804     }
7805
7806     /* partial sync sample atom */
7807     if ((stream->stps_present =
7808             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7809                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7810       /* copy atom data into a new buffer for later use */
7811       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7812
7813       /* skip version + flags */
7814       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7815           !gst_byte_reader_get_uint32_be (&stream->stps,
7816               &stream->n_sample_partial_syncs))
7817         goto corrupt_file;
7818
7819       /* if there are no entries, the stss table contains the real
7820        * sync samples */
7821       if (stream->n_sample_partial_syncs) {
7822         /* make sure there's enough data */
7823         if (!qt_atom_parser_has_chunks (&stream->stps,
7824                 stream->n_sample_partial_syncs, 4))
7825           goto corrupt_file;
7826       }
7827     }
7828   }
7829
7830   /* sample size */
7831   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7832     goto no_samples;
7833
7834   /* copy atom data into a new buffer for later use */
7835   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7836
7837   /* skip version + flags */
7838   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7839       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7840     goto corrupt_file;
7841
7842   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7843     goto corrupt_file;
7844
7845   if (!stream->n_samples)
7846     goto no_samples;
7847
7848   /* sample-to-chunk atom */
7849   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7850     goto corrupt_file;
7851
7852   /* copy atom data into a new buffer for later use */
7853   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7854
7855   /* skip version + flags */
7856   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7857       !gst_byte_reader_get_uint32_be (&stream->stsc,
7858           &stream->n_samples_per_chunk))
7859     goto corrupt_file;
7860
7861   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7862       stream->n_samples_per_chunk);
7863
7864   /* make sure there's enough data */
7865   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7866           12))
7867     goto corrupt_file;
7868
7869
7870   /* chunk offset */
7871   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7872     stream->co_size = sizeof (guint32);
7873   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7874           &stream->stco))
7875     stream->co_size = sizeof (guint64);
7876   else
7877     goto corrupt_file;
7878
7879   /* copy atom data into a new buffer for later use */
7880   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7881
7882   /* skip version + flags */
7883   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7884     goto corrupt_file;
7885
7886   /* chunks_are_samples == TRUE means treat chunks as samples */
7887   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7888   if (stream->chunks_are_samples) {
7889     /* treat chunks as samples */
7890     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7891       goto corrupt_file;
7892   } else {
7893     /* skip number of entries */
7894     if (!gst_byte_reader_skip (&stream->stco, 4))
7895       goto corrupt_file;
7896
7897     /* make sure there are enough data in the stsz atom */
7898     if (!stream->sample_size) {
7899       /* different sizes for each sample */
7900       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7901         goto corrupt_file;
7902     }
7903   }
7904
7905   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7906       stream->n_samples, (guint) sizeof (QtDemuxSample),
7907       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7908
7909   if (stream->n_samples >=
7910       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7911     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7912         "be larger than %uMB (broken file?)", stream->n_samples,
7913         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7914     return FALSE;
7915   }
7916
7917   g_assert (stream->samples == NULL);
7918   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7919   if (!stream->samples) {
7920     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7921         stream->n_samples);
7922     return FALSE;
7923   }
7924
7925   /* composition time-to-sample */
7926   if ((stream->ctts_present =
7927           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7928               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7929     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7930
7931     /* copy atom data into a new buffer for later use */
7932     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7933
7934     /* skip version + flags */
7935     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7936         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7937             &stream->n_composition_times))
7938       goto corrupt_file;
7939
7940     /* make sure there's enough data */
7941     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7942             4 + 4))
7943       goto corrupt_file;
7944
7945     /* This is optional, if missing we iterate the ctts */
7946     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7947       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7948           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7949         g_free ((gpointer) cslg.data);
7950         goto corrupt_file;
7951       }
7952     } else {
7953       gint32 cslg_least = 0;
7954       guint num_entries, pos;
7955       gint i;
7956
7957       pos = gst_byte_reader_get_pos (&stream->ctts);
7958       num_entries = stream->n_composition_times;
7959
7960       stream->cslg_shift = 0;
7961
7962       for (i = 0; i < num_entries; i++) {
7963         gint32 offset;
7964
7965         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7966         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7967
7968         if (offset < cslg_least)
7969           cslg_least = offset;
7970       }
7971
7972       if (cslg_least < 0)
7973         stream->cslg_shift = ABS (cslg_least);
7974       else
7975         stream->cslg_shift = 0;
7976
7977       /* reset the reader so we can generate sample table */
7978       gst_byte_reader_set_pos (&stream->ctts, pos);
7979     }
7980   } else {
7981     /* Ensure the cslg_shift value is consistent so we can use it
7982      * unconditionnally to produce TS and Segment */
7983     stream->cslg_shift = 0;
7984   }
7985
7986   return TRUE;
7987
7988 corrupt_file:
7989   {
7990     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7991         (_("This file is corrupt and cannot be played.")), (NULL));
7992     return FALSE;
7993   }
7994 no_samples:
7995   {
7996     gst_qtdemux_stbl_free (stream);
7997     if (!qtdemux->fragmented) {
7998       /* not quite good */
7999       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8000       return FALSE;
8001     } else {
8002       /* may pick up samples elsewhere */
8003       return TRUE;
8004     }
8005   }
8006 }
8007
8008 /* collect samples from the next sample to be parsed up to sample @n for @stream
8009  * by reading the info from @stbl
8010  *
8011  * This code can be executed from both the streaming thread and the seeking
8012  * thread so it takes the object lock to protect itself
8013  */
8014 static gboolean
8015 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8016 {
8017   gint i, j, k;
8018   QtDemuxSample *samples, *first, *cur, *last;
8019   guint32 n_samples_per_chunk;
8020   guint32 n_samples;
8021
8022   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8023       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8024       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8025
8026   n_samples = stream->n_samples;
8027
8028   if (n >= n_samples)
8029     goto out_of_samples;
8030
8031   GST_OBJECT_LOCK (qtdemux);
8032   if (n <= stream->stbl_index)
8033     goto already_parsed;
8034
8035   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8036
8037   if (!stream->stsz.data) {
8038     /* so we already parsed and passed all the moov samples;
8039      * onto fragmented ones */
8040     g_assert (qtdemux->fragmented);
8041     goto done;
8042   }
8043
8044   /* pointer to the sample table */
8045   samples = stream->samples;
8046
8047   /* starts from -1, moves to the next sample index to parse */
8048   stream->stbl_index++;
8049
8050   /* keep track of the first and last sample to fill */
8051   first = &samples[stream->stbl_index];
8052   last = &samples[n];
8053
8054   if (!stream->chunks_are_samples) {
8055     /* set the sample sizes */
8056     if (stream->sample_size == 0) {
8057       /* different sizes for each sample */
8058       for (cur = first; cur <= last; cur++) {
8059         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8060         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8061             (guint) (cur - samples), cur->size);
8062       }
8063     } else {
8064       /* samples have the same size */
8065       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8066       for (cur = first; cur <= last; cur++)
8067         cur->size = stream->sample_size;
8068     }
8069   }
8070
8071   n_samples_per_chunk = stream->n_samples_per_chunk;
8072   cur = first;
8073
8074   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8075     guint32 last_chunk;
8076
8077     if (stream->stsc_chunk_index >= stream->last_chunk
8078         || stream->stsc_chunk_index < stream->first_chunk) {
8079       stream->first_chunk =
8080           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8081       stream->samples_per_chunk =
8082           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8083       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8084
8085       /* chunk numbers are counted from 1 it seems */
8086       if (G_UNLIKELY (stream->first_chunk == 0))
8087         goto corrupt_file;
8088
8089       --stream->first_chunk;
8090
8091       /* the last chunk of each entry is calculated by taking the first chunk
8092        * of the next entry; except if there is no next, where we fake it with
8093        * INT_MAX */
8094       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8095         stream->last_chunk = G_MAXUINT32;
8096       } else {
8097         stream->last_chunk =
8098             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8099         if (G_UNLIKELY (stream->last_chunk == 0))
8100           goto corrupt_file;
8101
8102         --stream->last_chunk;
8103       }
8104
8105       GST_LOG_OBJECT (qtdemux,
8106           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8107           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8108
8109       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8110         goto corrupt_file;
8111
8112       if (stream->last_chunk != G_MAXUINT32) {
8113         if (!qt_atom_parser_peek_sub (&stream->stco,
8114                 stream->first_chunk * stream->co_size,
8115                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8116                 &stream->co_chunk))
8117           goto corrupt_file;
8118
8119       } else {
8120         stream->co_chunk = stream->stco;
8121         if (!gst_byte_reader_skip (&stream->co_chunk,
8122                 stream->first_chunk * stream->co_size))
8123           goto corrupt_file;
8124       }
8125
8126       stream->stsc_chunk_index = stream->first_chunk;
8127     }
8128
8129     last_chunk = stream->last_chunk;
8130
8131     if (stream->chunks_are_samples) {
8132       cur = &samples[stream->stsc_chunk_index];
8133
8134       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8135         if (j > n) {
8136           /* save state */
8137           stream->stsc_chunk_index = j;
8138           goto done;
8139         }
8140
8141         cur->offset =
8142             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8143             stream->co_size);
8144
8145         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8146             "%" G_GUINT64_FORMAT, j, cur->offset);
8147
8148         if (stream->samples_per_frame * stream->bytes_per_frame) {
8149           cur->size =
8150               (stream->samples_per_chunk * stream->n_channels) /
8151               stream->samples_per_frame * stream->bytes_per_frame;
8152         } else {
8153           cur->size = stream->samples_per_chunk;
8154         }
8155
8156         GST_DEBUG_OBJECT (qtdemux,
8157             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8158             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8159                     stream->stco_sample_index)), cur->size);
8160
8161         cur->timestamp = stream->stco_sample_index;
8162         cur->duration = stream->samples_per_chunk;
8163         cur->keyframe = TRUE;
8164         cur++;
8165
8166         stream->stco_sample_index += stream->samples_per_chunk;
8167       }
8168       stream->stsc_chunk_index = j;
8169     } else {
8170       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8171         guint32 samples_per_chunk;
8172         guint64 chunk_offset;
8173
8174         if (!stream->stsc_sample_index
8175             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8176                 &stream->chunk_offset))
8177           goto corrupt_file;
8178
8179         samples_per_chunk = stream->samples_per_chunk;
8180         chunk_offset = stream->chunk_offset;
8181
8182         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8183           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8184               G_GUINT64_FORMAT " and size %d",
8185               (guint) (cur - samples), chunk_offset, cur->size);
8186
8187           cur->offset = chunk_offset;
8188           chunk_offset += cur->size;
8189           cur++;
8190
8191           if (G_UNLIKELY (cur > last)) {
8192             /* save state */
8193             stream->stsc_sample_index = k + 1;
8194             stream->chunk_offset = chunk_offset;
8195             stream->stsc_chunk_index = j;
8196             goto done2;
8197           }
8198         }
8199         stream->stsc_sample_index = 0;
8200       }
8201       stream->stsc_chunk_index = j;
8202     }
8203     stream->stsc_index++;
8204   }
8205
8206   if (stream->chunks_are_samples)
8207     goto ctts;
8208 done2:
8209   {
8210     guint32 n_sample_times;
8211
8212     n_sample_times = stream->n_sample_times;
8213     cur = first;
8214
8215     for (i = stream->stts_index; i < n_sample_times; i++) {
8216       guint32 stts_samples;
8217       gint32 stts_duration;
8218       gint64 stts_time;
8219
8220       if (stream->stts_sample_index >= stream->stts_samples
8221           || !stream->stts_sample_index) {
8222
8223         stream->stts_samples =
8224             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8225         stream->stts_duration =
8226             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8227
8228         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8229             i, stream->stts_samples, stream->stts_duration);
8230
8231         stream->stts_sample_index = 0;
8232       }
8233
8234       stts_samples = stream->stts_samples;
8235       stts_duration = stream->stts_duration;
8236       stts_time = stream->stts_time;
8237
8238       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8239         GST_DEBUG_OBJECT (qtdemux,
8240             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8241             (guint) (cur - samples), j,
8242             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8243
8244         cur->timestamp = stts_time;
8245         cur->duration = stts_duration;
8246
8247         /* avoid 32-bit wrap-around,
8248          * but still mind possible 'negative' duration */
8249         stts_time += (gint64) stts_duration;
8250         cur++;
8251
8252         if (G_UNLIKELY (cur > last)) {
8253           /* save values */
8254           stream->stts_time = stts_time;
8255           stream->stts_sample_index = j + 1;
8256           goto done3;
8257         }
8258       }
8259       stream->stts_sample_index = 0;
8260       stream->stts_time = stts_time;
8261       stream->stts_index++;
8262     }
8263     /* fill up empty timestamps with the last timestamp, this can happen when
8264      * the last samples do not decode and so we don't have timestamps for them.
8265      * We however look at the last timestamp to estimate the track length so we
8266      * need something in here. */
8267     for (; cur < last; cur++) {
8268       GST_DEBUG_OBJECT (qtdemux,
8269           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8270           (guint) (cur - samples),
8271           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8272       cur->timestamp = stream->stts_time;
8273       cur->duration = -1;
8274     }
8275   }
8276 done3:
8277   {
8278     /* sample sync, can be NULL */
8279     if (stream->stss_present == TRUE) {
8280       guint32 n_sample_syncs;
8281
8282       n_sample_syncs = stream->n_sample_syncs;
8283
8284       if (!n_sample_syncs) {
8285         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8286         stream->all_keyframe = TRUE;
8287       } else {
8288         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8289           /* note that the first sample is index 1, not 0 */
8290           guint32 index;
8291
8292           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8293
8294           if (G_LIKELY (index > 0 && index <= n_samples)) {
8295             index -= 1;
8296             samples[index].keyframe = TRUE;
8297             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8298             /* and exit if we have enough samples */
8299             if (G_UNLIKELY (index >= n)) {
8300               i++;
8301               break;
8302             }
8303           }
8304         }
8305         /* save state */
8306         stream->stss_index = i;
8307       }
8308
8309       /* stps marks partial sync frames like open GOP I-Frames */
8310       if (stream->stps_present == TRUE) {
8311         guint32 n_sample_partial_syncs;
8312
8313         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8314
8315         /* if there are no entries, the stss table contains the real
8316          * sync samples */
8317         if (n_sample_partial_syncs) {
8318           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8319             /* note that the first sample is index 1, not 0 */
8320             guint32 index;
8321
8322             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8323
8324             if (G_LIKELY (index > 0 && index <= n_samples)) {
8325               index -= 1;
8326               samples[index].keyframe = TRUE;
8327               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8328               /* and exit if we have enough samples */
8329               if (G_UNLIKELY (index >= n)) {
8330                 i++;
8331                 break;
8332               }
8333             }
8334           }
8335           /* save state */
8336           stream->stps_index = i;
8337         }
8338       }
8339     } else {
8340       /* no stss, all samples are keyframes */
8341       stream->all_keyframe = TRUE;
8342       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8343     }
8344   }
8345
8346 ctts:
8347   /* composition time to sample */
8348   if (stream->ctts_present == TRUE) {
8349     guint32 n_composition_times;
8350     guint32 ctts_count;
8351     gint32 ctts_soffset;
8352
8353     /* Fill in the pts_offsets */
8354     cur = first;
8355     n_composition_times = stream->n_composition_times;
8356
8357     for (i = stream->ctts_index; i < n_composition_times; i++) {
8358       if (stream->ctts_sample_index >= stream->ctts_count
8359           || !stream->ctts_sample_index) {
8360         stream->ctts_count =
8361             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8362         stream->ctts_soffset =
8363             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8364         stream->ctts_sample_index = 0;
8365       }
8366
8367       ctts_count = stream->ctts_count;
8368       ctts_soffset = stream->ctts_soffset;
8369
8370       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8371         cur->pts_offset = ctts_soffset;
8372         cur++;
8373
8374         if (G_UNLIKELY (cur > last)) {
8375           /* save state */
8376           stream->ctts_sample_index = j + 1;
8377           goto done;
8378         }
8379       }
8380       stream->ctts_sample_index = 0;
8381       stream->ctts_index++;
8382     }
8383   }
8384 done:
8385   stream->stbl_index = n;
8386   /* if index has been completely parsed, free data that is no-longer needed */
8387   if (n + 1 == stream->n_samples) {
8388     gst_qtdemux_stbl_free (stream);
8389     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8390     if (qtdemux->pullbased) {
8391       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8392       while (n + 1 == stream->n_samples)
8393         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8394           break;
8395     }
8396   }
8397   GST_OBJECT_UNLOCK (qtdemux);
8398
8399   return TRUE;
8400
8401   /* SUCCESS */
8402 already_parsed:
8403   {
8404     GST_LOG_OBJECT (qtdemux,
8405         "Tried to parse up to sample %u but this sample has already been parsed",
8406         n);
8407     /* if fragmented, there may be more */
8408     if (qtdemux->fragmented && n == stream->stbl_index)
8409       goto done;
8410     GST_OBJECT_UNLOCK (qtdemux);
8411     return TRUE;
8412   }
8413   /* ERRORS */
8414 out_of_samples:
8415   {
8416     GST_LOG_OBJECT (qtdemux,
8417         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8418         stream->n_samples);
8419     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8420         (_("This file is corrupt and cannot be played.")), (NULL));
8421     return FALSE;
8422   }
8423 corrupt_file:
8424   {
8425     GST_OBJECT_UNLOCK (qtdemux);
8426     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8427         (_("This file is corrupt and cannot be played.")), (NULL));
8428     return FALSE;
8429   }
8430 }
8431
8432 /* collect all segment info for @stream.
8433  */
8434 static gboolean
8435 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8436     GNode * trak)
8437 {
8438   GNode *edts;
8439   /* accept edts if they contain gaps at start and there is only
8440    * one media segment */
8441   gboolean allow_pushbased_edts = TRUE;
8442   gint media_segments_count = 0;
8443
8444   /* parse and prepare segment info from the edit list */
8445   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8446   stream->n_segments = 0;
8447   stream->segments = NULL;
8448   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8449     GNode *elst;
8450     gint n_segments;
8451     gint i, count, entry_size;
8452     guint64 time;
8453     GstClockTime stime;
8454     guint8 *buffer;
8455     guint8 version;
8456
8457     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8458     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8459       goto done;
8460
8461     buffer = elst->data;
8462
8463     version = QT_UINT8 (buffer + 8);
8464     entry_size = (version == 1) ? 20 : 12;
8465
8466     n_segments = QT_UINT32 (buffer + 12);
8467
8468     /* we might allocate a bit too much, at least allocate 1 segment */
8469     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8470
8471     /* segments always start from 0 */
8472     time = 0;
8473     stime = 0;
8474     count = 0;
8475     for (i = 0; i < n_segments; i++) {
8476       guint64 duration;
8477       guint64 media_time;
8478       gboolean time_valid = TRUE;
8479       QtDemuxSegment *segment;
8480       guint32 rate_int;
8481       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8482
8483       if (version == 1) {
8484         media_time = QT_UINT64 (buffer + 24 + i * entry_size);
8485         duration = QT_UINT64 (buffer + 16 + i * entry_size);
8486         if (media_time == G_MAXUINT64)
8487           time_valid = FALSE;
8488       } else {
8489         media_time = QT_UINT32 (buffer + 20 + i * entry_size);
8490         duration = QT_UINT32 (buffer + 16 + i * entry_size);
8491         if (media_time == G_MAXUINT32)
8492           time_valid = FALSE;
8493       }
8494
8495       if (time_valid)
8496         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8497
8498       segment = &stream->segments[count++];
8499
8500       /* time and duration expressed in global timescale */
8501       segment->time = stime;
8502       /* add non scaled values so we don't cause roundoff errors */
8503       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8504         time += duration;
8505         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8506         segment->duration = stime - segment->time;
8507       } else {
8508         /* zero duration does not imply media_start == media_stop
8509          * but, only specify media_start.*/
8510         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8511         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8512             && stime >= media_start) {
8513           segment->duration = stime - media_start;
8514         } else {
8515           segment->duration = GST_CLOCK_TIME_NONE;
8516         }
8517       }
8518       segment->stop_time = stime;
8519
8520       segment->trak_media_start = media_time;
8521       /* media_time expressed in stream timescale */
8522       if (time_valid) {
8523         segment->media_start = media_start;
8524         segment->media_stop = segment->media_start + segment->duration;
8525         media_segments_count++;
8526       } else {
8527         segment->media_start = GST_CLOCK_TIME_NONE;
8528         segment->media_stop = GST_CLOCK_TIME_NONE;
8529       }
8530       rate_int =
8531           QT_UINT32 (buffer + ((version == 1) ? 32 : 24) + i * entry_size);
8532
8533       if (rate_int <= 1) {
8534         /* 0 is not allowed, some programs write 1 instead of the floating point
8535          * value */
8536         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8537             rate_int);
8538         segment->rate = 1;
8539       } else {
8540         segment->rate = rate_int / 65536.0;
8541       }
8542
8543       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8544           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8545           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8546           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8547           i, GST_TIME_ARGS (segment->time),
8548           GST_TIME_ARGS (segment->duration),
8549           GST_TIME_ARGS (segment->media_start), media_time,
8550           GST_TIME_ARGS (segment->media_stop),
8551           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8552           stream->timescale);
8553       if (segment->stop_time > qtdemux->segment.stop) {
8554         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8555             " extends to %" GST_TIME_FORMAT
8556             " past the end of the file duration %" GST_TIME_FORMAT
8557             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8558             GST_TIME_ARGS (qtdemux->segment.stop));
8559         qtdemux->segment.stop = segment->stop_time;
8560       }
8561     }
8562     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8563     stream->n_segments = count;
8564     if (media_segments_count != 1)
8565       allow_pushbased_edts = FALSE;
8566   }
8567 done:
8568
8569   /* push based does not handle segments, so act accordingly here,
8570    * and warn if applicable */
8571   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8572     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8573     /* remove and use default one below, we stream like it anyway */
8574     g_free (stream->segments);
8575     stream->segments = NULL;
8576     stream->n_segments = 0;
8577   }
8578
8579   /* no segments, create one to play the complete trak */
8580   if (stream->n_segments == 0) {
8581     GstClockTime stream_duration =
8582         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8583
8584     if (stream->segments == NULL)
8585       stream->segments = g_new (QtDemuxSegment, 1);
8586
8587     /* represent unknown our way */
8588     if (stream_duration == 0)
8589       stream_duration = GST_CLOCK_TIME_NONE;
8590
8591     stream->segments[0].time = 0;
8592     stream->segments[0].stop_time = stream_duration;
8593     stream->segments[0].duration = stream_duration;
8594     stream->segments[0].media_start = 0;
8595     stream->segments[0].media_stop = stream_duration;
8596     stream->segments[0].rate = 1.0;
8597     stream->segments[0].trak_media_start = 0;
8598
8599     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8600         GST_TIME_ARGS (stream_duration));
8601     stream->n_segments = 1;
8602     stream->dummy_segment = TRUE;
8603   }
8604   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8605
8606   return TRUE;
8607 }
8608
8609 /*
8610  * Parses the stsd atom of a svq3 trak looking for
8611  * the SMI and gama atoms.
8612  */
8613 static void
8614 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8615     guint8 ** gamma, GstBuffer ** seqh)
8616 {
8617   guint8 *_gamma = NULL;
8618   GstBuffer *_seqh = NULL;
8619   guint8 *stsd_data = stsd->data;
8620   guint32 length = QT_UINT32 (stsd_data);
8621   guint16 version;
8622
8623   if (length < 32) {
8624     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8625     goto end;
8626   }
8627
8628   stsd_data += 32;
8629   length -= 32;
8630   version = QT_UINT16 (stsd_data);
8631   if (version == 3) {
8632     if (length >= 70) {
8633       length -= 70;
8634       stsd_data += 70;
8635       while (length > 8) {
8636         guint32 fourcc, size;
8637         guint8 *data;
8638         size = QT_UINT32 (stsd_data);
8639         fourcc = QT_FOURCC (stsd_data + 4);
8640         data = stsd_data + 8;
8641
8642         if (size == 0) {
8643           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8644               "svq3 atom parsing");
8645           goto end;
8646         }
8647
8648         switch (fourcc) {
8649           case FOURCC_gama:{
8650             if (size == 12) {
8651               _gamma = data;
8652             } else {
8653               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8654                   " for gama atom, expected 12", size);
8655             }
8656             break;
8657           }
8658           case FOURCC_SMI_:{
8659             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8660               guint32 seqh_size;
8661               if (_seqh != NULL) {
8662                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8663                     " found, ignoring");
8664               } else {
8665                 seqh_size = QT_UINT32 (data + 4);
8666                 if (seqh_size > 0) {
8667                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8668                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8669                 }
8670               }
8671             }
8672             break;
8673           }
8674           default:{
8675             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8676                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8677           }
8678         }
8679
8680         if (size <= length) {
8681           length -= size;
8682           stsd_data += size;
8683         }
8684       }
8685     } else {
8686       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8687     }
8688   } else {
8689     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8690         G_GUINT16_FORMAT, version);
8691     goto end;
8692   }
8693
8694 end:
8695   if (gamma) {
8696     *gamma = _gamma;
8697   }
8698   if (seqh) {
8699     *seqh = _seqh;
8700   } else if (_seqh) {
8701     gst_buffer_unref (_seqh);
8702   }
8703 }
8704
8705 static gchar *
8706 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8707 {
8708   GNode *dinf;
8709   GstByteReader dref;
8710   gchar *uri = NULL;
8711
8712   /*
8713    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8714    * atom that might contain a 'data' atom with the rtsp uri.
8715    * This case was reported in bug #597497, some info about
8716    * the hndl atom can be found in TN1195
8717    */
8718   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8719   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8720
8721   if (dinf) {
8722     guint32 dref_num_entries = 0;
8723     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8724         gst_byte_reader_skip (&dref, 4) &&
8725         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8726       gint i;
8727
8728       /* search dref entries for hndl atom */
8729       for (i = 0; i < dref_num_entries; i++) {
8730         guint32 size = 0, type;
8731         guint8 string_len = 0;
8732         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8733             qt_atom_parser_get_fourcc (&dref, &type)) {
8734           if (type == FOURCC_hndl) {
8735             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8736
8737             /* skip data reference handle bytes and the
8738              * following pascal string and some extra 4
8739              * bytes I have no idea what are */
8740             if (!gst_byte_reader_skip (&dref, 4) ||
8741                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8742                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8743               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8744               break;
8745             }
8746
8747             /* iterate over the atoms to find the data atom */
8748             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8749               guint32 atom_size;
8750               guint32 atom_type;
8751
8752               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8753                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8754                 if (atom_type == FOURCC_data) {
8755                   const guint8 *uri_aux = NULL;
8756
8757                   /* found the data atom that might contain the rtsp uri */
8758                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8759                       "hndl atom, interpreting it as an URI");
8760                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8761                           &uri_aux)) {
8762                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8763                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8764                     else
8765                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8766                           "didn't contain a rtsp address");
8767                   } else {
8768                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8769                         "atom contents");
8770                   }
8771                   break;
8772                 }
8773                 /* skipping to the next entry */
8774                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8775                   break;
8776               } else {
8777                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8778                     "atom header");
8779                 break;
8780               }
8781             }
8782             break;
8783           }
8784           /* skip to the next entry */
8785           if (!gst_byte_reader_skip (&dref, size - 8))
8786             break;
8787         } else {
8788           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8789         }
8790       }
8791       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8792     }
8793   }
8794   return uri;
8795 }
8796
8797 #define AMR_NB_ALL_MODES        0x81ff
8798 #define AMR_WB_ALL_MODES        0x83ff
8799 static guint
8800 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8801 {
8802   /* The 'damr' atom is of the form:
8803    *
8804    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8805    *    32 b       8 b          16 b           8 b                 8 b
8806    *
8807    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8808    * represents the highest mode used in the stream (and thus the maximum
8809    * bitrate), with a couple of special cases as seen below.
8810    */
8811
8812   /* Map of frame type ID -> bitrate */
8813   static const guint nb_bitrates[] = {
8814     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8815   };
8816   static const guint wb_bitrates[] = {
8817     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8818   };
8819   GstMapInfo map;
8820   gsize max_mode;
8821   guint16 mode_set;
8822
8823   gst_buffer_map (buf, &map, GST_MAP_READ);
8824
8825   if (map.size != 0x11) {
8826     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8827     goto bad_data;
8828   }
8829
8830   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8831     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8832         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8833     goto bad_data;
8834   }
8835
8836   mode_set = QT_UINT16 (map.data + 13);
8837
8838   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8839     max_mode = 7 + (wb ? 1 : 0);
8840   else
8841     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8842     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8843
8844   if (max_mode == -1) {
8845     GST_DEBUG ("No mode indication was found (mode set) = %x",
8846         (guint) mode_set);
8847     goto bad_data;
8848   }
8849
8850   gst_buffer_unmap (buf, &map);
8851   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8852
8853 bad_data:
8854   gst_buffer_unmap (buf, &map);
8855   return 0;
8856 }
8857
8858 static gboolean
8859 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8860     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8861 {
8862   /*
8863    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8864    * [0 1 2]
8865    * [3 4 5]
8866    * [6 7 8]
8867    */
8868
8869   if (gst_byte_reader_get_remaining (reader) < 36)
8870     return FALSE;
8871
8872   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8873   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8874   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8875   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8876   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8877   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8878   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8879   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8880   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8881
8882   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8883   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8884       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8885       matrix[2] & 0xFF);
8886   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8887       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8888       matrix[5] & 0xFF);
8889   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8890       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8891       matrix[8] & 0xFF);
8892
8893   return TRUE;
8894 }
8895
8896 static void
8897 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8898     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8899 {
8900
8901 /* [a b c]
8902  * [d e f]
8903  * [g h i]
8904  *
8905  * This macro will only compare value abdegh, it expects cfi to have already
8906  * been checked
8907  */
8908 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8909                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8910
8911   /* only handle the cases where the last column has standard values */
8912   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8913     const gchar *rotation_tag = NULL;
8914
8915     /* no rotation needed */
8916     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8917       /* NOP */
8918     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8919       rotation_tag = "rotate-90";
8920     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8921       rotation_tag = "rotate-180";
8922     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8923       rotation_tag = "rotate-270";
8924     } else {
8925       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8926     }
8927
8928     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8929         rotation_tag);
8930     if (rotation_tag != NULL) {
8931       if (*taglist == NULL)
8932         *taglist = gst_tag_list_new_empty ();
8933       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8934           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8935     }
8936   } else {
8937     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8938   }
8939 }
8940
8941 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8942  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8943  * Common Encryption (cenc), the function will also parse the tenc box (defined
8944  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8945  * (typically an enc[v|a|t|s] sample entry); the function will set
8946  * @original_fmt to the fourcc of the original unencrypted stream format.
8947  * Returns TRUE if successful; FALSE otherwise. */
8948 static gboolean
8949 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8950     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8951 {
8952   GNode *sinf;
8953   GNode *frma;
8954   GNode *schm;
8955   GNode *schi;
8956
8957   g_return_val_if_fail (qtdemux != NULL, FALSE);
8958   g_return_val_if_fail (stream != NULL, FALSE);
8959   g_return_val_if_fail (container != NULL, FALSE);
8960   g_return_val_if_fail (original_fmt != NULL, FALSE);
8961
8962   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8963   if (G_UNLIKELY (!sinf)) {
8964     if (stream->protection_scheme_type == FOURCC_cenc) {
8965       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8966           "mandatory for Common Encryption");
8967       return FALSE;
8968     }
8969     return TRUE;
8970   }
8971
8972   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8973   if (G_UNLIKELY (!frma)) {
8974     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8975     return FALSE;
8976   }
8977
8978   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8979   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8980       GST_FOURCC_ARGS (*original_fmt));
8981
8982   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8983   if (!schm) {
8984     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8985     return FALSE;
8986   }
8987   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
8988   stream->protection_scheme_version =
8989       QT_UINT32 ((const guint8 *) schm->data + 16);
8990
8991   GST_DEBUG_OBJECT (qtdemux,
8992       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
8993       "protection_scheme_version: %#010x",
8994       GST_FOURCC_ARGS (stream->protection_scheme_type),
8995       stream->protection_scheme_version);
8996
8997   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
8998   if (!schi) {
8999     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9000     return FALSE;
9001   }
9002   if (stream->protection_scheme_type == FOURCC_cenc) {
9003     QtDemuxCencSampleSetInfo *info;
9004     GNode *tenc;
9005     const guint8 *tenc_data;
9006     guint32 isEncrypted;
9007     guint8 iv_size;
9008     const guint8 *default_kid;
9009     GstBuffer *kid_buf;
9010
9011     if (G_UNLIKELY (!stream->protection_scheme_info))
9012       stream->protection_scheme_info =
9013           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9014
9015     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9016
9017     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9018     if (!tenc) {
9019       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9020           "which is mandatory for Common Encryption");
9021       return FALSE;
9022     }
9023     tenc_data = (const guint8 *) tenc->data + 12;
9024     isEncrypted = QT_UINT24 (tenc_data);
9025     iv_size = QT_UINT8 (tenc_data + 3);
9026     default_kid = (tenc_data + 4);
9027     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9028     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9029     if (info->default_properties)
9030       gst_structure_free (info->default_properties);
9031     info->default_properties =
9032         gst_structure_new ("application/x-cenc",
9033         "iv_size", G_TYPE_UINT, iv_size,
9034         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9035         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9036     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9037         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9038     gst_buffer_unref (kid_buf);
9039   }
9040   return TRUE;
9041 }
9042
9043 /* parse the traks.
9044  * With each track we associate a new QtDemuxStream that contains all the info
9045  * about the trak.
9046  * traks that do not decode to something (like strm traks) will not have a pad.
9047  */
9048 static gboolean
9049 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9050 {
9051   GstByteReader tkhd;
9052   int offset;
9053   GNode *mdia;
9054   GNode *mdhd;
9055   GNode *hdlr;
9056   GNode *minf;
9057   GNode *stbl;
9058   GNode *stsd;
9059   GNode *mp4a;
9060   GNode *mp4v;
9061   GNode *wave;
9062   GNode *esds;
9063   GNode *pasp;
9064   GNode *tref;
9065   GNode *udta;
9066   GNode *svmi;
9067
9068   QtDemuxStream *stream = NULL;
9069   gboolean new_stream = FALSE;
9070   gchar *codec = NULL;
9071   const guint8 *stsd_data;
9072   guint16 lang_code;            /* quicktime lang code or packed iso code */
9073   guint32 version;
9074   guint32 tkhd_flags = 0;
9075   guint8 tkhd_version = 0;
9076   guint32 fourcc;
9077   guint value_size, stsd_len, len;
9078   guint32 track_id;
9079   guint32 dummy;
9080
9081   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9082
9083   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9084       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9085       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9086     goto corrupt_file;
9087
9088   /* pick between 64 or 32 bits */
9089   value_size = tkhd_version == 1 ? 8 : 4;
9090   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9091       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9092     goto corrupt_file;
9093
9094   if (!qtdemux->got_moov) {
9095     if (qtdemux_find_stream (qtdemux, track_id))
9096       goto existing_stream;
9097     stream = _create_stream ();
9098     stream->track_id = track_id;
9099     new_stream = TRUE;
9100   } else {
9101     stream = qtdemux_find_stream (qtdemux, track_id);
9102     if (!stream) {
9103       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9104       goto skip_track;
9105     }
9106
9107     /* flush samples data from this track from previous moov */
9108     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9109     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9110   }
9111   /* need defaults for fragments */
9112   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9113
9114   if (stream->pending_tags == NULL)
9115     stream->pending_tags = gst_tag_list_new_empty ();
9116
9117   if ((tkhd_flags & 1) == 0)
9118     stream->disabled = TRUE;
9119
9120   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9121       tkhd_version, tkhd_flags, stream->track_id);
9122
9123   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9124     goto corrupt_file;
9125
9126   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9127     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9128     if (qtdemux->major_brand != FOURCC_mjp2 ||
9129         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9130       goto corrupt_file;
9131   }
9132
9133   len = QT_UINT32 ((guint8 *) mdhd->data);
9134   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9135   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9136   if (version == 0x01000000) {
9137     if (len < 38)
9138       goto corrupt_file;
9139     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9140     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9141     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9142   } else {
9143     if (len < 30)
9144       goto corrupt_file;
9145     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9146     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9147     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9148   }
9149
9150   if (lang_code < 0x400) {
9151     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9152   } else if (lang_code == 0x7fff) {
9153     stream->lang_id[0] = 0;     /* unspecified */
9154   } else {
9155     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9156     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9157     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9158     stream->lang_id[3] = 0;
9159   }
9160
9161   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9162       stream->timescale);
9163   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9164       stream->duration);
9165   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9166       lang_code, stream->lang_id);
9167
9168   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9169     goto corrupt_file;
9170
9171   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9172     /* chapters track reference */
9173     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9174     if (chap) {
9175       gsize length = GST_READ_UINT32_BE (chap->data);
9176       if (qtdemux->chapters_track_id)
9177         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9178
9179       if (length >= 12) {
9180         qtdemux->chapters_track_id =
9181             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9182       }
9183     }
9184   }
9185
9186   /* fragmented files may have bogus duration in moov */
9187   if (!qtdemux->fragmented &&
9188       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9189     guint64 tdur1, tdur2;
9190
9191     /* don't overflow */
9192     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9193     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9194
9195     /* HACK:
9196      * some of those trailers, nowadays, have prologue images that are
9197      * themselves video tracks as well. I haven't really found a way to
9198      * identify those yet, except for just looking at their duration. */
9199     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9200       GST_WARNING_OBJECT (qtdemux,
9201           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9202           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9203           "found, assuming preview image or something; skipping track",
9204           stream->duration, stream->timescale, qtdemux->duration,
9205           qtdemux->timescale);
9206       if (new_stream)
9207         gst_qtdemux_stream_free (qtdemux, stream);
9208       return TRUE;
9209     }
9210   }
9211
9212   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9213     goto corrupt_file;
9214
9215   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9216       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9217
9218   len = QT_UINT32 ((guint8 *) hdlr->data);
9219   if (len >= 20)
9220     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9221   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9222       GST_FOURCC_ARGS (stream->subtype));
9223
9224   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9225     goto corrupt_file;
9226
9227   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9228     goto corrupt_file;
9229
9230   /*parse svmi header if existing */
9231   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9232   if (svmi) {
9233     len = QT_UINT32 ((guint8 *) svmi->data);
9234     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9235     if (!version) {
9236       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9237       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9238       guint8 frame_type, frame_layout;
9239
9240       /* MPEG-A stereo video */
9241       if (qtdemux->major_brand == FOURCC_ss02)
9242         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9243
9244       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9245       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9246       switch (frame_type) {
9247         case 0:
9248           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9249           break;
9250         case 1:
9251           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9252           break;
9253         case 2:
9254           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9255           break;
9256         case 3:
9257           /* mode 3 is primary/secondary view sequence, ie
9258            * left/right views in separate tracks. See section 7.2
9259            * of ISO/IEC 23000-11:2009 */
9260           GST_FIXME_OBJECT (qtdemux,
9261               "Implement stereo video in separate streams");
9262       }
9263
9264       if ((frame_layout & 0x1) == 0)
9265         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9266
9267       GST_LOG_OBJECT (qtdemux,
9268           "StereoVideo: composition type: %u, is_left_first: %u",
9269           frame_type, frame_layout);
9270       stream->multiview_mode = mode;
9271       stream->multiview_flags = flags;
9272     }
9273   }
9274
9275   /* parse stsd */
9276   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9277     goto corrupt_file;
9278   stsd_data = (const guint8 *) stsd->data;
9279
9280   /* stsd should at least have one entry */
9281   stsd_len = QT_UINT32 (stsd_data);
9282   if (stsd_len < 24) {
9283     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9284     if (stream->subtype == FOURCC_vivo) {
9285       if (new_stream)
9286         gst_qtdemux_stream_free (qtdemux, stream);
9287       return TRUE;
9288     } else {
9289       goto corrupt_file;
9290     }
9291   }
9292
9293   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9294
9295   /* and that entry should fit within stsd */
9296   len = QT_UINT32 (stsd_data + 16);
9297   if (len > stsd_len + 16)
9298     goto corrupt_file;
9299
9300   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9301   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9302       GST_FOURCC_ARGS (stream->fourcc));
9303   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9304
9305   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9306     goto error_encrypted;
9307
9308   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9309     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9310     stream->protected = TRUE;
9311     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9312       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9313   }
9314
9315   if (stream->subtype == FOURCC_vide) {
9316     guint32 w = 0, h = 0;
9317     gboolean gray;
9318     gint depth, palette_size, palette_count;
9319     guint32 matrix[9];
9320     guint32 *palette_data = NULL;
9321
9322     stream->sampled = TRUE;
9323
9324     /* version 1 uses some 64-bit ints */
9325     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9326       goto corrupt_file;
9327
9328     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9329       goto corrupt_file;
9330
9331     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9332         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9333       goto corrupt_file;
9334
9335     stream->display_width = w >> 16;
9336     stream->display_height = h >> 16;
9337
9338     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9339         &stream->pending_tags);
9340
9341     offset = 16;
9342     if (len < 86)
9343       goto corrupt_file;
9344
9345     stream->width = QT_UINT16 (stsd_data + offset + 32);
9346     stream->height = QT_UINT16 (stsd_data + offset + 34);
9347     stream->fps_n = 0;          /* this is filled in later */
9348     stream->fps_d = 0;          /* this is filled in later */
9349     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9350     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9351
9352     /* if color_table_id is 0, ctab atom must follow; however some files
9353      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9354      * if color table is not present we'll correct the value */
9355     if (stream->color_table_id == 0 &&
9356         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9357       stream->color_table_id = -1;
9358     }
9359
9360     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9361         stream->width, stream->height, stream->bits_per_sample,
9362         stream->color_table_id);
9363
9364     depth = stream->bits_per_sample;
9365
9366     /* more than 32 bits means grayscale */
9367     gray = (depth > 32);
9368     /* low 32 bits specify the depth  */
9369     depth &= 0x1F;
9370
9371     /* different number of palette entries is determined by depth. */
9372     palette_count = 0;
9373     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9374       palette_count = (1 << depth);
9375     palette_size = palette_count * 4;
9376
9377     if (stream->color_table_id) {
9378       switch (palette_count) {
9379         case 0:
9380           break;
9381         case 2:
9382           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9383           break;
9384         case 4:
9385           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9386           break;
9387         case 16:
9388           if (gray)
9389             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9390           else
9391             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9392           break;
9393         case 256:
9394           if (gray)
9395             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9396           else
9397             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9398           break;
9399         default:
9400           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9401               (_("The video in this file might not play correctly.")),
9402               ("unsupported palette depth %d", depth));
9403           break;
9404       }
9405     } else {
9406       gint i, j, start, end;
9407
9408       if (len < 94)
9409         goto corrupt_file;
9410
9411       /* read table */
9412       start = QT_UINT32 (stsd_data + offset + 86);
9413       palette_count = QT_UINT16 (stsd_data + offset + 90);
9414       end = QT_UINT16 (stsd_data + offset + 92);
9415
9416       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9417           start, end, palette_count);
9418
9419       if (end > 255)
9420         end = 255;
9421       if (start > end)
9422         start = end;
9423
9424       if (len < 94 + (end - start) * 8)
9425         goto corrupt_file;
9426
9427       /* palette is always the same size */
9428       palette_data = g_malloc0 (256 * 4);
9429       palette_size = 256 * 4;
9430
9431       for (j = 0, i = start; i <= end; j++, i++) {
9432         guint32 a, r, g, b;
9433
9434         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9435         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9436         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9437         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9438
9439         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9440             (g & 0xff00) | (b >> 8);
9441       }
9442     }
9443
9444     if (stream->caps)
9445       gst_caps_unref (stream->caps);
9446
9447     stream->caps =
9448         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9449     if (G_UNLIKELY (!stream->caps)) {
9450       g_free (palette_data);
9451       goto unknown_stream;
9452     }
9453
9454     if (codec) {
9455       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9456           GST_TAG_VIDEO_CODEC, codec, NULL);
9457       g_free (codec);
9458       codec = NULL;
9459     }
9460
9461
9462     if (palette_data) {
9463       GstStructure *s;
9464
9465       if (stream->rgb8_palette)
9466         gst_memory_unref (stream->rgb8_palette);
9467       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9468           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9469
9470       s = gst_caps_get_structure (stream->caps, 0);
9471
9472       /* non-raw video has a palette_data property. raw video has the palette as
9473        * an extra plane that we append to the output buffers before we push
9474        * them*/
9475       if (!gst_structure_has_name (s, "video/x-raw")) {
9476         GstBuffer *palette;
9477
9478         palette = gst_buffer_new ();
9479         gst_buffer_append_memory (palette, stream->rgb8_palette);
9480         stream->rgb8_palette = NULL;
9481
9482         gst_caps_set_simple (stream->caps, "palette_data",
9483             GST_TYPE_BUFFER, palette, NULL);
9484         gst_buffer_unref (palette);
9485       }
9486     } else if (palette_count != 0) {
9487       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9488           (NULL), ("Unsupported palette depth %d", depth));
9489     }
9490
9491     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9492         QT_UINT16 (stsd_data + offset + 48));
9493
9494     esds = NULL;
9495     pasp = NULL;
9496     /* pick 'the' stsd child */
9497     if (!stream->protected)
9498       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9499     else
9500       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9501
9502     if (mp4v) {
9503       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9504       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9505     }
9506
9507     if (pasp) {
9508       const guint8 *pasp_data = (const guint8 *) pasp->data;
9509
9510       stream->par_w = QT_UINT32 (pasp_data + 8);
9511       stream->par_h = QT_UINT32 (pasp_data + 12);
9512     } else {
9513       stream->par_w = 0;
9514       stream->par_h = 0;
9515     }
9516
9517     if (esds) {
9518       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9519     } else {
9520       switch (fourcc) {
9521         case FOURCC_H264:
9522         case FOURCC_avc1:
9523         case FOURCC_avc3:
9524         {
9525           gint len = QT_UINT32 (stsd_data) - 0x66;
9526           const guint8 *avc_data = stsd_data + 0x66;
9527
9528           /* find avcC */
9529           while (len >= 0x8) {
9530             gint size;
9531
9532             if (QT_UINT32 (avc_data) <= len)
9533               size = QT_UINT32 (avc_data) - 0x8;
9534             else
9535               size = len - 0x8;
9536
9537             if (size < 1)
9538               /* No real data, so break out */
9539               break;
9540
9541             switch (QT_FOURCC (avc_data + 0x4)) {
9542               case FOURCC_avcC:
9543               {
9544                 /* parse, if found */
9545                 GstBuffer *buf;
9546
9547                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9548
9549                 /* First 4 bytes are the length of the atom, the next 4 bytes
9550                  * are the fourcc, the next 1 byte is the version, and the
9551                  * subsequent bytes are profile_tier_level structure like data. */
9552                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9553                     avc_data + 8 + 1, size - 1);
9554                 buf = gst_buffer_new_and_alloc (size);
9555                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9556                 gst_caps_set_simple (stream->caps,
9557                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9558                 gst_buffer_unref (buf);
9559
9560                 break;
9561               }
9562               case FOURCC_strf:
9563               {
9564                 GstBuffer *buf;
9565
9566                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9567
9568                 /* First 4 bytes are the length of the atom, the next 4 bytes
9569                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9570                  * next 1 byte is the version, and the
9571                  * subsequent bytes are sequence parameter set like data. */
9572
9573                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9574                 if (size > 1) {
9575                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9576                       avc_data + 8 + 40 + 1, size - 1);
9577
9578                   buf = gst_buffer_new_and_alloc (size);
9579                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9580                   gst_caps_set_simple (stream->caps,
9581                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9582                   gst_buffer_unref (buf);
9583                 }
9584                 break;
9585               }
9586               case FOURCC_btrt:
9587               {
9588                 guint avg_bitrate, max_bitrate;
9589
9590                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9591                 if (size < 12)
9592                   break;
9593
9594                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9595                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9596
9597                 if (!max_bitrate && !avg_bitrate)
9598                   break;
9599
9600                 /* Some muxers seem to swap the average and maximum bitrates
9601                  * (I'm looking at you, YouTube), so we swap for sanity. */
9602                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9603                   guint temp = avg_bitrate;
9604
9605                   avg_bitrate = max_bitrate;
9606                   max_bitrate = temp;
9607                 }
9608
9609                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9610                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9611                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9612                 }
9613                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9614                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9615                       GST_TAG_BITRATE, avg_bitrate, NULL);
9616                 }
9617
9618                 break;
9619               }
9620
9621               default:
9622                 break;
9623             }
9624
9625             len -= size + 8;
9626             avc_data += size + 8;
9627           }
9628
9629           break;
9630         }
9631         case FOURCC_H265:
9632         case FOURCC_hvc1:
9633         case FOURCC_hev1:
9634         {
9635           gint len = QT_UINT32 (stsd_data) - 0x66;
9636           const guint8 *hevc_data = stsd_data + 0x66;
9637
9638           /* find hevc */
9639           while (len >= 0x8) {
9640             gint size;
9641
9642             if (QT_UINT32 (hevc_data) <= len)
9643               size = QT_UINT32 (hevc_data) - 0x8;
9644             else
9645               size = len - 0x8;
9646
9647             if (size < 1)
9648               /* No real data, so break out */
9649               break;
9650
9651             switch (QT_FOURCC (hevc_data + 0x4)) {
9652               case FOURCC_hvcC:
9653               {
9654                 /* parse, if found */
9655                 GstBuffer *buf;
9656
9657                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9658
9659                 /* First 4 bytes are the length of the atom, the next 4 bytes
9660                  * are the fourcc, the next 1 byte is the version, and the
9661                  * subsequent bytes are sequence parameter set like data. */
9662                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9663                     (stream->caps, hevc_data + 8 + 1, size - 1);
9664
9665                 buf = gst_buffer_new_and_alloc (size);
9666                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9667                 gst_caps_set_simple (stream->caps,
9668                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9669                 gst_buffer_unref (buf);
9670                 break;
9671               }
9672               default:
9673                 break;
9674             }
9675             len -= size + 8;
9676             hevc_data += size + 8;
9677           }
9678           break;
9679         }
9680         case FOURCC_mp4v:
9681         case FOURCC_MP4V:
9682         case FOURCC_fmp4:
9683         case FOURCC_FMP4:
9684         {
9685           GNode *glbl;
9686
9687           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9688               GST_FOURCC_ARGS (fourcc));
9689
9690           /* codec data might be in glbl extension atom */
9691           glbl = mp4v ?
9692               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9693           if (glbl) {
9694             guint8 *data;
9695             GstBuffer *buf;
9696             gint len;
9697
9698             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9699             data = glbl->data;
9700             len = QT_UINT32 (data);
9701             if (len > 0x8) {
9702               len -= 0x8;
9703               buf = gst_buffer_new_and_alloc (len);
9704               gst_buffer_fill (buf, 0, data + 8, len);
9705               gst_caps_set_simple (stream->caps,
9706                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9707               gst_buffer_unref (buf);
9708             }
9709           }
9710           break;
9711         }
9712         case FOURCC_mjp2:
9713         {
9714           /* see annex I of the jpeg2000 spec */
9715           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9716           const guint8 *data;
9717           const gchar *colorspace = NULL;
9718           gint ncomp = 0;
9719           guint32 ncomp_map = 0;
9720           gint32 *comp_map = NULL;
9721           guint32 nchan_def = 0;
9722           gint32 *chan_def = NULL;
9723
9724           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9725           /* some required atoms */
9726           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9727           if (!mjp2)
9728             break;
9729           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9730           if (!jp2h)
9731             break;
9732
9733           /* number of components; redundant with info in codestream, but useful
9734              to a muxer */
9735           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9736           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9737             break;
9738           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9739
9740           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9741           if (!colr)
9742             break;
9743           GST_DEBUG_OBJECT (qtdemux, "found colr");
9744           /* extract colour space info */
9745           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9746             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9747               case 16:
9748                 colorspace = "sRGB";
9749                 break;
9750               case 17:
9751                 colorspace = "GRAY";
9752                 break;
9753               case 18:
9754                 colorspace = "sYUV";
9755                 break;
9756               default:
9757                 colorspace = NULL;
9758                 break;
9759             }
9760           }
9761           if (!colorspace)
9762             /* colr is required, and only values 16, 17, and 18 are specified,
9763                so error if we have no colorspace */
9764             break;
9765
9766           /* extract component mapping */
9767           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9768           if (cmap) {
9769             guint32 cmap_len = 0;
9770             int i;
9771             cmap_len = QT_UINT32 (cmap->data);
9772             if (cmap_len >= 8) {
9773               /* normal box, subtract off header */
9774               cmap_len -= 8;
9775               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9776               if (cmap_len % 4 == 0) {
9777                 ncomp_map = (cmap_len / 4);
9778                 comp_map = g_new0 (gint32, ncomp_map);
9779                 for (i = 0; i < ncomp_map; i++) {
9780                   guint16 cmp;
9781                   guint8 mtyp, pcol;
9782                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9783                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9784                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9785                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9786                 }
9787               }
9788             }
9789           }
9790           /* extract channel definitions */
9791           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9792           if (cdef) {
9793             guint32 cdef_len = 0;
9794             int i;
9795             cdef_len = QT_UINT32 (cdef->data);
9796             if (cdef_len >= 10) {
9797               /* normal box, subtract off header and len */
9798               cdef_len -= 10;
9799               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9800               if (cdef_len % 6 == 0) {
9801                 nchan_def = (cdef_len / 6);
9802                 chan_def = g_new0 (gint32, nchan_def);
9803                 for (i = 0; i < nchan_def; i++)
9804                   chan_def[i] = -1;
9805                 for (i = 0; i < nchan_def; i++) {
9806                   guint16 cn, typ, asoc;
9807                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9808                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9809                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9810                   if (cn < nchan_def) {
9811                     switch (typ) {
9812                       case 0:
9813                         chan_def[cn] = asoc;
9814                         break;
9815                       case 1:
9816                         chan_def[cn] = 0;       /* alpha */
9817                         break;
9818                       default:
9819                         chan_def[cn] = -typ;
9820                     }
9821                   }
9822                 }
9823               }
9824             }
9825           }
9826
9827           gst_caps_set_simple (stream->caps,
9828               "num-components", G_TYPE_INT, ncomp, NULL);
9829           gst_caps_set_simple (stream->caps,
9830               "colorspace", G_TYPE_STRING, colorspace, NULL);
9831
9832           if (comp_map) {
9833             GValue arr = { 0, };
9834             GValue elt = { 0, };
9835             int i;
9836             g_value_init (&arr, GST_TYPE_ARRAY);
9837             g_value_init (&elt, G_TYPE_INT);
9838             for (i = 0; i < ncomp_map; i++) {
9839               g_value_set_int (&elt, comp_map[i]);
9840               gst_value_array_append_value (&arr, &elt);
9841             }
9842             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9843                 "component-map", &arr);
9844             g_value_unset (&elt);
9845             g_value_unset (&arr);
9846             g_free (comp_map);
9847           }
9848
9849           if (chan_def) {
9850             GValue arr = { 0, };
9851             GValue elt = { 0, };
9852             int i;
9853             g_value_init (&arr, GST_TYPE_ARRAY);
9854             g_value_init (&elt, G_TYPE_INT);
9855             for (i = 0; i < nchan_def; i++) {
9856               g_value_set_int (&elt, chan_def[i]);
9857               gst_value_array_append_value (&arr, &elt);
9858             }
9859             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9860                 "channel-definitions", &arr);
9861             g_value_unset (&elt);
9862             g_value_unset (&arr);
9863             g_free (chan_def);
9864           }
9865
9866           /* some optional atoms */
9867           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9868           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9869
9870           /* indicate possible fields in caps */
9871           if (field) {
9872             data = (guint8 *) field->data + 8;
9873             if (*data != 1)
9874               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9875                   (gint) * data, NULL);
9876           }
9877           /* add codec_data if provided */
9878           if (prefix) {
9879             GstBuffer *buf;
9880             gint len;
9881
9882             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9883             data = prefix->data;
9884             len = QT_UINT32 (data);
9885             if (len > 0x8) {
9886               len -= 0x8;
9887               buf = gst_buffer_new_and_alloc (len);
9888               gst_buffer_fill (buf, 0, data + 8, len);
9889               gst_caps_set_simple (stream->caps,
9890                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9891               gst_buffer_unref (buf);
9892             }
9893           }
9894           break;
9895         }
9896         case FOURCC_SVQ3:
9897         case FOURCC_VP31:
9898         {
9899           GstBuffer *buf;
9900           GstBuffer *seqh = NULL;
9901           guint8 *gamma_data = NULL;
9902           gint len = QT_UINT32 (stsd_data);
9903
9904           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9905           if (gamma_data) {
9906             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9907                 QT_FP32 (gamma_data), NULL);
9908           }
9909           if (seqh) {
9910             /* sorry for the bad name, but we don't know what this is, other
9911              * than its own fourcc */
9912             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9913                 NULL);
9914           }
9915
9916           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9917           buf = gst_buffer_new_and_alloc (len);
9918           gst_buffer_fill (buf, 0, stsd_data, len);
9919           gst_caps_set_simple (stream->caps,
9920               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9921           gst_buffer_unref (buf);
9922           break;
9923         }
9924         case FOURCC_rle_:
9925         case FOURCC_WRLE:
9926         {
9927           gst_caps_set_simple (stream->caps,
9928               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9929           break;
9930         }
9931         case FOURCC_XiTh:
9932         {
9933           GNode *xith, *xdxt;
9934
9935           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9936           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9937           if (!xith)
9938             break;
9939
9940           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9941           if (!xdxt)
9942             break;
9943
9944           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9945           /* collect the headers and store them in a stream list so that we can
9946            * send them out first */
9947           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9948           break;
9949         }
9950         case FOURCC_ovc1:
9951         {
9952           GNode *ovc1;
9953           guint8 *ovc1_data;
9954           guint ovc1_len;
9955           GstBuffer *buf;
9956
9957           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9958           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9959           if (!ovc1)
9960             break;
9961           ovc1_data = ovc1->data;
9962           ovc1_len = QT_UINT32 (ovc1_data);
9963           if (ovc1_len <= 198) {
9964             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9965             break;
9966           }
9967           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9968           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9969           gst_caps_set_simple (stream->caps,
9970               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9971           gst_buffer_unref (buf);
9972           break;
9973         }
9974         case FOURCC_vc_1:
9975         {
9976           gint len = QT_UINT32 (stsd_data) - 0x66;
9977           const guint8 *vc1_data = stsd_data + 0x66;
9978
9979           /* find dvc1 */
9980           while (len >= 8) {
9981             gint size;
9982
9983             if (QT_UINT32 (vc1_data) <= len)
9984               size = QT_UINT32 (vc1_data) - 8;
9985             else
9986               size = len - 8;
9987
9988             if (size < 1)
9989               /* No real data, so break out */
9990               break;
9991
9992             switch (QT_FOURCC (vc1_data + 0x4)) {
9993               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
9994               {
9995                 GstBuffer *buf;
9996
9997                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
9998                 buf = gst_buffer_new_and_alloc (size);
9999                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
10000                 gst_caps_set_simple (stream->caps,
10001                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10002                 gst_buffer_unref (buf);
10003                 break;
10004               }
10005               default:
10006                 break;
10007             }
10008             len -= size + 8;
10009             vc1_data += size + 8;
10010           }
10011           break;
10012         }
10013         default:
10014           break;
10015       }
10016     }
10017
10018     GST_INFO_OBJECT (qtdemux,
10019         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10020         GST_FOURCC_ARGS (fourcc), stream->caps);
10021
10022   } else if (stream->subtype == FOURCC_soun) {
10023     int version, samplesize;
10024     guint16 compression_id;
10025     gboolean amrwb = FALSE;
10026
10027     offset = 32;
10028     /* sample description entry (16) + sound sample description v0 (20) */
10029     if (len < 36)
10030       goto corrupt_file;
10031
10032     version = QT_UINT32 (stsd_data + offset);
10033     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10034     samplesize = QT_UINT16 (stsd_data + offset + 10);
10035     compression_id = QT_UINT16 (stsd_data + offset + 12);
10036     stream->rate = QT_FP32 (stsd_data + offset + 16);
10037
10038     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10039     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10040         QT_UINT32 (stsd_data + offset + 4));
10041     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10042     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10043     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10044     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10045         QT_UINT16 (stsd_data + offset + 14));
10046     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10047
10048     if (compression_id == 0xfffe)
10049       stream->sampled = TRUE;
10050
10051     /* first assume uncompressed audio */
10052     stream->bytes_per_sample = samplesize / 8;
10053     stream->samples_per_frame = stream->n_channels;
10054     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10055     stream->samples_per_packet = stream->samples_per_frame;
10056     stream->bytes_per_packet = stream->bytes_per_sample;
10057
10058     offset = 52;
10059     switch (fourcc) {
10060         /* Yes, these have to be hard-coded */
10061       case FOURCC_MAC6:
10062       {
10063         stream->samples_per_packet = 6;
10064         stream->bytes_per_packet = 1;
10065         stream->bytes_per_frame = 1 * stream->n_channels;
10066         stream->bytes_per_sample = 1;
10067         stream->samples_per_frame = 6 * stream->n_channels;
10068         break;
10069       }
10070       case FOURCC_MAC3:
10071       {
10072         stream->samples_per_packet = 3;
10073         stream->bytes_per_packet = 1;
10074         stream->bytes_per_frame = 1 * stream->n_channels;
10075         stream->bytes_per_sample = 1;
10076         stream->samples_per_frame = 3 * stream->n_channels;
10077         break;
10078       }
10079       case FOURCC_ima4:
10080       {
10081         stream->samples_per_packet = 64;
10082         stream->bytes_per_packet = 34;
10083         stream->bytes_per_frame = 34 * stream->n_channels;
10084         stream->bytes_per_sample = 2;
10085         stream->samples_per_frame = 64 * stream->n_channels;
10086         break;
10087       }
10088       case FOURCC_ulaw:
10089       case FOURCC_alaw:
10090       {
10091         stream->samples_per_packet = 1;
10092         stream->bytes_per_packet = 1;
10093         stream->bytes_per_frame = 1 * stream->n_channels;
10094         stream->bytes_per_sample = 1;
10095         stream->samples_per_frame = 1 * stream->n_channels;
10096         break;
10097       }
10098       case FOURCC_agsm:
10099       {
10100         stream->samples_per_packet = 160;
10101         stream->bytes_per_packet = 33;
10102         stream->bytes_per_frame = 33 * stream->n_channels;
10103         stream->bytes_per_sample = 2;
10104         stream->samples_per_frame = 160 * stream->n_channels;
10105         break;
10106       }
10107       default:
10108         break;
10109     }
10110
10111     if (version == 0x00010000) {
10112       /* sample description entry (16) + sound sample description v1 (20+16) */
10113       if (len < 52)
10114         goto corrupt_file;
10115
10116       switch (fourcc) {
10117         case FOURCC_twos:
10118         case FOURCC_sowt:
10119         case FOURCC_raw_:
10120           break;
10121         default:
10122         {
10123           /* only parse extra decoding config for non-pcm audio */
10124           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10125           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10126           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10127           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10128
10129           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10130               stream->samples_per_packet);
10131           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10132               stream->bytes_per_packet);
10133           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10134               stream->bytes_per_frame);
10135           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10136               stream->bytes_per_sample);
10137
10138           if (!stream->sampled && stream->bytes_per_packet) {
10139             stream->samples_per_frame = (stream->bytes_per_frame /
10140                 stream->bytes_per_packet) * stream->samples_per_packet;
10141             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10142                 stream->samples_per_frame);
10143           }
10144           break;
10145         }
10146       }
10147     } else if (version == 0x00020000) {
10148       union
10149       {
10150         gdouble fp;
10151         guint64 val;
10152       } qtfp;
10153
10154       /* sample description entry (16) + sound sample description v2 (56) */
10155       if (len < 72)
10156         goto corrupt_file;
10157
10158       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10159       stream->rate = qtfp.fp;
10160       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10161
10162       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10163       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10164       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10165       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10166           QT_UINT32 (stsd_data + offset + 20));
10167       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10168           QT_UINT32 (stsd_data + offset + 24));
10169       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10170           QT_UINT32 (stsd_data + offset + 28));
10171       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10172           QT_UINT32 (stsd_data + offset + 32));
10173     } else if (version != 0x00000) {
10174       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10175     }
10176
10177     if (stream->caps)
10178       gst_caps_unref (stream->caps);
10179
10180     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10181         stsd_data + 32, len - 16, &codec);
10182
10183     switch (fourcc) {
10184       case FOURCC_in24:
10185       {
10186         GNode *enda;
10187         GNode *in24;
10188
10189         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10190
10191         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10192         if (!enda) {
10193           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10194           if (wave)
10195             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10196         }
10197         if (enda) {
10198           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10199           gst_caps_set_simple (stream->caps,
10200               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10201         }
10202         break;
10203       }
10204       case FOURCC_owma:
10205       {
10206         GNode *owma;
10207         const guint8 *owma_data;
10208         const gchar *codec_name = NULL;
10209         guint owma_len;
10210         GstBuffer *buf;
10211         gint version = 1;
10212         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10213         /* FIXME this should also be gst_riff_strf_auds,
10214          * but the latter one is actually missing bits-per-sample :( */
10215         typedef struct
10216         {
10217           gint16 wFormatTag;
10218           gint16 nChannels;
10219           gint32 nSamplesPerSec;
10220           gint32 nAvgBytesPerSec;
10221           gint16 nBlockAlign;
10222           gint16 wBitsPerSample;
10223           gint16 cbSize;
10224         } WAVEFORMATEX;
10225         WAVEFORMATEX *wfex;
10226
10227         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10228         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10229         if (!owma)
10230           break;
10231         owma_data = owma->data;
10232         owma_len = QT_UINT32 (owma_data);
10233         if (owma_len <= 54) {
10234           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10235           break;
10236         }
10237         wfex = (WAVEFORMATEX *) (owma_data + 36);
10238         buf = gst_buffer_new_and_alloc (owma_len - 54);
10239         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10240         if (wfex->wFormatTag == 0x0161) {
10241           codec_name = "Windows Media Audio";
10242           version = 2;
10243         } else if (wfex->wFormatTag == 0x0162) {
10244           codec_name = "Windows Media Audio 9 Pro";
10245           version = 3;
10246         } else if (wfex->wFormatTag == 0x0163) {
10247           codec_name = "Windows Media Audio 9 Lossless";
10248           /* is that correct? gstffmpegcodecmap.c is missing it, but
10249            * fluendo codec seems to support it */
10250           version = 4;
10251         }
10252
10253         gst_caps_set_simple (stream->caps,
10254             "codec_data", GST_TYPE_BUFFER, buf,
10255             "wmaversion", G_TYPE_INT, version,
10256             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10257             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10258             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10259             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10260             NULL);
10261         gst_buffer_unref (buf);
10262
10263         if (codec_name) {
10264           g_free (codec);
10265           codec = g_strdup (codec_name);
10266         }
10267         break;
10268       }
10269       case FOURCC_wma_:
10270       {
10271         gint len = QT_UINT32 (stsd_data) - offset;
10272         const guint8 *wfex_data = stsd_data + offset;
10273         const gchar *codec_name = NULL;
10274         gint version = 1;
10275         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10276         /* FIXME this should also be gst_riff_strf_auds,
10277          * but the latter one is actually missing bits-per-sample :( */
10278         typedef struct
10279         {
10280           gint16 wFormatTag;
10281           gint16 nChannels;
10282           gint32 nSamplesPerSec;
10283           gint32 nAvgBytesPerSec;
10284           gint16 nBlockAlign;
10285           gint16 wBitsPerSample;
10286           gint16 cbSize;
10287         } WAVEFORMATEX;
10288         WAVEFORMATEX wfex;
10289
10290         /* FIXME: unify with similar wavformatex parsing code above */
10291         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10292
10293         /* find wfex */
10294         while (len >= 8) {
10295           gint size;
10296
10297           if (QT_UINT32 (wfex_data) <= len)
10298             size = QT_UINT32 (wfex_data) - 8;
10299           else
10300             size = len - 8;
10301
10302           if (size < 1)
10303             /* No real data, so break out */
10304             break;
10305
10306           switch (QT_FOURCC (wfex_data + 4)) {
10307             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10308             {
10309               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10310
10311               if (size < 8 + 18)
10312                 break;
10313
10314               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10315               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10316               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10317               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10318               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10319               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10320               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10321
10322               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10323               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10324                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10325                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10326                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10327                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10328
10329               if (wfex.wFormatTag == 0x0161) {
10330                 codec_name = "Windows Media Audio";
10331                 version = 2;
10332               } else if (wfex.wFormatTag == 0x0162) {
10333                 codec_name = "Windows Media Audio 9 Pro";
10334                 version = 3;
10335               } else if (wfex.wFormatTag == 0x0163) {
10336                 codec_name = "Windows Media Audio 9 Lossless";
10337                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10338                  * fluendo codec seems to support it */
10339                 version = 4;
10340               }
10341
10342               gst_caps_set_simple (stream->caps,
10343                   "wmaversion", G_TYPE_INT, version,
10344                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10345                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10346                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10347                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10348
10349               if (size > wfex.cbSize) {
10350                 GstBuffer *buf;
10351
10352                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10353                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10354                     size - wfex.cbSize);
10355                 gst_caps_set_simple (stream->caps,
10356                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10357                 gst_buffer_unref (buf);
10358               } else {
10359                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10360               }
10361
10362               if (codec_name) {
10363                 g_free (codec);
10364                 codec = g_strdup (codec_name);
10365               }
10366               break;
10367             }
10368             default:
10369               break;
10370           }
10371           len -= size + 8;
10372           wfex_data += size + 8;
10373         }
10374         break;
10375       }
10376       case FOURCC_opus:
10377       {
10378         GNode *opus;
10379         const guint8 *opus_data;
10380         guint8 *channel_mapping = NULL;
10381         guint32 rate;
10382         guint8 channels;
10383         guint8 channel_mapping_family;
10384         guint8 stream_count;
10385         guint8 coupled_count;
10386         guint8 i;
10387
10388         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10389         opus_data = opus->data;
10390
10391         channels = GST_READ_UINT8 (opus_data + 45);
10392         rate = GST_READ_UINT32_LE (opus_data + 48);
10393         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10394         stream_count = GST_READ_UINT8 (opus_data + 55);
10395         coupled_count = GST_READ_UINT8 (opus_data + 56);
10396
10397         if (channels > 0) {
10398           channel_mapping = g_malloc (channels * sizeof (guint8));
10399           for (i = 0; i < channels; i++)
10400             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10401         }
10402
10403         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10404             channel_mapping_family, stream_count, coupled_count,
10405             channel_mapping);
10406         break;
10407       }
10408       default:
10409         break;
10410     }
10411
10412     if (codec) {
10413       GstStructure *s;
10414       gint bitrate = 0;
10415
10416       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10417           GST_TAG_AUDIO_CODEC, codec, NULL);
10418       g_free (codec);
10419       codec = NULL;
10420
10421       /* some bitrate info may have ended up in caps */
10422       s = gst_caps_get_structure (stream->caps, 0);
10423       gst_structure_get_int (s, "bitrate", &bitrate);
10424       if (bitrate > 0)
10425         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10426             GST_TAG_BITRATE, bitrate, NULL);
10427     }
10428
10429     if (stream->protected && fourcc == FOURCC_mp4a)
10430       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10431     else
10432       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10433
10434     wave = NULL;
10435     esds = NULL;
10436     if (mp4a) {
10437       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10438       if (wave)
10439         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10440       if (!esds)
10441         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10442     }
10443
10444
10445     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10446        16 bits is a byte-swapped wave-style codec identifier,
10447        and we can find a WAVE header internally to a 'wave' atom here.
10448        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10449        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10450        is big-endian).
10451      */
10452     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10453       if (len < offset + 20) {
10454         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10455       } else {
10456         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10457         const guint8 *data = stsd_data + offset + 16;
10458         GNode *wavenode;
10459         GNode *waveheadernode;
10460
10461         wavenode = g_node_new ((guint8 *) data);
10462         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10463           const guint8 *waveheader;
10464           guint32 headerlen;
10465
10466           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10467           if (waveheadernode) {
10468             waveheader = (const guint8 *) waveheadernode->data;
10469             headerlen = QT_UINT32 (waveheader);
10470
10471             if (headerlen > 8) {
10472               gst_riff_strf_auds *header = NULL;
10473               GstBuffer *headerbuf;
10474               GstBuffer *extra;
10475
10476               waveheader += 8;
10477               headerlen -= 8;
10478
10479               headerbuf = gst_buffer_new_and_alloc (headerlen);
10480               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10481
10482               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10483                       headerbuf, &header, &extra)) {
10484                 gst_caps_unref (stream->caps);
10485                 /* FIXME: Need to do something with the channel reorder map */
10486                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10487                     header, extra, NULL, NULL, NULL);
10488
10489                 if (extra)
10490                   gst_buffer_unref (extra);
10491                 g_free (header);
10492               }
10493             }
10494           } else
10495             GST_DEBUG ("Didn't find waveheadernode for this codec");
10496         }
10497         g_node_destroy (wavenode);
10498       }
10499     } else if (esds) {
10500       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10501     } else {
10502       switch (fourcc) {
10503 #if 0
10504           /* FIXME: what is in the chunk? */
10505         case FOURCC_QDMC:
10506         {
10507           gint len = QT_UINT32 (stsd_data);
10508
10509           /* seems to be always = 116 = 0x74 */
10510           break;
10511         }
10512 #endif
10513         case FOURCC_QDM2:
10514         {
10515           gint len = QT_UINT32 (stsd_data);
10516
10517           if (len > 0x4C) {
10518             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10519
10520             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10521             gst_caps_set_simple (stream->caps,
10522                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10523             gst_buffer_unref (buf);
10524           }
10525           gst_caps_set_simple (stream->caps,
10526               "samplesize", G_TYPE_INT, samplesize, NULL);
10527           break;
10528         }
10529         case FOURCC_alac:
10530         {
10531           GNode *alac, *wave = NULL;
10532
10533           /* apparently, m4a has this atom appended directly in the stsd entry,
10534            * while mov has it in a wave atom */
10535           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10536           if (alac) {
10537             /* alac now refers to stsd entry atom */
10538             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10539             if (wave)
10540               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10541             else
10542               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10543           }
10544           if (alac) {
10545             const guint8 *alac_data = alac->data;
10546             gint len = QT_UINT32 (alac->data);
10547             GstBuffer *buf;
10548
10549             if (len < 36) {
10550               GST_DEBUG_OBJECT (qtdemux,
10551                   "discarding alac atom with unexpected len %d", len);
10552             } else {
10553               /* codec-data contains alac atom size and prefix,
10554                * ffmpeg likes it that way, not quite gst-ish though ...*/
10555               buf = gst_buffer_new_and_alloc (len);
10556               gst_buffer_fill (buf, 0, alac->data, len);
10557               gst_caps_set_simple (stream->caps,
10558                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10559               gst_buffer_unref (buf);
10560
10561               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10562               stream->n_channels = QT_UINT8 (alac_data + 21);
10563               stream->rate = QT_UINT32 (alac_data + 32);
10564             }
10565           }
10566           gst_caps_set_simple (stream->caps,
10567               "samplesize", G_TYPE_INT, samplesize, NULL);
10568           break;
10569         }
10570         case FOURCC_sawb:
10571           /* Fallthrough! */
10572           amrwb = TRUE;
10573         case FOURCC_samr:
10574         {
10575           gint len = QT_UINT32 (stsd_data);
10576
10577           if (len > 0x34) {
10578             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10579             guint bitrate;
10580
10581             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10582
10583             /* If we have enough data, let's try to get the 'damr' atom. See
10584              * the 3GPP container spec (26.244) for more details. */
10585             if ((len - 0x34) > 8 &&
10586                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10587               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10588                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10589             }
10590
10591             gst_caps_set_simple (stream->caps,
10592                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10593             gst_buffer_unref (buf);
10594           }
10595           break;
10596         }
10597         case FOURCC_mp4a:
10598         {
10599           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10600           gint len = QT_UINT32 (stsd_data);
10601
10602           if (len >= 50) {
10603             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10604
10605             if (sound_version == 1) {
10606               guint16 channels = QT_UINT16 (stsd_data + 40);
10607               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10608               guint8 codec_data[2];
10609               GstBuffer *buf;
10610               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10611
10612               gint sample_rate_index =
10613                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10614
10615               /* build AAC codec data */
10616               codec_data[0] = profile << 3;
10617               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10618               codec_data[1] = (sample_rate_index & 0x01) << 7;
10619               codec_data[1] |= (channels & 0xF) << 3;
10620
10621               buf = gst_buffer_new_and_alloc (2);
10622               gst_buffer_fill (buf, 0, codec_data, 2);
10623               gst_caps_set_simple (stream->caps,
10624                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10625               gst_buffer_unref (buf);
10626             }
10627           }
10628           break;
10629         }
10630         default:
10631           GST_INFO_OBJECT (qtdemux,
10632               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10633           break;
10634       }
10635     }
10636     GST_INFO_OBJECT (qtdemux,
10637         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10638         GST_FOURCC_ARGS (fourcc), stream->caps);
10639
10640   } else if (stream->subtype == FOURCC_strm) {
10641     if (fourcc == FOURCC_rtsp) {
10642       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10643     } else {
10644       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10645           GST_FOURCC_ARGS (fourcc));
10646       goto unknown_stream;
10647     }
10648     stream->sampled = TRUE;
10649   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10650       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10651
10652     stream->sampled = TRUE;
10653     stream->sparse = TRUE;
10654
10655     stream->caps =
10656         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10657     if (codec) {
10658       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10659           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10660       g_free (codec);
10661       codec = NULL;
10662     }
10663
10664     /* hunt for sort-of codec data */
10665     switch (fourcc) {
10666       case FOURCC_mp4s:
10667       {
10668         GNode *mp4s = NULL;
10669         GNode *esds = NULL;
10670
10671         /* look for palette in a stsd->mp4s->esds sub-atom */
10672         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10673         if (mp4s)
10674           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10675         if (esds == NULL) {
10676           /* Invalid STSD */
10677           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10678           break;
10679         }
10680
10681         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10682         break;
10683       }
10684       default:
10685         GST_INFO_OBJECT (qtdemux,
10686             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10687         break;
10688     }
10689     GST_INFO_OBJECT (qtdemux,
10690         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10691         GST_FOURCC_ARGS (fourcc), stream->caps);
10692   } else {
10693     /* everything in 1 sample */
10694     stream->sampled = TRUE;
10695
10696     stream->caps =
10697         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10698
10699     if (stream->caps == NULL)
10700       goto unknown_stream;
10701
10702     if (codec) {
10703       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10704           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10705       g_free (codec);
10706       codec = NULL;
10707     }
10708   }
10709
10710   /* promote to sampled format */
10711   if (stream->fourcc == FOURCC_samr) {
10712     /* force mono 8000 Hz for AMR */
10713     stream->sampled = TRUE;
10714     stream->n_channels = 1;
10715     stream->rate = 8000;
10716   } else if (stream->fourcc == FOURCC_sawb) {
10717     /* force mono 16000 Hz for AMR-WB */
10718     stream->sampled = TRUE;
10719     stream->n_channels = 1;
10720     stream->rate = 16000;
10721   } else if (stream->fourcc == FOURCC_mp4a) {
10722     stream->sampled = TRUE;
10723   }
10724
10725   /* collect sample information */
10726   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10727     goto samples_failed;
10728
10729   if (qtdemux->fragmented) {
10730     guint64 offset;
10731
10732     /* need all moov samples as basis; probably not many if any at all */
10733     /* prevent moof parsing taking of at this time */
10734     offset = qtdemux->moof_offset;
10735     qtdemux->moof_offset = 0;
10736     if (stream->n_samples &&
10737         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10738       qtdemux->moof_offset = offset;
10739       goto samples_failed;
10740     }
10741     qtdemux->moof_offset = 0;
10742     /* movie duration more reliable in this case (e.g. mehd) */
10743     if (qtdemux->segment.duration &&
10744         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10745       stream->duration =
10746           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10747   }
10748
10749   /* configure segments */
10750   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10751     goto segments_failed;
10752
10753   /* add some language tag, if useful */
10754   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10755       strcmp (stream->lang_id, "und")) {
10756     const gchar *lang_code;
10757
10758     /* convert ISO 639-2 code to ISO 639-1 */
10759     lang_code = gst_tag_get_language_code (stream->lang_id);
10760     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10761         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10762   }
10763
10764   /* Check for UDTA tags */
10765   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10766     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10767   }
10768
10769   /* now we are ready to add the stream */
10770   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10771     goto too_many_streams;
10772
10773   if (!qtdemux->got_moov) {
10774     qtdemux->streams[qtdemux->n_streams] = stream;
10775     qtdemux->n_streams++;
10776     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10777   }
10778
10779   return TRUE;
10780
10781 /* ERRORS */
10782 skip_track:
10783   {
10784     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10785     if (new_stream)
10786       gst_qtdemux_stream_free (qtdemux, stream);
10787     return TRUE;
10788   }
10789 corrupt_file:
10790   {
10791     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10792         (_("This file is corrupt and cannot be played.")), (NULL));
10793     if (new_stream)
10794       gst_qtdemux_stream_free (qtdemux, stream);
10795     return FALSE;
10796   }
10797 error_encrypted:
10798   {
10799     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10800     if (new_stream)
10801       gst_qtdemux_stream_free (qtdemux, stream);
10802     return FALSE;
10803   }
10804 samples_failed:
10805 segments_failed:
10806   {
10807     /* we posted an error already */
10808     /* free stbl sub-atoms */
10809     gst_qtdemux_stbl_free (stream);
10810     if (new_stream)
10811       gst_qtdemux_stream_free (qtdemux, stream);
10812     return FALSE;
10813   }
10814 existing_stream:
10815   {
10816     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10817         track_id);
10818     if (new_stream)
10819       gst_qtdemux_stream_free (qtdemux, stream);
10820     return TRUE;
10821   }
10822 unknown_stream:
10823   {
10824     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10825         GST_FOURCC_ARGS (stream->subtype));
10826     if (new_stream)
10827       gst_qtdemux_stream_free (qtdemux, stream);
10828     return TRUE;
10829   }
10830 too_many_streams:
10831   {
10832     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10833         (_("This file contains too many streams. Only playing first %d"),
10834             GST_QTDEMUX_MAX_STREAMS), (NULL));
10835     return TRUE;
10836   }
10837 }
10838
10839 /* If we can estimate the overall bitrate, and don't have information about the
10840  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10841  * the overall bitrate minus the sum of the bitrates of all other streams. This
10842  * should be useful for the common case where we have one audio and one video
10843  * stream and can estimate the bitrate of one, but not the other. */
10844 static void
10845 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10846 {
10847   QtDemuxStream *stream = NULL;
10848   gint64 size, sys_bitrate, sum_bitrate = 0;
10849   GstClockTime duration;
10850   gint i;
10851   guint bitrate;
10852
10853   if (qtdemux->fragmented)
10854     return;
10855
10856   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10857
10858   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10859       || size <= 0) {
10860     GST_DEBUG_OBJECT (qtdemux,
10861         "Size in bytes of the stream not known - bailing");
10862     return;
10863   }
10864
10865   /* Subtract the header size */
10866   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10867       size, qtdemux->header_size);
10868
10869   if (size < qtdemux->header_size)
10870     return;
10871
10872   size = size - qtdemux->header_size;
10873
10874   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
10875     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10876     return;
10877   }
10878
10879   for (i = 0; i < qtdemux->n_streams; i++) {
10880     switch (qtdemux->streams[i]->subtype) {
10881       case FOURCC_soun:
10882       case FOURCC_vide:
10883         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10884             qtdemux->streams[i]->caps);
10885         /* retrieve bitrate, prefer avg then max */
10886         bitrate = 0;
10887         if (qtdemux->streams[i]->pending_tags) {
10888           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10889               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10890           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10891           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10892               GST_TAG_NOMINAL_BITRATE, &bitrate);
10893           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10894           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10895               GST_TAG_BITRATE, &bitrate);
10896           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10897         }
10898         if (bitrate)
10899           sum_bitrate += bitrate;
10900         else {
10901           if (stream) {
10902             GST_DEBUG_OBJECT (qtdemux,
10903                 ">1 stream with unknown bitrate - bailing");
10904             return;
10905           } else
10906             stream = qtdemux->streams[i];
10907         }
10908
10909       default:
10910         /* For other subtypes, we assume no significant impact on bitrate */
10911         break;
10912     }
10913   }
10914
10915   if (!stream) {
10916     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10917     return;
10918   }
10919
10920   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10921
10922   if (sys_bitrate < sum_bitrate) {
10923     /* This can happen, since sum_bitrate might be derived from maximum
10924      * bitrates and not average bitrates */
10925     GST_DEBUG_OBJECT (qtdemux,
10926         "System bitrate less than sum bitrate - bailing");
10927     return;
10928   }
10929
10930   bitrate = sys_bitrate - sum_bitrate;
10931   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10932       ", Stream bitrate = %u", sys_bitrate, bitrate);
10933
10934   if (!stream->pending_tags)
10935     stream->pending_tags = gst_tag_list_new_empty ();
10936
10937   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10938       GST_TAG_BITRATE, bitrate, NULL);
10939 }
10940
10941 static GstFlowReturn
10942 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10943 {
10944   gint i;
10945   GstFlowReturn ret = GST_FLOW_OK;
10946
10947   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10948
10949   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10950     QtDemuxStream *stream = qtdemux->streams[i];
10951     guint32 sample_num = 0;
10952
10953     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10954         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10955
10956     if (qtdemux->fragmented) {
10957       /* need all moov samples first */
10958       GST_OBJECT_LOCK (qtdemux);
10959       while (stream->n_samples == 0)
10960         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10961           break;
10962       GST_OBJECT_UNLOCK (qtdemux);
10963     } else {
10964       /* discard any stray moof */
10965       qtdemux->moof_offset = 0;
10966     }
10967
10968     /* prepare braking */
10969     if (ret != GST_FLOW_ERROR)
10970       ret = GST_FLOW_OK;
10971
10972     /* in pull mode, we should have parsed some sample info by now;
10973      * and quite some code will not handle no samples.
10974      * in push mode, we'll just have to deal with it */
10975     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10976       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10977       gst_qtdemux_remove_stream (qtdemux, i);
10978       i--;
10979       continue;
10980     }
10981
10982     /* parse the initial sample for use in setting the frame rate cap */
10983     while (sample_num == 0 && sample_num < stream->n_samples) {
10984       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10985         break;
10986       ++sample_num;
10987     }
10988     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
10989       stream->first_duration = stream->samples[0].duration;
10990       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
10991           stream->track_id, stream->first_duration);
10992     }
10993   }
10994
10995   return ret;
10996 }
10997
10998 static GstFlowReturn
10999 qtdemux_expose_streams (GstQTDemux * qtdemux)
11000 {
11001   gint i;
11002   GstFlowReturn ret = GST_FLOW_OK;
11003   GSList *oldpads = NULL;
11004   GSList *iter;
11005
11006   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11007
11008   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11009     QtDemuxStream *stream = qtdemux->streams[i];
11010     GstPad *oldpad = stream->pad;
11011     GstTagList *list;
11012
11013     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11014         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11015
11016     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11017         stream->track_id == qtdemux->chapters_track_id) {
11018       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11019          so that it doesn't look like a subtitle track */
11020       gst_qtdemux_remove_stream (qtdemux, i);
11021       i--;
11022       continue;
11023     }
11024
11025     /* now we have all info and can expose */
11026     list = stream->pending_tags;
11027     stream->pending_tags = NULL;
11028     if (oldpad)
11029       oldpads = g_slist_prepend (oldpads, oldpad);
11030     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11031       return GST_FLOW_ERROR;
11032   }
11033
11034   gst_qtdemux_guess_bitrate (qtdemux);
11035
11036   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11037
11038   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11039     GstPad *oldpad = iter->data;
11040     GstEvent *event;
11041
11042     event = gst_event_new_eos ();
11043     if (qtdemux->segment_seqnum)
11044       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11045
11046     gst_pad_push_event (oldpad, event);
11047     gst_pad_set_active (oldpad, FALSE);
11048     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11049     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11050     gst_object_unref (oldpad);
11051   }
11052
11053   /* check if we should post a redirect in case there is a single trak
11054    * and it is a redirecting trak */
11055   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11056     GstMessage *m;
11057
11058     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11059         "an external content");
11060     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11061         gst_structure_new ("redirect",
11062             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11063             NULL));
11064     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11065     qtdemux->posted_redirect = TRUE;
11066   }
11067
11068   for (i = 0; i < qtdemux->n_streams; i++) {
11069     QtDemuxStream *stream = qtdemux->streams[i];
11070
11071     qtdemux_do_allocation (qtdemux, stream);
11072   }
11073
11074   qtdemux->exposed = TRUE;
11075   return ret;
11076 }
11077
11078 /* check if major or compatible brand is 3GP */
11079 static inline gboolean
11080 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11081 {
11082   if (major) {
11083     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11084         FOURCC_3g__);
11085   } else if (qtdemux->comp_brands != NULL) {
11086     GstMapInfo map;
11087     guint8 *data;
11088     gsize size;
11089     gboolean res = FALSE;
11090
11091     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11092     data = map.data;
11093     size = map.size;
11094     while (size >= 4) {
11095       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11096           FOURCC_3g__);
11097       data += 4;
11098       size -= 4;
11099     }
11100     gst_buffer_unmap (qtdemux->comp_brands, &map);
11101     return res;
11102   } else {
11103     return FALSE;
11104   }
11105 }
11106
11107 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11108 static inline gboolean
11109 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11110 {
11111   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11112       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11113       || fourcc == FOURCC_albm;
11114 }
11115
11116 static void
11117 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11118     const char *tag, const char *dummy, GNode * node)
11119 {
11120   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11121   int offset;
11122   char *name;
11123   gchar *data;
11124   gdouble longitude, latitude, altitude;
11125   gint len;
11126
11127   len = QT_UINT32 (node->data);
11128   if (len <= 14)
11129     goto short_read;
11130
11131   data = node->data;
11132   offset = 14;
11133
11134   /* TODO: language code skipped */
11135
11136   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11137
11138   if (!name) {
11139     /* do not alarm in trivial case, but bail out otherwise */
11140     if (*(data + offset) != 0) {
11141       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11142           "giving up", tag);
11143     }
11144   } else {
11145     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11146         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11147     offset += strlen (name);
11148     g_free (name);
11149   }
11150
11151   if (len < offset + 2 + 4 + 4 + 4)
11152     goto short_read;
11153
11154   /* +1 +1 = skip null-terminator and location role byte */
11155   offset += 1 + 1;
11156   /* table in spec says unsigned, semantics say negative has meaning ... */
11157   longitude = QT_SFP32 (data + offset);
11158
11159   offset += 4;
11160   latitude = QT_SFP32 (data + offset);
11161
11162   offset += 4;
11163   altitude = QT_SFP32 (data + offset);
11164
11165   /* one invalid means all are invalid */
11166   if (longitude >= -180.0 && longitude <= 180.0 &&
11167       latitude >= -90.0 && latitude <= 90.0) {
11168     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11169         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11170         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11171         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11172   }
11173
11174   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11175
11176   return;
11177
11178   /* ERRORS */
11179 short_read:
11180   {
11181     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11182     return;
11183   }
11184 }
11185
11186
11187 static void
11188 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11189     const char *tag, const char *dummy, GNode * node)
11190 {
11191   guint16 y;
11192   GDate *date;
11193   gint len;
11194
11195   len = QT_UINT32 (node->data);
11196   if (len < 14)
11197     return;
11198
11199   y = QT_UINT16 ((guint8 *) node->data + 12);
11200   if (y == 0) {
11201     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11202     return;
11203   }
11204   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11205
11206   date = g_date_new_dmy (1, 1, y);
11207   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11208   g_date_free (date);
11209 }
11210
11211 static void
11212 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11213     const char *tag, const char *dummy, GNode * node)
11214 {
11215   int offset;
11216   char *tag_str = NULL;
11217   guint8 *entity;
11218   guint16 table;
11219   gint len;
11220
11221   len = QT_UINT32 (node->data);
11222   if (len <= 20)
11223     goto short_read;
11224
11225   offset = 12;
11226   entity = (guint8 *) node->data + offset;
11227   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11228     GST_DEBUG_OBJECT (qtdemux,
11229         "classification info: %c%c%c%c invalid classification entity",
11230         entity[0], entity[1], entity[2], entity[3]);
11231     return;
11232   }
11233
11234   offset += 4;
11235   table = QT_UINT16 ((guint8 *) node->data + offset);
11236
11237   /* Language code skipped */
11238
11239   offset += 4;
11240
11241   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11242    * XXXX: classification entity, fixed length 4 chars.
11243    * Y[YYYY]: classification table, max 5 chars.
11244    */
11245   tag_str = g_strdup_printf ("----://%u/%s",
11246       table, (char *) node->data + offset);
11247
11248   /* memcpy To be sure we're preserving byte order */
11249   memcpy (tag_str, entity, 4);
11250   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11251
11252   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11253
11254   g_free (tag_str);
11255
11256   return;
11257
11258   /* ERRORS */
11259 short_read:
11260   {
11261     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11262     return;
11263   }
11264 }
11265
11266 static gboolean
11267 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11268     const char *tag, const char *dummy, GNode * node)
11269 {
11270   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11271   GNode *data;
11272   char *s;
11273   int len;
11274   guint32 type;
11275   int offset;
11276   gboolean ret = TRUE;
11277   const gchar *charset = NULL;
11278
11279   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11280   if (data) {
11281     len = QT_UINT32 (data->data);
11282     type = QT_UINT32 ((guint8 *) data->data + 8);
11283     if (type == 0x00000001 && len > 16) {
11284       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11285           env_vars);
11286       if (s) {
11287         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11288         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11289         g_free (s);
11290       } else {
11291         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11292       }
11293     }
11294   } else {
11295     len = QT_UINT32 (node->data);
11296     type = QT_UINT32 ((guint8 *) node->data + 4);
11297     if ((type >> 24) == 0xa9) {
11298       gint str_len;
11299       gint lang_code;
11300
11301       /* Type starts with the (C) symbol, so the next data is a list
11302        * of (string size(16), language code(16), string) */
11303
11304       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11305       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11306
11307       /* the string + fourcc + size + 2 16bit fields,
11308        * means that there are more tags in this atom */
11309       if (len > str_len + 8 + 4) {
11310         /* TODO how to represent the same tag in different languages? */
11311         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11312             "text alternatives, reading only first one");
11313       }
11314
11315       offset = 12;
11316       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
11317       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11318
11319       if (lang_code < 0x800) {  /* MAC encoded string */
11320         charset = "mac";
11321       }
11322     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11323             QT_FOURCC ((guint8 *) node->data + 4))) {
11324       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11325
11326       /* we go for 3GP style encoding if major brands claims so,
11327        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11328       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11329           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11330               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11331         offset = 14;
11332         /* 16-bit Language code is ignored here as well */
11333         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11334       } else {
11335         goto normal;
11336       }
11337     } else {
11338     normal:
11339       offset = 8;
11340       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11341       ret = FALSE;              /* may have to fallback */
11342     }
11343     if (charset) {
11344       GError *err = NULL;
11345
11346       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11347           charset, NULL, NULL, &err);
11348       if (err) {
11349         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11350             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11351             err->message);
11352         g_error_free (err);
11353       }
11354     } else {
11355       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11356           len - offset, env_vars);
11357     }
11358     if (s) {
11359       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11360       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11361       g_free (s);
11362       ret = TRUE;
11363     } else {
11364       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11365     }
11366   }
11367   return ret;
11368 }
11369
11370 static void
11371 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11372     const char *tag, const char *dummy, GNode * node)
11373 {
11374   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11375 }
11376
11377 static void
11378 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11379     const char *tag, const char *dummy, GNode * node)
11380 {
11381   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11382   guint8 *data;
11383   char *s, *t, *k = NULL;
11384   int len;
11385   int offset;
11386   int count;
11387
11388   /* first try normal string tag if major brand not 3GP */
11389   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11390     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11391       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11392        * let's try it 3gpp way after minor safety check */
11393       data = node->data;
11394       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11395         return;
11396     } else
11397       return;
11398   }
11399
11400   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11401
11402   data = node->data;
11403
11404   len = QT_UINT32 (data);
11405   if (len < 15)
11406     goto short_read;
11407
11408   count = QT_UINT8 (data + 14);
11409   offset = 15;
11410   for (; count; count--) {
11411     gint slen;
11412
11413     if (offset + 1 > len)
11414       goto short_read;
11415     slen = QT_UINT8 (data + offset);
11416     offset += 1;
11417     if (offset + slen > len)
11418       goto short_read;
11419     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11420         slen, env_vars);
11421     if (s) {
11422       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11423       if (k) {
11424         t = g_strjoin (",", k, s, NULL);
11425         g_free (s);
11426         g_free (k);
11427         k = t;
11428       } else {
11429         k = s;
11430       }
11431     } else {
11432       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11433     }
11434     offset += slen;
11435   }
11436
11437 done:
11438   if (k) {
11439     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11440     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11441   }
11442   g_free (k);
11443
11444   return;
11445
11446   /* ERRORS */
11447 short_read:
11448   {
11449     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11450     goto done;
11451   }
11452 }
11453
11454 static void
11455 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11456     const char *tag1, const char *tag2, GNode * node)
11457 {
11458   GNode *data;
11459   int len;
11460   int type;
11461   int n1, n2;
11462
11463   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11464   if (data) {
11465     len = QT_UINT32 (data->data);
11466     type = QT_UINT32 ((guint8 *) data->data + 8);
11467     if (type == 0x00000000 && len >= 22) {
11468       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11469       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11470       if (n1 > 0) {
11471         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11472         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11473       }
11474       if (n2 > 0) {
11475         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11476         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11477       }
11478     }
11479   }
11480 }
11481
11482 static void
11483 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11484     const char *tag1, const char *dummy, GNode * node)
11485 {
11486   GNode *data;
11487   int len;
11488   int type;
11489   int n1;
11490
11491   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11492   if (data) {
11493     len = QT_UINT32 (data->data);
11494     type = QT_UINT32 ((guint8 *) data->data + 8);
11495     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11496     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11497     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11498       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11499       if (n1) {
11500         /* do not add bpm=0 */
11501         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11502         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11503             NULL);
11504       }
11505     }
11506   }
11507 }
11508
11509 static void
11510 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11511     const char *tag1, const char *dummy, GNode * node)
11512 {
11513   GNode *data;
11514   int len;
11515   int type;
11516   guint32 num;
11517
11518   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11519   if (data) {
11520     len = QT_UINT32 (data->data);
11521     type = QT_UINT32 ((guint8 *) data->data + 8);
11522     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11523     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11524     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11525       num = QT_UINT32 ((guint8 *) data->data + 16);
11526       if (num) {
11527         /* do not add num=0 */
11528         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11529         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11530       }
11531     }
11532   }
11533 }
11534
11535 static void
11536 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11537     const char *tag1, const char *dummy, GNode * node)
11538 {
11539   GNode *data;
11540   int len;
11541   int type;
11542   GstSample *sample;
11543
11544   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11545   if (data) {
11546     len = QT_UINT32 (data->data);
11547     type = QT_UINT32 ((guint8 *) data->data + 8);
11548     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11549     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11550       if ((sample =
11551               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11552                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11553         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11554         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11555         gst_sample_unref (sample);
11556       }
11557     }
11558   }
11559 }
11560
11561 static void
11562 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11563     const char *tag, const char *dummy, GNode * node)
11564 {
11565   GNode *data;
11566   char *s;
11567   int len;
11568   int type;
11569
11570   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11571   if (data) {
11572     len = QT_UINT32 (data->data);
11573     type = QT_UINT32 ((guint8 *) data->data + 8);
11574     if (type == 0x00000001 && len > 16) {
11575       guint y, m = 1, d = 1;
11576       gint ret;
11577
11578       s = g_strndup ((char *) data->data + 16, len - 16);
11579       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11580       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11581       if (ret >= 1 && y > 1500 && y < 3000) {
11582         GDate *date;
11583
11584         date = g_date_new_dmy (d, m, y);
11585         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11586         g_date_free (date);
11587       } else {
11588         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11589       }
11590       g_free (s);
11591     }
11592   }
11593 }
11594
11595 static void
11596 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11597     const char *tag, const char *dummy, GNode * node)
11598 {
11599   GNode *data;
11600
11601   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11602
11603   /* re-route to normal string tag if major brand says so
11604    * or no data atom and compatible brand suggests so */
11605   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11606       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11607     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11608     return;
11609   }
11610
11611   if (data) {
11612     guint len, type, n;
11613
11614     len = QT_UINT32 (data->data);
11615     type = QT_UINT32 ((guint8 *) data->data + 8);
11616     if (type == 0x00000000 && len >= 18) {
11617       n = QT_UINT16 ((guint8 *) data->data + 16);
11618       if (n > 0) {
11619         const gchar *genre;
11620
11621         genre = gst_tag_id3_genre_get (n - 1);
11622         if (genre != NULL) {
11623           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11624           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11625         }
11626       }
11627     }
11628   }
11629 }
11630
11631 static void
11632 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11633     const gchar * tag, guint8 * data, guint32 datasize)
11634 {
11635   gdouble value;
11636   gchar *datacopy;
11637
11638   /* make a copy to have \0 at the end */
11639   datacopy = g_strndup ((gchar *) data, datasize);
11640
11641   /* convert the str to double */
11642   if (sscanf (datacopy, "%lf", &value) == 1) {
11643     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11644     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11645   } else {
11646     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11647         datacopy);
11648   }
11649   g_free (datacopy);
11650 }
11651
11652
11653 static void
11654 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11655     const char *tag, const char *tag_bis, GNode * node)
11656 {
11657   GNode *mean;
11658   GNode *name;
11659   GNode *data;
11660   guint32 meansize;
11661   guint32 namesize;
11662   guint32 datatype;
11663   guint32 datasize;
11664   const gchar *meanstr;
11665   const gchar *namestr;
11666
11667   /* checking the whole ---- atom size for consistency */
11668   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11669     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11670     return;
11671   }
11672
11673   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11674   if (!mean) {
11675     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11676     return;
11677   }
11678
11679   meansize = QT_UINT32 (mean->data);
11680   if (meansize <= 12) {
11681     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11682     return;
11683   }
11684   meanstr = ((gchar *) mean->data) + 12;
11685   meansize -= 12;
11686
11687   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11688   if (!name) {
11689     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11690     return;
11691   }
11692
11693   namesize = QT_UINT32 (name->data);
11694   if (namesize <= 12) {
11695     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11696     return;
11697   }
11698   namestr = ((gchar *) name->data) + 12;
11699   namesize -= 12;
11700
11701   /*
11702    * Data atom is:
11703    * uint32 - size
11704    * uint32 - name
11705    * uint8  - version
11706    * uint24 - data type
11707    * uint32 - all 0
11708    * rest   - the data
11709    */
11710   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11711   if (!data) {
11712     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11713     return;
11714   }
11715   datasize = QT_UINT32 (data->data);
11716   if (datasize <= 16) {
11717     GST_WARNING_OBJECT (demux, "Data atom too small");
11718     return;
11719   }
11720   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11721
11722   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11723       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11724     static const struct
11725     {
11726       const gchar name[28];
11727       const gchar tag[28];
11728     } tags[] = {
11729       {
11730       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11731       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11732       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11733       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11734       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11735       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11736       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11737       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11738     };
11739     int i;
11740
11741     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11742       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11743         switch (gst_tag_get_type (tags[i].tag)) {
11744           case G_TYPE_DOUBLE:
11745             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11746                 ((guint8 *) data->data) + 16, datasize - 16);
11747             break;
11748           case G_TYPE_STRING:
11749             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11750             break;
11751           default:
11752             /* not reached */
11753             break;
11754         }
11755         break;
11756       }
11757     }
11758     if (i == G_N_ELEMENTS (tags))
11759       goto unknown_tag;
11760   } else {
11761     goto unknown_tag;
11762   }
11763
11764   return;
11765
11766 /* errors */
11767 unknown_tag:
11768 #ifndef GST_DISABLE_GST_DEBUG
11769   {
11770     gchar *namestr_dbg;
11771     gchar *meanstr_dbg;
11772
11773     meanstr_dbg = g_strndup (meanstr, meansize);
11774     namestr_dbg = g_strndup (namestr, namesize);
11775
11776     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11777         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11778
11779     g_free (namestr_dbg);
11780     g_free (meanstr_dbg);
11781   }
11782 #endif
11783   return;
11784 }
11785
11786 static void
11787 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11788     const char *tag_bis, GNode * node)
11789 {
11790   guint8 *data;
11791   GstBuffer *buf;
11792   guint len;
11793   GstTagList *id32_taglist = NULL;
11794
11795   GST_LOG_OBJECT (demux, "parsing ID32");
11796
11797   data = node->data;
11798   len = GST_READ_UINT32_BE (data);
11799
11800   /* need at least full box and language tag */
11801   if (len < 12 + 2)
11802     return;
11803
11804   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11805   gst_buffer_fill (buf, 0, data + 14, len - 14);
11806
11807   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11808   if (id32_taglist) {
11809     GST_LOG_OBJECT (demux, "parsing ok");
11810     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11811     gst_tag_list_unref (id32_taglist);
11812   } else {
11813     GST_LOG_OBJECT (demux, "parsing failed");
11814   }
11815
11816   gst_buffer_unref (buf);
11817 }
11818
11819 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11820     const char *tag, const char *tag_bis, GNode * node);
11821
11822 /* unmapped tags
11823 FOURCC_pcst -> if media is a podcast -> bool
11824 FOURCC_cpil -> if media is part of a compilation -> bool
11825 FOURCC_pgap -> if media is part of a gapless context -> bool
11826 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11827 */
11828
11829 static const struct
11830 {
11831   guint32 fourcc;
11832   const gchar *gst_tag;
11833   const gchar *gst_tag_bis;
11834   const GstQTDemuxAddTagFunc func;
11835 } add_funcs[] = {
11836   {
11837   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11838   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11839   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11840   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11841   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11842   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11843   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11844   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11845   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11846   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11847   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11848   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11849   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11850   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11851   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11852   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11853   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11854   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11855   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11856   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11857   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11858   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11859   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11860         qtdemux_tag_add_num}, {
11861   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11862         qtdemux_tag_add_num}, {
11863   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11864   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11865   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11866   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11867   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11868   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11869   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11870   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11871   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11872   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11873   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11874   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11875   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11876   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11877   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11878   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11879   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11880   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11881         qtdemux_tag_add_classification}, {
11882   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11883   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11884   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11885
11886     /* This is a special case, some tags are stored in this
11887      * 'reverse dns naming', according to:
11888      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11889      * bug #614471
11890      */
11891   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11892     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11893   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11894 };
11895
11896 struct _GstQtDemuxTagList
11897 {
11898   GstQTDemux *demux;
11899   GstTagList *taglist;
11900 };
11901 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11902
11903 static void
11904 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11905 {
11906   gint len;
11907   guint8 *data;
11908   GstBuffer *buf;
11909   gchar *media_type;
11910   const gchar *style;
11911   GstSample *sample;
11912   GstStructure *s;
11913   guint i;
11914   guint8 ndata[4];
11915   GstQTDemux *demux = qtdemuxtaglist->demux;
11916   GstTagList *taglist = qtdemuxtaglist->taglist;
11917
11918   data = node->data;
11919   len = QT_UINT32 (data);
11920   buf = gst_buffer_new_and_alloc (len);
11921   gst_buffer_fill (buf, 0, data, len);
11922
11923   /* heuristic to determine style of tag */
11924   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11925       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11926     style = "itunes";
11927   else if (demux->major_brand == FOURCC_qt__)
11928     style = "quicktime";
11929   /* fall back to assuming iso/3gp tag style */
11930   else
11931     style = "iso";
11932
11933   /* santize the name for the caps. */
11934   for (i = 0; i < 4; i++) {
11935     guint8 d = data[4 + i];
11936     if (g_ascii_isalnum (d))
11937       ndata[i] = g_ascii_tolower (d);
11938     else
11939       ndata[i] = '_';
11940   }
11941
11942   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11943       ndata[0], ndata[1], ndata[2], ndata[3]);
11944   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11945
11946   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11947   sample = gst_sample_new (buf, NULL, NULL, s);
11948   gst_buffer_unref (buf);
11949   g_free (media_type);
11950
11951   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11952       len, s);
11953
11954   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11955       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11956
11957   gst_sample_unref (sample);
11958 }
11959
11960 static void
11961 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11962 {
11963   GNode *meta;
11964   GNode *ilst;
11965   GNode *xmp_;
11966   GNode *node;
11967   gint i;
11968   GstQtDemuxTagList demuxtaglist;
11969
11970   demuxtaglist.demux = qtdemux;
11971   demuxtaglist.taglist = taglist;
11972
11973   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11974   if (meta != NULL) {
11975     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11976     if (ilst == NULL) {
11977       GST_LOG_OBJECT (qtdemux, "no ilst");
11978       return;
11979     }
11980   } else {
11981     ilst = udta;
11982     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11983   }
11984
11985   i = 0;
11986   while (i < G_N_ELEMENTS (add_funcs)) {
11987     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
11988     if (node) {
11989       gint len;
11990
11991       len = QT_UINT32 (node->data);
11992       if (len < 12) {
11993         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
11994             GST_FOURCC_ARGS (add_funcs[i].fourcc));
11995       } else {
11996         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
11997             add_funcs[i].gst_tag_bis, node);
11998       }
11999       g_node_destroy (node);
12000     } else {
12001       i++;
12002     }
12003   }
12004
12005   /* parsed nodes have been removed, pass along remainder as blob */
12006   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12007       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12008
12009   /* parse up XMP_ node if existing */
12010   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12011   if (xmp_ != NULL) {
12012     GstBuffer *buf;
12013     GstTagList *xmptaglist;
12014
12015     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12016         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12017     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12018     gst_buffer_unref (buf);
12019
12020     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12021   } else {
12022     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12023   }
12024 }
12025
12026 typedef struct
12027 {
12028   GstStructure *structure;      /* helper for sort function */
12029   gchar *location;
12030   guint min_req_bitrate;
12031   guint min_req_qt_version;
12032 } GstQtReference;
12033
12034 static gint
12035 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12036 {
12037   GstQtReference *ref_a = (GstQtReference *) a;
12038   GstQtReference *ref_b = (GstQtReference *) b;
12039
12040   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12041     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12042
12043   /* known bitrates go before unknown; higher bitrates go first */
12044   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12045 }
12046
12047 /* sort the redirects and post a message for the application.
12048  */
12049 static void
12050 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12051 {
12052   GstQtReference *best;
12053   GstStructure *s;
12054   GstMessage *msg;
12055   GValue list_val = { 0, };
12056   GList *l;
12057
12058   g_assert (references != NULL);
12059
12060   references = g_list_sort (references, qtdemux_redirects_sort_func);
12061
12062   best = (GstQtReference *) references->data;
12063
12064   g_value_init (&list_val, GST_TYPE_LIST);
12065
12066   for (l = references; l != NULL; l = l->next) {
12067     GstQtReference *ref = (GstQtReference *) l->data;
12068     GValue struct_val = { 0, };
12069
12070     ref->structure = gst_structure_new ("redirect",
12071         "new-location", G_TYPE_STRING, ref->location, NULL);
12072
12073     if (ref->min_req_bitrate > 0) {
12074       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12075           ref->min_req_bitrate, NULL);
12076     }
12077
12078     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12079     g_value_set_boxed (&struct_val, ref->structure);
12080     gst_value_list_append_value (&list_val, &struct_val);
12081     g_value_unset (&struct_val);
12082     /* don't free anything here yet, since we need best->structure below */
12083   }
12084
12085   g_assert (best != NULL);
12086   s = gst_structure_copy (best->structure);
12087
12088   if (g_list_length (references) > 1) {
12089     gst_structure_set_value (s, "locations", &list_val);
12090   }
12091
12092   g_value_unset (&list_val);
12093
12094   for (l = references; l != NULL; l = l->next) {
12095     GstQtReference *ref = (GstQtReference *) l->data;
12096
12097     gst_structure_free (ref->structure);
12098     g_free (ref->location);
12099     g_free (ref);
12100   }
12101   g_list_free (references);
12102
12103   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12104   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12105   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12106   qtdemux->posted_redirect = TRUE;
12107 }
12108
12109 /* look for redirect nodes, collect all redirect information and
12110  * process it.
12111  */
12112 static gboolean
12113 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12114 {
12115   GNode *rmra, *rmda, *rdrf;
12116
12117   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12118   if (rmra) {
12119     GList *redirects = NULL;
12120
12121     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12122     while (rmda) {
12123       GstQtReference ref = { NULL, NULL, 0, 0 };
12124       GNode *rmdr, *rmvc;
12125
12126       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12127         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12128         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12129             ref.min_req_bitrate);
12130       }
12131
12132       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12133         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12134         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12135
12136 #ifndef GST_DISABLE_GST_DEBUG
12137         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12138 #endif
12139         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12140
12141         GST_LOG_OBJECT (qtdemux,
12142             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12143             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12144             bitmask, check_type);
12145         if (package == FOURCC_qtim && check_type == 0) {
12146           ref.min_req_qt_version = version;
12147         }
12148       }
12149
12150       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12151       if (rdrf) {
12152         guint32 ref_type;
12153         guint8 *ref_data;
12154         guint ref_len;
12155
12156         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12157         if (ref_len > 20) {
12158           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12159           ref_data = (guint8 *) rdrf->data + 20;
12160           if (ref_type == FOURCC_alis) {
12161             guint record_len, record_version, fn_len;
12162
12163             if (ref_len > 70) {
12164               /* MacOSX alias record, google for alias-layout.txt */
12165               record_len = QT_UINT16 (ref_data + 4);
12166               record_version = QT_UINT16 (ref_data + 4 + 2);
12167               fn_len = QT_UINT8 (ref_data + 50);
12168               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12169                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12170               }
12171             } else {
12172               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12173                   ref_len);
12174             }
12175           } else if (ref_type == FOURCC_url_) {
12176             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12177           } else {
12178             GST_DEBUG_OBJECT (qtdemux,
12179                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12180                 GST_FOURCC_ARGS (ref_type));
12181           }
12182           if (ref.location != NULL) {
12183             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12184             redirects =
12185                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12186           } else {
12187             GST_WARNING_OBJECT (qtdemux,
12188                 "Failed to extract redirect location from rdrf atom");
12189           }
12190         } else {
12191           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12192         }
12193       }
12194
12195       /* look for others */
12196       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12197     }
12198
12199     if (redirects != NULL) {
12200       qtdemux_process_redirects (qtdemux, redirects);
12201     }
12202   }
12203   return TRUE;
12204 }
12205
12206 static GstTagList *
12207 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12208 {
12209   const gchar *fmt;
12210
12211   if (tags == NULL) {
12212     tags = gst_tag_list_new_empty ();
12213     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12214   }
12215
12216   if (qtdemux->major_brand == FOURCC_mjp2)
12217     fmt = "Motion JPEG 2000";
12218   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12219     fmt = "3GP";
12220   else if (qtdemux->major_brand == FOURCC_qt__)
12221     fmt = "Quicktime";
12222   else if (qtdemux->fragmented)
12223     fmt = "ISO fMP4";
12224   else
12225     fmt = "ISO MP4/M4A";
12226
12227   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12228       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12229
12230   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12231       fmt, NULL);
12232
12233   return tags;
12234 }
12235
12236 /* we have read the complete moov node now.
12237  * This function parses all of the relevant info, creates the traks and
12238  * prepares all data structures for playback
12239  */
12240 static gboolean
12241 qtdemux_parse_tree (GstQTDemux * qtdemux)
12242 {
12243   GNode *mvhd;
12244   GNode *trak;
12245   GNode *udta;
12246   GNode *mvex;
12247   GstClockTime duration;
12248   GNode *pssh;
12249   guint64 creation_time;
12250   GstDateTime *datetime = NULL;
12251   gint version;
12252
12253   /* make sure we have a usable taglist */
12254   if (!qtdemux->tag_list) {
12255     qtdemux->tag_list = gst_tag_list_new_empty ();
12256     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12257   } else {
12258     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12259   }
12260
12261   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12262   if (mvhd == NULL) {
12263     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12264     return qtdemux_parse_redirects (qtdemux);
12265   }
12266
12267   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12268   if (version == 1) {
12269     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12270     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12271     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12272   } else if (version == 0) {
12273     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12274     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12275     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12276   } else {
12277     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12278     return FALSE;
12279   }
12280
12281   /* Moving qt creation time (secs since 1904) to unix time */
12282   if (creation_time != 0) {
12283     /* Try to use epoch first as it should be faster and more commonly found */
12284     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12285       GTimeVal now;
12286
12287       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12288       /* some data cleansing sanity */
12289       g_get_current_time (&now);
12290       if (now.tv_sec + 24 * 3600 < creation_time) {
12291         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12292       } else {
12293         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12294       }
12295     } else {
12296       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12297       GDateTime *dt, *dt_local;
12298
12299       dt = g_date_time_add_seconds (base_dt, creation_time);
12300       dt_local = g_date_time_to_local (dt);
12301       datetime = gst_date_time_new_from_g_date_time (dt_local);
12302
12303       g_date_time_unref (base_dt);
12304       g_date_time_unref (dt);
12305     }
12306   }
12307   if (datetime) {
12308     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12309     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12310         datetime, NULL);
12311     gst_date_time_unref (datetime);
12312   }
12313
12314   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12315   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12316
12317   /* check for fragmented file and get some (default) data */
12318   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12319   if (mvex) {
12320     GNode *mehd;
12321     GstByteReader mehd_data;
12322
12323     /* let track parsing or anyone know weird stuff might happen ... */
12324     qtdemux->fragmented = TRUE;
12325
12326     /* compensate for total duration */
12327     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12328     if (mehd)
12329       qtdemux_parse_mehd (qtdemux, &mehd_data);
12330   }
12331
12332   /* set duration in the segment info */
12333   gst_qtdemux_get_duration (qtdemux, &duration);
12334   if (duration) {
12335     qtdemux->segment.duration = duration;
12336     /* also do not exceed duration; stop is set that way post seek anyway,
12337      * and segment activation falls back to duration,
12338      * whereas loop only checks stop, so let's align this here as well */
12339     qtdemux->segment.stop = duration;
12340   }
12341
12342   /* parse all traks */
12343   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12344   while (trak) {
12345     qtdemux_parse_trak (qtdemux, trak);
12346     /* iterate all siblings */
12347     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12348   }
12349
12350   if (!qtdemux->tag_list) {
12351     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12352     qtdemux->tag_list = gst_tag_list_new_empty ();
12353     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12354   } else {
12355     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12356   }
12357
12358   /* find tags */
12359   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12360   if (udta) {
12361     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12362   } else {
12363     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12364   }
12365
12366   /* maybe also some tags in meta box */
12367   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12368   if (udta) {
12369     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12370     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12371   } else {
12372     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12373   }
12374
12375   /* parse any protection system info */
12376   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12377   while (pssh) {
12378     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12379     qtdemux_parse_pssh (qtdemux, pssh);
12380     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12381   }
12382
12383   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12384
12385   return TRUE;
12386 }
12387
12388 /* taken from ffmpeg */
12389 static int
12390 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12391 {
12392   int count = 4;
12393   int len = 0;
12394
12395   while (count--) {
12396     int c;
12397
12398     if (ptr >= end)
12399       return -1;
12400
12401     c = *ptr++;
12402     len = (len << 7) | (c & 0x7f);
12403     if (!(c & 0x80))
12404       break;
12405   }
12406   *end_out = ptr;
12407   return len;
12408 }
12409
12410 /* this can change the codec originally present in @list */
12411 static void
12412 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12413     GNode * esds, GstTagList * list)
12414 {
12415   int len = QT_UINT32 (esds->data);
12416   guint8 *ptr = esds->data;
12417   guint8 *end = ptr + len;
12418   int tag;
12419   guint8 *data_ptr = NULL;
12420   int data_len = 0;
12421   guint8 object_type_id = 0;
12422   const char *codec_name = NULL;
12423   GstCaps *caps = NULL;
12424
12425   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12426   ptr += 8;
12427   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12428   ptr += 4;
12429   while (ptr + 1 < end) {
12430     tag = QT_UINT8 (ptr);
12431     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12432     ptr++;
12433     len = read_descr_size (ptr, end, &ptr);
12434     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12435
12436     /* Check the stated amount of data is available for reading */
12437     if (len < 0 || ptr + len > end)
12438       break;
12439
12440     switch (tag) {
12441       case ES_DESCRIPTOR_TAG:
12442         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12443         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12444         ptr += 3;
12445         break;
12446       case DECODER_CONFIG_DESC_TAG:{
12447         guint max_bitrate, avg_bitrate;
12448
12449         object_type_id = QT_UINT8 (ptr);
12450         max_bitrate = QT_UINT32 (ptr + 5);
12451         avg_bitrate = QT_UINT32 (ptr + 9);
12452         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12453         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12454         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12455         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12456         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12457         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12458           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12459               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12460         }
12461         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12462           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12463               avg_bitrate, NULL);
12464         }
12465         ptr += 13;
12466         break;
12467       }
12468       case DECODER_SPECIFIC_INFO_TAG:
12469         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12470         if (object_type_id == 0xe0 && len == 0x40) {
12471           guint8 *data;
12472           GstStructure *s;
12473           guint32 clut[16];
12474           gint i;
12475
12476           GST_DEBUG_OBJECT (qtdemux,
12477               "Have VOBSUB palette. Creating palette event");
12478           /* move to decConfigDescr data and read palette */
12479           data = ptr;
12480           for (i = 0; i < 16; i++) {
12481             clut[i] = QT_UINT32 (data);
12482             data += 4;
12483           }
12484
12485           s = gst_structure_new ("application/x-gst-dvd", "event",
12486               G_TYPE_STRING, "dvd-spu-clut-change",
12487               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12488               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12489               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12490               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12491               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12492               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12493               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12494               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12495               NULL);
12496
12497           /* store event and trigger custom processing */
12498           stream->pending_event =
12499               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12500         } else {
12501           /* Generic codec_data handler puts it on the caps */
12502           data_ptr = ptr;
12503           data_len = len;
12504         }
12505
12506         ptr += len;
12507         break;
12508       case SL_CONFIG_DESC_TAG:
12509         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12510         ptr += 1;
12511         break;
12512       default:
12513         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12514             tag);
12515         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12516         ptr += len;
12517         break;
12518     }
12519   }
12520
12521   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12522    * in use, and should also be used to override some other parameters for some
12523    * codecs. */
12524   switch (object_type_id) {
12525     case 0x20:                 /* MPEG-4 */
12526       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12527        * profile_and_level_indication */
12528       if (data_ptr != NULL && data_len >= 5 &&
12529           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12530         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12531             data_ptr + 4, data_len - 4);
12532       }
12533       break;                    /* Nothing special needed here */
12534     case 0x21:                 /* H.264 */
12535       codec_name = "H.264 / AVC";
12536       caps = gst_caps_new_simple ("video/x-h264",
12537           "stream-format", G_TYPE_STRING, "avc",
12538           "alignment", G_TYPE_STRING, "au", NULL);
12539       break;
12540     case 0x40:                 /* AAC (any) */
12541     case 0x66:                 /* AAC Main */
12542     case 0x67:                 /* AAC LC */
12543     case 0x68:                 /* AAC SSR */
12544       /* Override channels and rate based on the codec_data, as it's often
12545        * wrong. */
12546       /* Only do so for basic setup without HE-AAC extension */
12547       if (data_ptr && data_len == 2) {
12548         guint channels, rate;
12549
12550         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
12551         if (channels > 0)
12552           stream->n_channels = channels;
12553
12554         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
12555         if (rate > 0)
12556           stream->rate = rate;
12557       }
12558
12559       /* Set level and profile if possible */
12560       if (data_ptr != NULL && data_len >= 2) {
12561         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12562             data_ptr, data_len);
12563       }
12564       break;
12565     case 0x60:                 /* MPEG-2, various profiles */
12566     case 0x61:
12567     case 0x62:
12568     case 0x63:
12569     case 0x64:
12570     case 0x65:
12571       codec_name = "MPEG-2 video";
12572       caps = gst_caps_new_simple ("video/mpeg",
12573           "mpegversion", G_TYPE_INT, 2,
12574           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12575       break;
12576     case 0x69:                 /* MPEG-2 BC audio */
12577     case 0x6B:                 /* MPEG-1 audio */
12578       caps = gst_caps_new_simple ("audio/mpeg",
12579           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12580       codec_name = "MPEG-1 audio";
12581       break;
12582     case 0x6A:                 /* MPEG-1 */
12583       codec_name = "MPEG-1 video";
12584       caps = gst_caps_new_simple ("video/mpeg",
12585           "mpegversion", G_TYPE_INT, 1,
12586           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12587       break;
12588     case 0x6C:                 /* MJPEG */
12589       caps =
12590           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12591           NULL);
12592       codec_name = "Motion-JPEG";
12593       break;
12594     case 0x6D:                 /* PNG */
12595       caps =
12596           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12597           NULL);
12598       codec_name = "PNG still images";
12599       break;
12600     case 0x6E:                 /* JPEG2000 */
12601       codec_name = "JPEG-2000";
12602       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12603       break;
12604     case 0xA4:                 /* Dirac */
12605       codec_name = "Dirac";
12606       caps = gst_caps_new_empty_simple ("video/x-dirac");
12607       break;
12608     case 0xA5:                 /* AC3 */
12609       codec_name = "AC-3 audio";
12610       caps = gst_caps_new_simple ("audio/x-ac3",
12611           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12612       break;
12613     case 0xA9:                 /* AC3 */
12614       codec_name = "DTS audio";
12615       caps = gst_caps_new_simple ("audio/x-dts",
12616           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12617       break;
12618     case 0xE1:                 /* QCELP */
12619       /* QCELP, the codec_data is a riff tag (little endian) with
12620        * 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). */
12621       caps = gst_caps_new_empty_simple ("audio/qcelp");
12622       codec_name = "QCELP";
12623       break;
12624     default:
12625       break;
12626   }
12627
12628   /* If we have a replacement caps, then change our caps for this stream */
12629   if (caps) {
12630     gst_caps_unref (stream->caps);
12631     stream->caps = caps;
12632   }
12633
12634   if (codec_name && list)
12635     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12636         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12637
12638   /* Add the codec_data attribute to caps, if we have it */
12639   if (data_ptr) {
12640     GstBuffer *buffer;
12641
12642     buffer = gst_buffer_new_and_alloc (data_len);
12643     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12644
12645     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12646     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12647
12648     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12649         buffer, NULL);
12650     gst_buffer_unref (buffer);
12651   }
12652
12653 }
12654
12655 #define _codec(name) \
12656   do { \
12657     if (codec_name) { \
12658       *codec_name = g_strdup (name); \
12659     } \
12660   } while (0)
12661
12662 static GstCaps *
12663 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12664     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12665 {
12666   GstCaps *caps = NULL;
12667   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12668
12669   switch (fourcc) {
12670     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12671       _codec ("PNG still images");
12672       caps = gst_caps_new_empty_simple ("image/png");
12673       break;
12674     case FOURCC_jpeg:
12675       _codec ("JPEG still images");
12676       caps =
12677           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12678           NULL);
12679       break;
12680     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12681     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12682     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12683     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12684       _codec ("Motion-JPEG");
12685       caps =
12686           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12687           NULL);
12688       break;
12689     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12690       _codec ("Motion-JPEG format B");
12691       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12692       break;
12693     case FOURCC_mjp2:
12694       _codec ("JPEG-2000");
12695       /* override to what it should be according to spec, avoid palette_data */
12696       stream->bits_per_sample = 24;
12697       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12698       break;
12699     case FOURCC_SVQ3:
12700       _codec ("Sorensen video v.3");
12701       caps = gst_caps_new_simple ("video/x-svq",
12702           "svqversion", G_TYPE_INT, 3, NULL);
12703       break;
12704     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12705     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12706       _codec ("Sorensen video v.1");
12707       caps = gst_caps_new_simple ("video/x-svq",
12708           "svqversion", G_TYPE_INT, 1, NULL);
12709       break;
12710     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12711       caps = gst_caps_new_empty_simple ("video/x-raw");
12712       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12713       _codec ("Windows Raw RGB");
12714       break;
12715     case FOURCC_raw_:
12716     {
12717       guint16 bps;
12718
12719       bps = QT_UINT16 (stsd_data + 98);
12720       switch (bps) {
12721         case 15:
12722           format = GST_VIDEO_FORMAT_RGB15;
12723           break;
12724         case 16:
12725           format = GST_VIDEO_FORMAT_RGB16;
12726           break;
12727         case 24:
12728           format = GST_VIDEO_FORMAT_RGB;
12729           break;
12730         case 32:
12731           format = GST_VIDEO_FORMAT_ARGB;
12732           break;
12733         default:
12734           /* unknown */
12735           break;
12736       }
12737       break;
12738     }
12739     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12740       format = GST_VIDEO_FORMAT_I420;
12741       break;
12742     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12743     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12744       format = GST_VIDEO_FORMAT_I420;
12745       break;
12746     case FOURCC_2vuy:
12747     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12748       format = GST_VIDEO_FORMAT_UYVY;
12749       break;
12750     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12751       format = GST_VIDEO_FORMAT_v308;
12752       break;
12753     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12754       format = GST_VIDEO_FORMAT_v216;
12755       break;
12756     case FOURCC_v210:
12757       format = GST_VIDEO_FORMAT_v210;
12758       break;
12759     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12760       format = GST_VIDEO_FORMAT_r210;
12761       break;
12762       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12763          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12764          format = GST_VIDEO_FORMAT_v410;
12765          break;
12766        */
12767       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12768        * but different order than AYUV
12769        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12770        format = GST_VIDEO_FORMAT_v408;
12771        break;
12772        */
12773     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12774     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12775       _codec ("MPEG-1 video");
12776       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12777           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12778       break;
12779     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12780     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12781     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12782     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12783     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12784     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12785     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12786     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12787     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12788     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12789     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12790     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12791     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12792     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12793     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12794     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12795     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12796     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12797     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12798     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12799     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12800     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12801     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12802     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12803     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12804     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12805     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12806     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12807     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12808     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12809     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12810     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12811     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12812     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12813     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12814     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12815     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12816     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12817     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12818     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12819     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12820     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12821     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12822     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12823     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12824     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12825       _codec ("MPEG-2 video");
12826       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12827           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12828       break;
12829     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12830       _codec ("GIF still images");
12831       caps = gst_caps_new_empty_simple ("image/gif");
12832       break;
12833     case FOURCC_h263:
12834     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12835     case FOURCC_s263:
12836     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12837       _codec ("H.263");
12838       /* ffmpeg uses the height/width props, don't know why */
12839       caps = gst_caps_new_simple ("video/x-h263",
12840           "variant", G_TYPE_STRING, "itu", NULL);
12841       break;
12842     case FOURCC_mp4v:
12843     case FOURCC_MP4V:
12844       _codec ("MPEG-4 video");
12845       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12846           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12847       break;
12848     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12849     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12850       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12851       caps = gst_caps_new_simple ("video/x-msmpeg",
12852           "msmpegversion", G_TYPE_INT, 43, NULL);
12853       break;
12854     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12855       _codec ("DivX 3");
12856       caps = gst_caps_new_simple ("video/x-divx",
12857           "divxversion", G_TYPE_INT, 3, NULL);
12858       break;
12859     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12860     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12861       _codec ("DivX 4");
12862       caps = gst_caps_new_simple ("video/x-divx",
12863           "divxversion", G_TYPE_INT, 4, NULL);
12864       break;
12865     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12866       _codec ("DivX 5");
12867       caps = gst_caps_new_simple ("video/x-divx",
12868           "divxversion", G_TYPE_INT, 5, NULL);
12869       break;
12870
12871     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
12872       _codec ("FFV1");
12873       caps = gst_caps_new_simple ("video/x-ffv",
12874           "ffvversion", G_TYPE_INT, 1, NULL);
12875       break;
12876
12877     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12878     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12879     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12880     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12881     case FOURCC_FMP4:
12882     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12883       caps = gst_caps_new_simple ("video/mpeg",
12884           "mpegversion", G_TYPE_INT, 4, NULL);
12885       _codec ("MPEG-4");
12886       break;
12887
12888     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12889       _codec ("Cinepak");
12890       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12891       break;
12892     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12893       _codec ("Apple QuickDraw");
12894       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12895       break;
12896     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12897       _codec ("Apple video");
12898       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12899       break;
12900     case FOURCC_H264:
12901     case FOURCC_avc1:
12902       _codec ("H.264 / AVC");
12903       caps = gst_caps_new_simple ("video/x-h264",
12904           "stream-format", G_TYPE_STRING, "avc",
12905           "alignment", G_TYPE_STRING, "au", NULL);
12906       break;
12907     case FOURCC_avc3:
12908       _codec ("H.264 / AVC");
12909       caps = gst_caps_new_simple ("video/x-h264",
12910           "stream-format", G_TYPE_STRING, "avc3",
12911           "alignment", G_TYPE_STRING, "au", NULL);
12912       break;
12913     case FOURCC_H265:
12914     case FOURCC_hvc1:
12915       _codec ("H.265 / HEVC");
12916       caps = gst_caps_new_simple ("video/x-h265",
12917           "stream-format", G_TYPE_STRING, "hvc1",
12918           "alignment", G_TYPE_STRING, "au", NULL);
12919       break;
12920     case FOURCC_hev1:
12921       _codec ("H.265 / HEVC");
12922       caps = gst_caps_new_simple ("video/x-h265",
12923           "stream-format", G_TYPE_STRING, "hev1",
12924           "alignment", G_TYPE_STRING, "au", NULL);
12925       break;
12926     case FOURCC_rle_:
12927       _codec ("Run-length encoding");
12928       caps = gst_caps_new_simple ("video/x-rle",
12929           "layout", G_TYPE_STRING, "quicktime", NULL);
12930       break;
12931     case FOURCC_WRLE:
12932       _codec ("Run-length encoding");
12933       caps = gst_caps_new_simple ("video/x-rle",
12934           "layout", G_TYPE_STRING, "microsoft", NULL);
12935       break;
12936     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12937     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12938       _codec ("Indeo Video 3");
12939       caps = gst_caps_new_simple ("video/x-indeo",
12940           "indeoversion", G_TYPE_INT, 3, NULL);
12941       break;
12942     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12943     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12944       _codec ("Intel Video 4");
12945       caps = gst_caps_new_simple ("video/x-indeo",
12946           "indeoversion", G_TYPE_INT, 4, NULL);
12947       break;
12948     case FOURCC_dvcp:
12949     case FOURCC_dvc_:
12950     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12951     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12952     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12953     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12954     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12955     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12956       _codec ("DV Video");
12957       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12958           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12959       break;
12960     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
12961     case FOURCC_dv5p:          /* DVCPRO50 PAL */
12962       _codec ("DVCPro50 Video");
12963       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12964           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12965       break;
12966     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12967     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12968       _codec ("DVCProHD Video");
12969       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12970           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12971       break;
12972     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12973       _codec ("Apple Graphics (SMC)");
12974       caps = gst_caps_new_empty_simple ("video/x-smc");
12975       break;
12976     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12977       _codec ("VP3");
12978       caps = gst_caps_new_empty_simple ("video/x-vp3");
12979       break;
12980     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12981       _codec ("VP6 Flash");
12982       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12983       break;
12984     case FOURCC_XiTh:
12985       _codec ("Theora");
12986       caps = gst_caps_new_empty_simple ("video/x-theora");
12987       /* theora uses one byte of padding in the data stream because it does not
12988        * allow 0 sized packets while theora does */
12989       stream->padding = 1;
12990       break;
12991     case FOURCC_drac:
12992       _codec ("Dirac");
12993       caps = gst_caps_new_empty_simple ("video/x-dirac");
12994       break;
12995     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
12996       _codec ("TIFF still images");
12997       caps = gst_caps_new_empty_simple ("image/tiff");
12998       break;
12999     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13000       _codec ("Apple Intermediate Codec");
13001       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13002       break;
13003     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13004       _codec ("AVID DNxHD");
13005       caps = gst_caps_from_string ("video/x-dnxhd");
13006       break;
13007     case FOURCC_VP80:
13008       _codec ("On2 VP8");
13009       caps = gst_caps_from_string ("video/x-vp8");
13010       break;
13011     case FOURCC_apcs:
13012       _codec ("Apple ProRes LT");
13013       caps =
13014           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13015           NULL);
13016       break;
13017     case FOURCC_apch:
13018       _codec ("Apple ProRes HQ");
13019       caps =
13020           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13021           NULL);
13022       break;
13023     case FOURCC_apcn:
13024       _codec ("Apple ProRes");
13025       caps =
13026           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13027           "standard", NULL);
13028       break;
13029     case FOURCC_apco:
13030       _codec ("Apple ProRes Proxy");
13031       caps =
13032           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13033           "proxy", NULL);
13034       break;
13035     case FOURCC_ap4h:
13036       _codec ("Apple ProRes 4444");
13037       caps =
13038           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13039           "4444", NULL);
13040       break;
13041     case FOURCC_vc_1:
13042     case FOURCC_ovc1:
13043       _codec ("VC-1");
13044       caps = gst_caps_new_simple ("video/x-wmv",
13045           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13046       break;
13047     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13048     default:
13049     {
13050       char *s, fourstr[5];
13051
13052       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13053       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
13054       caps = gst_caps_new_empty_simple (s);
13055       g_free (s);
13056       break;
13057     }
13058   }
13059
13060   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13061     GstVideoInfo info;
13062
13063     gst_video_info_init (&info);
13064     gst_video_info_set_format (&info, format, stream->width, stream->height);
13065
13066     caps = gst_video_info_to_caps (&info);
13067     *codec_name = gst_pb_utils_get_codec_description (caps);
13068
13069     /* enable clipping for raw video streams */
13070     stream->need_clip = TRUE;
13071   }
13072
13073   return caps;
13074 }
13075
13076 static GstCaps *
13077 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13078     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13079 {
13080   GstCaps *caps;
13081   const GstStructure *s;
13082   const gchar *name;
13083   gint endian = 0;
13084   GstAudioFormat format = 0;
13085   gint depth;
13086
13087   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13088
13089   depth = stream->bytes_per_packet * 8;
13090
13091   switch (fourcc) {
13092     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13093     case FOURCC_raw_:
13094       /* 8-bit audio is unsigned */
13095       if (depth == 8)
13096         format = GST_AUDIO_FORMAT_U8;
13097       /* otherwise it's signed and big-endian just like 'twos' */
13098     case FOURCC_twos:
13099       endian = G_BIG_ENDIAN;
13100       /* fall-through */
13101     case FOURCC_sowt:
13102     {
13103       gchar *str;
13104
13105       if (!endian)
13106         endian = G_LITTLE_ENDIAN;
13107
13108       if (!format)
13109         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13110
13111       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13112       _codec (str);
13113       g_free (str);
13114
13115       caps = gst_caps_new_simple ("audio/x-raw",
13116           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13117           "layout", G_TYPE_STRING, "interleaved", NULL);
13118       break;
13119     }
13120     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13121       _codec ("Raw 64-bit floating-point audio");
13122       caps = gst_caps_new_simple ("audio/x-raw",
13123           "format", G_TYPE_STRING, "F64BE",
13124           "layout", G_TYPE_STRING, "interleaved", NULL);
13125       break;
13126     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13127       _codec ("Raw 32-bit floating-point audio");
13128       caps = gst_caps_new_simple ("audio/x-raw",
13129           "format", G_TYPE_STRING, "F32BE",
13130           "layout", G_TYPE_STRING, "interleaved", NULL);
13131       break;
13132     case FOURCC_in24:
13133       _codec ("Raw 24-bit PCM audio");
13134       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13135        * endian later */
13136       caps = gst_caps_new_simple ("audio/x-raw",
13137           "format", G_TYPE_STRING, "S24BE",
13138           "layout", G_TYPE_STRING, "interleaved", NULL);
13139       break;
13140     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13141       _codec ("Raw 32-bit PCM audio");
13142       caps = gst_caps_new_simple ("audio/x-raw",
13143           "format", G_TYPE_STRING, "S32BE",
13144           "layout", G_TYPE_STRING, "interleaved", NULL);
13145       break;
13146     case FOURCC_ulaw:
13147       _codec ("Mu-law audio");
13148       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13149       break;
13150     case FOURCC_alaw:
13151       _codec ("A-law audio");
13152       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13153       break;
13154     case 0x0200736d:
13155     case 0x6d730002:
13156       _codec ("Microsoft ADPCM");
13157       /* Microsoft ADPCM-ACM code 2 */
13158       caps = gst_caps_new_simple ("audio/x-adpcm",
13159           "layout", G_TYPE_STRING, "microsoft", NULL);
13160       break;
13161     case 0x1100736d:
13162     case 0x6d730011:
13163       _codec ("DVI/IMA ADPCM");
13164       caps = gst_caps_new_simple ("audio/x-adpcm",
13165           "layout", G_TYPE_STRING, "dvi", NULL);
13166       break;
13167     case 0x1700736d:
13168     case 0x6d730017:
13169       _codec ("DVI/Intel IMA ADPCM");
13170       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13171       caps = gst_caps_new_simple ("audio/x-adpcm",
13172           "layout", G_TYPE_STRING, "quicktime", NULL);
13173       break;
13174     case 0x5500736d:
13175     case 0x6d730055:
13176       /* MPEG layer 3, CBR only (pre QT4.1) */
13177     case FOURCC__mp3:
13178       _codec ("MPEG-1 layer 3");
13179       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13180       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13181           "mpegversion", G_TYPE_INT, 1, NULL);
13182       break;
13183     case 0x20736d:
13184     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13185       _codec ("EAC-3 audio");
13186       caps = gst_caps_new_simple ("audio/x-eac3",
13187           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13188       stream->sampled = TRUE;
13189       break;
13190     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13191     case FOURCC_ac_3:
13192       _codec ("AC-3 audio");
13193       caps = gst_caps_new_simple ("audio/x-ac3",
13194           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13195       stream->sampled = TRUE;
13196       break;
13197     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13198     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13199       _codec ("DTS audio");
13200       caps = gst_caps_new_simple ("audio/x-dts",
13201           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13202       stream->sampled = TRUE;
13203       break;
13204     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13205     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13206       _codec ("DTS-HD audio");
13207       caps = gst_caps_new_simple ("audio/x-dts",
13208           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13209       stream->sampled = TRUE;
13210       break;
13211     case FOURCC_MAC3:
13212       _codec ("MACE-3");
13213       caps = gst_caps_new_simple ("audio/x-mace",
13214           "maceversion", G_TYPE_INT, 3, NULL);
13215       break;
13216     case FOURCC_MAC6:
13217       _codec ("MACE-6");
13218       caps = gst_caps_new_simple ("audio/x-mace",
13219           "maceversion", G_TYPE_INT, 6, NULL);
13220       break;
13221     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13222       /* ogg/vorbis */
13223       caps = gst_caps_new_empty_simple ("application/ogg");
13224       break;
13225     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13226       _codec ("DV audio");
13227       caps = gst_caps_new_empty_simple ("audio/x-dv");
13228       break;
13229     case FOURCC_mp4a:
13230       _codec ("MPEG-4 AAC audio");
13231       caps = gst_caps_new_simple ("audio/mpeg",
13232           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13233           "stream-format", G_TYPE_STRING, "raw", NULL);
13234       break;
13235     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13236       _codec ("QDesign Music");
13237       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13238       break;
13239     case FOURCC_QDM2:
13240       _codec ("QDesign Music v.2");
13241       /* FIXME: QDesign music version 2 (no constant) */
13242       if (FALSE && data) {
13243         caps = gst_caps_new_simple ("audio/x-qdm2",
13244             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13245             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13246             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13247       } else {
13248         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13249       }
13250       break;
13251     case FOURCC_agsm:
13252       _codec ("GSM audio");
13253       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13254       break;
13255     case FOURCC_samr:
13256       _codec ("AMR audio");
13257       caps = gst_caps_new_empty_simple ("audio/AMR");
13258       break;
13259     case FOURCC_sawb:
13260       _codec ("AMR-WB audio");
13261       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13262       break;
13263     case FOURCC_ima4:
13264       _codec ("Quicktime IMA ADPCM");
13265       caps = gst_caps_new_simple ("audio/x-adpcm",
13266           "layout", G_TYPE_STRING, "quicktime", NULL);
13267       break;
13268     case FOURCC_alac:
13269       _codec ("Apple lossless audio");
13270       caps = gst_caps_new_empty_simple ("audio/x-alac");
13271       break;
13272     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13273       _codec ("QualComm PureVoice");
13274       caps = gst_caps_from_string ("audio/qcelp");
13275       break;
13276     case FOURCC_wma_:
13277     case FOURCC_owma:
13278       _codec ("WMA");
13279       caps = gst_caps_new_empty_simple ("audio/x-wma");
13280       break;
13281     case FOURCC_opus:
13282       _codec ("Opus");
13283       caps = gst_caps_new_empty_simple ("audio/x-opus");
13284       break;
13285     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13286     {
13287       guint32 flags = 0;
13288       guint32 depth = 0;
13289       guint32 width = 0;
13290       GstAudioFormat format;
13291       enum
13292       {
13293         FLAG_IS_FLOAT = 0x1,
13294         FLAG_IS_BIG_ENDIAN = 0x2,
13295         FLAG_IS_SIGNED = 0x4,
13296         FLAG_IS_PACKED = 0x8,
13297         FLAG_IS_ALIGNED_HIGH = 0x10,
13298         FLAG_IS_NON_INTERLEAVED = 0x20
13299       };
13300       _codec ("Raw LPCM audio");
13301
13302       if (data && len >= 56) {
13303         depth = QT_UINT32 (data + 40);
13304         flags = QT_UINT32 (data + 44);
13305         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13306       }
13307       if ((flags & FLAG_IS_FLOAT) == 0) {
13308         if (depth == 0)
13309           depth = 16;
13310         if (width == 0)
13311           width = 16;
13312         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13313             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13314             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13315         caps = gst_caps_new_simple ("audio/x-raw",
13316             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13317             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13318             "non-interleaved" : "interleaved", NULL);
13319       } else {
13320         if (width == 0)
13321           width = 32;
13322         if (width == 64) {
13323           if (flags & FLAG_IS_BIG_ENDIAN)
13324             format = GST_AUDIO_FORMAT_F64BE;
13325           else
13326             format = GST_AUDIO_FORMAT_F64LE;
13327         } else {
13328           if (flags & FLAG_IS_BIG_ENDIAN)
13329             format = GST_AUDIO_FORMAT_F32BE;
13330           else
13331             format = GST_AUDIO_FORMAT_F32LE;
13332         }
13333         caps = gst_caps_new_simple ("audio/x-raw",
13334             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13335             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13336             "non-interleaved" : "interleaved", NULL);
13337       }
13338       break;
13339     }
13340     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
13341       /* ? */
13342     default:
13343     {
13344       char *s, fourstr[5];
13345
13346       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13347       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
13348       caps = gst_caps_new_empty_simple (s);
13349       g_free (s);
13350       break;
13351     }
13352   }
13353
13354   if (caps) {
13355     GstCaps *templ_caps =
13356         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
13357     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
13358     gst_caps_unref (caps);
13359     gst_caps_unref (templ_caps);
13360     caps = intersection;
13361   }
13362
13363   /* enable clipping for raw audio streams */
13364   s = gst_caps_get_structure (caps, 0);
13365   name = gst_structure_get_name (s);
13366   if (g_str_has_prefix (name, "audio/x-raw")) {
13367     stream->need_clip = TRUE;
13368     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
13369     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
13370   }
13371   return caps;
13372 }
13373
13374 static GstCaps *
13375 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13376     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13377 {
13378   GstCaps *caps;
13379
13380   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13381
13382   switch (fourcc) {
13383     case FOURCC_mp4s:
13384       _codec ("DVD subtitle");
13385       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
13386       stream->need_process = TRUE;
13387       break;
13388     case FOURCC_text:
13389       _codec ("Quicktime timed text");
13390       goto text;
13391     case FOURCC_tx3g:
13392       _codec ("3GPP timed text");
13393     text:
13394       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
13395           "utf8", NULL);
13396       /* actual text piece needs to be extracted */
13397       stream->need_process = TRUE;
13398       break;
13399     case FOURCC_stpp:
13400       _codec ("XML subtitles");
13401       caps = gst_caps_new_empty_simple ("application/ttml+xml");
13402       break;
13403     default:
13404     {
13405       char *s, fourstr[5];
13406
13407       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13408       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
13409       caps = gst_caps_new_empty_simple (s);
13410       g_free (s);
13411       break;
13412     }
13413   }
13414   return caps;
13415 }
13416
13417 static GstCaps *
13418 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13419     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13420 {
13421   GstCaps *caps;
13422
13423   switch (fourcc) {
13424     case FOURCC_m1v:
13425       _codec ("MPEG 1 video");
13426       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13427           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13428       break;
13429     default:
13430       caps = NULL;
13431       break;
13432   }
13433   return caps;
13434 }
13435
13436 static void
13437 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
13438     const gchar * system_id)
13439 {
13440   gint i;
13441
13442   if (!qtdemux->protection_system_ids)
13443     qtdemux->protection_system_ids =
13444         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13445   /* Check whether we already have an entry for this system ID. */
13446   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13447     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13448     if (g_ascii_strcasecmp (system_id, id) == 0) {
13449       return;
13450     }
13451   }
13452   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13453   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13454           -1));
13455 }