qtdemux: Fix wrong compiler warning with gcc 6.2
[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  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * 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
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59
60 #include "qtatomparser.h"
61 #include "qtdemux_types.h"
62 #include "qtdemux_dump.h"
63 #include "fourcc.h"
64 #include "descriptors.h"
65 #include "qtdemux_lang.h"
66 #include "qtdemux.h"
67 #include "qtpalette.h"
68
69 #include "gst/riff/riff-media.h"
70 #include "gst/riff/riff-read.h"
71
72 #include <gst/pbutils/pbutils.h>
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
98
99 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
100
101 GST_DEBUG_CATEGORY (qtdemux_debug);
102
103 typedef struct _QtDemuxSegment QtDemuxSegment;
104 typedef struct _QtDemuxSample QtDemuxSample;
105
106 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
107
108 struct _QtDemuxSample
109 {
110   guint32 size;
111   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
112   guint64 offset;
113   guint64 timestamp;            /* DTS In mov time */
114   guint32 duration;             /* In mov time */
115   gboolean keyframe;            /* TRUE when this packet is a keyframe */
116 };
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset is the PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + duration - dts is the duration */
130 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
131
132 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
133
134 /*
135  * Quicktime has tracks and segments. A track is a continuous piece of
136  * multimedia content. The track is not always played from start to finish but
137  * instead, pieces of the track are 'cut out' and played in sequence. This is
138  * what the segments do.
139  *
140  * Inside the track we have keyframes (K) and delta frames. The track has its
141  * own timing, which starts from 0 and extends to end. The position in the track
142  * is called the media_time.
143  *
144  * The segments now describe the pieces that should be played from this track
145  * and are basically tuples of media_time/duration/rate entries. We can have
146  * multiple segments and they are all played after one another. An example:
147  *
148  * segment 1: media_time: 1 second, duration: 1 second, rate 1
149  * segment 2: media_time: 3 second, duration: 2 second, rate 2
150  *
151  * To correctly play back this track, one must play: 1 second of media starting
152  * from media_time 1 followed by 2 seconds of media starting from media_time 3
153  * at a rate of 2.
154  *
155  * Each of the segments will be played at a specific time, the first segment at
156  * time 0, the second one after the duration of the first one, etc.. Note that
157  * the time in resulting playback is not identical to the media_time of the
158  * track anymore.
159  *
160  * Visually, assuming the track has 4 second of media_time:
161  *
162  *                (a)                   (b)          (c)              (d)
163  *         .-----------------------------------------------------------.
164  * track:  | K.....K.........K........K.......K.......K...........K... |
165  *         '-----------------------------------------------------------'
166  *         0              1              2              3              4
167  *           .------------^              ^   .----------^              ^
168  *          /              .-------------'  /       .------------------'
169  *         /              /          .-----'       /
170  *         .--------------.         .--------------.
171  *         | segment 1    |         | segment 2    |
172  *         '--------------'         '--------------'
173  *
174  * The challenge here is to cut out the right pieces of the track for each of
175  * the playback segments. This fortunately can easily be done with the SEGMENT
176  * events of GStreamer.
177  *
178  * For playback of segment 1, we need to provide the decoder with the keyframe
179  * (a), in the above figure, but we must instruct it only to output the decoded
180  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
181  * position set to the time of the segment: 0.
182  *
183  * We then proceed to push data from keyframe (a) to frame (b). The decoder
184  * decodes but clips all before media_time 1.
185  *
186  * After finishing a segment, we push out a new SEGMENT event with the clipping
187  * boundaries of the new data.
188  *
189  * This is a good usecase for the GStreamer accumulated SEGMENT events.
190  */
191
192 struct _QtDemuxSegment
193 {
194   /* global time and duration, all gst time */
195   GstClockTime time;
196   GstClockTime stop_time;
197   GstClockTime duration;
198   /* media time of trak, all gst time */
199   GstClockTime media_start;
200   GstClockTime media_stop;
201   gdouble rate;
202   /* Media start time in trak timescale units */
203   guint32 trak_media_start;
204 };
205
206 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
207
208 /* Used with fragmented MP4 files (mfra atom) */
209 typedef struct
210 {
211   GstClockTime ts;
212   guint64 moof_offset;
213 } QtDemuxRandomAccessEntry;
214
215 struct _QtDemuxStream
216 {
217   GstPad *pad;
218
219   /* stream type */
220   guint32 subtype;
221   GstCaps *caps;
222   guint32 fourcc;
223   gboolean sparse;
224
225   gboolean new_caps;            /* If TRUE, caps need to be generated (by
226                                  * calling _configure_stream()) This happens
227                                  * for MSS and fragmented streams */
228
229   gboolean new_stream;          /* signals that a stream_start is required */
230   gboolean on_keyframe;         /* if this stream last pushed buffer was a
231                                  * keyframe. This is important to identify
232                                  * where to stop pushing buffers after a
233                                  * segment stop time */
234
235   /* if the stream has a redirect URI in its headers, we store it here */
236   gchar *redirect_uri;
237
238   /* track id */
239   guint track_id;
240
241   /* duration/scale */
242   guint64 duration;             /* in timescale units */
243   guint32 timescale;
244
245   /* language */
246   gchar lang_id[4];             /* ISO 639-2T language code */
247
248   /* our samples */
249   guint32 n_samples;
250   QtDemuxSample *samples;
251   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
252   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
253                                    the framerate */
254   guint32 n_samples_moof;       /* sample count in a moof */
255   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
256                                  * the framerate of fragmented format stream */
257   guint64 duration_last_moof;
258
259   guint32 offset_in_sample;     /* Offset in the current sample, used for
260                                  * streams which have got exceedingly big
261                                  * sample size (such as 24s of raw audio).
262                                  * Only used when max_buffer_size is non-NULL */
263   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
264                                  * Currently only set for raw audio streams*/
265
266   /* if we use chunks or samples */
267   gboolean sampled;
268   guint padding;
269
270   /* video info */
271   gint width;
272   gint height;
273   /* aspect ratio */
274   gint display_width;
275   gint display_height;
276   gint par_w;
277   gint par_h;
278   /* Numerator/denominator framerate */
279   gint fps_n;
280   gint fps_d;
281   GstVideoColorimetry colorimetry;
282   guint16 bits_per_sample;
283   guint16 color_table_id;
284   GstMemory *rgb8_palette;
285
286   /* audio info */
287   gdouble rate;
288   gint n_channels;
289   guint samples_per_packet;
290   guint samples_per_frame;
291   guint bytes_per_packet;
292   guint bytes_per_sample;
293   guint bytes_per_frame;
294   guint compression;
295
296   /* allocation */
297   gboolean use_allocator;
298   GstAllocator *allocator;
299   GstAllocationParams params;
300
301   gsize alignment;
302
303   /* when a discontinuity is pending */
304   gboolean discont;
305
306   /* list of buffers to push first */
307   GSList *buffers;
308
309   /* if we need to clip this buffer. This is only needed for uncompressed
310    * data */
311   gboolean need_clip;
312
313   /* buffer needs some custom processing, e.g. subtitles */
314   gboolean need_process;
315
316   /* current position */
317   guint32 segment_index;
318   guint32 sample_index;
319   GstClockTime time_position;   /* in gst time */
320   guint64 accumulated_base;
321
322   /* the Gst segment we are processing out, used for clipping */
323   GstSegment segment;
324
325   /* quicktime segments */
326   guint32 n_segments;
327   QtDemuxSegment *segments;
328   gboolean dummy_segment;
329   guint32 from_sample;
330   guint32 to_sample;
331
332   gboolean sent_eos;
333   GstTagList *pending_tags;
334   gboolean send_global_tags;
335
336   GstEvent *pending_event;
337
338   GstByteReader stco;
339   GstByteReader stsz;
340   GstByteReader stsc;
341   GstByteReader stts;
342   GstByteReader stss;
343   GstByteReader stps;
344   GstByteReader ctts;
345
346   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
347   gint64 stbl_index;
348   /* stco */
349   guint co_size;
350   GstByteReader co_chunk;
351   guint32 first_chunk;
352   guint32 current_chunk;
353   guint32 last_chunk;
354   guint32 samples_per_chunk;
355   guint32 stco_sample_index;
356   /* stsz */
357   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
358   /* stsc */
359   guint32 stsc_index;
360   guint32 n_samples_per_chunk;
361   guint32 stsc_chunk_index;
362   guint32 stsc_sample_index;
363   guint64 chunk_offset;
364   /* stts */
365   guint32 stts_index;
366   guint32 stts_samples;
367   guint32 n_sample_times;
368   guint32 stts_sample_index;
369   guint64 stts_time;
370   guint32 stts_duration;
371   /* stss */
372   gboolean stss_present;
373   guint32 n_sample_syncs;
374   guint32 stss_index;
375   /* stps */
376   gboolean stps_present;
377   guint32 n_sample_partial_syncs;
378   guint32 stps_index;
379   QtDemuxRandomAccessEntry *ra_entries;
380   guint n_ra_entries;
381
382   const QtDemuxRandomAccessEntry *pending_seek;
383
384   /* ctts */
385   gboolean ctts_present;
386   guint32 n_composition_times;
387   guint32 ctts_index;
388   guint32 ctts_sample_index;
389   guint32 ctts_count;
390   gint32 ctts_soffset;
391
392   /* cslg */
393   guint32 cslg_shift;
394
395   /* fragmented */
396   gboolean parsed_trex;
397   guint32 def_sample_duration;
398   guint32 def_sample_size;
399   guint32 def_sample_flags;
400
401   gboolean disabled;
402
403   /* stereoscopic video streams */
404   GstVideoMultiviewMode multiview_mode;
405   GstVideoMultiviewFlags multiview_flags;
406
407   /* protected streams */
408   gboolean protected;
409   guint32 protection_scheme_type;
410   guint32 protection_scheme_version;
411   gpointer protection_scheme_info;      /* specific to the protection scheme */
412   GQueue protection_scheme_event_queue;
413 };
414
415 /* Contains properties and cryptographic info for a set of samples from a
416  * track protected using Common Encryption (cenc) */
417 struct _QtDemuxCencSampleSetInfo
418 {
419   GstStructure *default_properties;
420
421   /* @crypto_info holds one GstStructure per sample */
422   GPtrArray *crypto_info;
423 };
424
425 static const gchar *
426 qt_demux_state_string (enum QtDemuxState state)
427 {
428   switch (state) {
429     case QTDEMUX_STATE_INITIAL:
430       return "<INITIAL>";
431     case QTDEMUX_STATE_HEADER:
432       return "<HEADER>";
433     case QTDEMUX_STATE_MOVIE:
434       return "<MOVIE>";
435     case QTDEMUX_STATE_BUFFER_MDAT:
436       return "<BUFFER_MDAT>";
437     default:
438       return "<UNKNOWN>";
439   }
440 }
441
442 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
443 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
444     guint32 fourcc, GstByteReader * parser);
445 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
446 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
447     guint32 fourcc, GstByteReader * parser);
448
449 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
450
451 static GstStaticPadTemplate gst_qtdemux_sink_template =
452     GST_STATIC_PAD_TEMPLATE ("sink",
453     GST_PAD_SINK,
454     GST_PAD_ALWAYS,
455     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
456         "application/x-3gp")
457     );
458
459 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
460 GST_STATIC_PAD_TEMPLATE ("video_%u",
461     GST_PAD_SRC,
462     GST_PAD_SOMETIMES,
463     GST_STATIC_CAPS_ANY);
464
465 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
466 GST_STATIC_PAD_TEMPLATE ("audio_%u",
467     GST_PAD_SRC,
468     GST_PAD_SOMETIMES,
469     GST_STATIC_CAPS_ANY);
470
471 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
472 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
473     GST_PAD_SRC,
474     GST_PAD_SOMETIMES,
475     GST_STATIC_CAPS_ANY);
476
477 #define gst_qtdemux_parent_class parent_class
478 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
479
480 static void gst_qtdemux_dispose (GObject * object);
481
482 static guint32
483 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
484     GstClockTime media_time);
485 static guint32
486 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
487     QtDemuxStream * str, gint64 media_offset);
488
489 #if 0
490 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
491 static GstIndex *gst_qtdemux_get_index (GstElement * element);
492 #endif
493 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
494     GstStateChange transition);
495 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
496 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
497     GstObject * parent, GstPadMode mode, gboolean active);
498
499 static void gst_qtdemux_loop (GstPad * pad);
500 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
501     GstBuffer * inbuf);
502 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
503     GstEvent * event);
504 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
505 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
506     QtDemuxStream * stream);
507 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
508     gboolean force);
509
510 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
511     const guint8 * buffer, guint length);
512 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
513     const guint8 * buffer, guint length);
514 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
515 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
516     GNode * udta);
517
518 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
519     QtDemuxStream * stream, GNode * esds, GstTagList * list);
520 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
521     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
522     gchar ** codec_name);
523 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
524     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
525     gchar ** codec_name);
526 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
527     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
528     gchar ** codec_name);
529 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
530     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
531     gchar ** codec_name);
532
533 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
534     QtDemuxStream * stream, guint32 n);
535 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
536 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
537     QtDemuxStream * stream);
538 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
539     QtDemuxStream * stream);
540 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
541 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
542 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
543     QtDemuxStream * stream);
544 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
545     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
546 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
547     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
548     GstClockTime * _start, GstClockTime * _stop);
549 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
550     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
551
552 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
553 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
554
555 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
556
557 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
558     QtDemuxStream * stream, guint sample_index);
559 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
560     const gchar * id);
561 static void qtdemux_gst_structure_free (GstStructure * gststructure);
562
563 static void
564 gst_qtdemux_class_init (GstQTDemuxClass * klass)
565 {
566   GObjectClass *gobject_class;
567   GstElementClass *gstelement_class;
568
569   gobject_class = (GObjectClass *) klass;
570   gstelement_class = (GstElementClass *) klass;
571
572   parent_class = g_type_class_peek_parent (klass);
573
574   gobject_class->dispose = gst_qtdemux_dispose;
575
576   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
577 #if 0
578   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
579   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
580 #endif
581
582   gst_tag_register_musicbrainz_tags ();
583
584   gst_element_class_add_static_pad_template (gstelement_class,
585       &gst_qtdemux_sink_template);
586   gst_element_class_add_static_pad_template (gstelement_class,
587       &gst_qtdemux_videosrc_template);
588   gst_element_class_add_static_pad_template (gstelement_class,
589       &gst_qtdemux_audiosrc_template);
590   gst_element_class_add_static_pad_template (gstelement_class,
591       &gst_qtdemux_subsrc_template);
592   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
593       "Codec/Demuxer",
594       "Demultiplex a QuickTime file into audio and video streams",
595       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
596
597   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
598
599 }
600
601 static void
602 gst_qtdemux_init (GstQTDemux * qtdemux)
603 {
604   qtdemux->sinkpad =
605       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
606   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
607   gst_pad_set_activatemode_function (qtdemux->sinkpad,
608       qtdemux_sink_activate_mode);
609   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
610   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
611   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
612
613   qtdemux->state = QTDEMUX_STATE_INITIAL;
614   qtdemux->pullbased = FALSE;
615   qtdemux->posted_redirect = FALSE;
616   qtdemux->neededbytes = 16;
617   qtdemux->todrop = 0;
618   qtdemux->adapter = gst_adapter_new ();
619   qtdemux->offset = 0;
620   qtdemux->first_mdat = -1;
621   qtdemux->got_moov = FALSE;
622   qtdemux->mdatoffset = -1;
623   qtdemux->mdatbuffer = NULL;
624   qtdemux->restoredata_buffer = NULL;
625   qtdemux->restoredata_offset = -1;
626   qtdemux->fragment_start = -1;
627   qtdemux->fragment_start_offset = -1;
628   qtdemux->media_caps = NULL;
629   qtdemux->exposed = FALSE;
630   qtdemux->mss_mode = FALSE;
631   qtdemux->pending_newsegment = NULL;
632   qtdemux->upstream_format_is_time = FALSE;
633   qtdemux->have_group_id = FALSE;
634   qtdemux->group_id = G_MAXUINT;
635   qtdemux->cenc_aux_info_offset = 0;
636   qtdemux->cenc_aux_info_sizes = NULL;
637   qtdemux->cenc_aux_sample_count = 0;
638   qtdemux->protection_system_ids = NULL;
639   g_queue_init (&qtdemux->protection_event_queue);
640   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
641   qtdemux->flowcombiner = gst_flow_combiner_new ();
642
643   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
644 }
645
646 static void
647 gst_qtdemux_dispose (GObject * object)
648 {
649   GstQTDemux *qtdemux = GST_QTDEMUX (object);
650
651   if (qtdemux->adapter) {
652     g_object_unref (G_OBJECT (qtdemux->adapter));
653     qtdemux->adapter = NULL;
654   }
655   gst_flow_combiner_free (qtdemux->flowcombiner);
656   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
657       NULL);
658   g_queue_clear (&qtdemux->protection_event_queue);
659
660   g_free (qtdemux->cenc_aux_info_sizes);
661   qtdemux->cenc_aux_info_sizes = NULL;
662
663   G_OBJECT_CLASS (parent_class)->dispose (object);
664 }
665
666 static void
667 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
668 {
669   if (qtdemux->posted_redirect) {
670     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
671         (_("This file contains no playable streams.")),
672         ("no known streams found, a redirect message has been posted"));
673   } else {
674     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
675         (_("This file contains no playable streams.")),
676         ("no known streams found"));
677   }
678 }
679
680 static GstBuffer *
681 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
682 {
683   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
684       mem, size, 0, size, mem, free_func);
685 }
686
687 static GstFlowReturn
688 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
689     GstBuffer ** buf)
690 {
691   GstFlowReturn flow;
692   GstMapInfo map;
693   gsize bsize;
694
695   if (G_UNLIKELY (size == 0)) {
696     GstFlowReturn ret;
697     GstBuffer *tmp = NULL;
698
699     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
700     if (ret != GST_FLOW_OK)
701       return ret;
702
703     gst_buffer_map (tmp, &map, GST_MAP_READ);
704     size = QT_UINT32 (map.data);
705     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
706
707     gst_buffer_unmap (tmp, &map);
708     gst_buffer_unref (tmp);
709   }
710
711   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
712   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
713     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
714       /* we're pulling header but already got most interesting bits,
715        * so never mind the rest (e.g. tags) (that much) */
716       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
717           size);
718       return GST_FLOW_EOS;
719     } else {
720       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
721           (_("This file is invalid and cannot be played.")),
722           ("atom has bogus size %" G_GUINT64_FORMAT, size));
723       return GST_FLOW_ERROR;
724     }
725   }
726
727   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
728
729   if (G_UNLIKELY (flow != GST_FLOW_OK))
730     return flow;
731
732   bsize = gst_buffer_get_size (*buf);
733   /* Catch short reads - we don't want any partial atoms */
734   if (G_UNLIKELY (bsize < size)) {
735     GST_WARNING_OBJECT (qtdemux,
736         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
737     gst_buffer_unref (*buf);
738     *buf = NULL;
739     return GST_FLOW_EOS;
740   }
741
742   return flow;
743 }
744
745 #if 1
746 static gboolean
747 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
748     GstFormat src_format, gint64 src_value, GstFormat dest_format,
749     gint64 * dest_value)
750 {
751   gboolean res = TRUE;
752   QtDemuxStream *stream = gst_pad_get_element_private (pad);
753   gint32 index;
754
755   if (stream->subtype != FOURCC_vide) {
756     res = FALSE;
757     goto done;
758   }
759
760   switch (src_format) {
761     case GST_FORMAT_TIME:
762       switch (dest_format) {
763         case GST_FORMAT_BYTES:{
764           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
765           if (-1 == index) {
766             res = FALSE;
767             goto done;
768           }
769
770           *dest_value = stream->samples[index].offset;
771
772           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
773               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
774               GST_TIME_ARGS (src_value), *dest_value);
775           break;
776         }
777         default:
778           res = FALSE;
779           break;
780       }
781       break;
782     case GST_FORMAT_BYTES:
783       switch (dest_format) {
784         case GST_FORMAT_TIME:{
785           index =
786               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
787               stream, src_value);
788
789           if (-1 == index) {
790             res = FALSE;
791             goto done;
792           }
793
794           *dest_value =
795               QTSTREAMTIME_TO_GSTTIME (stream,
796               stream->samples[index].timestamp);
797           GST_DEBUG_OBJECT (qtdemux,
798               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
799               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
800           break;
801         }
802         default:
803           res = FALSE;
804           break;
805       }
806       break;
807     default:
808       res = FALSE;
809       break;
810   }
811
812 done:
813   return res;
814 }
815 #endif
816
817 static gboolean
818 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
819 {
820   gboolean res = FALSE;
821
822   *duration = GST_CLOCK_TIME_NONE;
823
824   if (qtdemux->duration != 0 &&
825       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
826     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
827     res = TRUE;
828   } else {
829     *duration = GST_CLOCK_TIME_NONE;
830   }
831
832   return res;
833 }
834
835 static gboolean
836 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
837     GstQuery * query)
838 {
839   gboolean res = FALSE;
840   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
841
842   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
843
844   switch (GST_QUERY_TYPE (query)) {
845     case GST_QUERY_POSITION:{
846       GstFormat fmt;
847
848       gst_query_parse_position (query, &fmt, NULL);
849       if (fmt == GST_FORMAT_TIME
850           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
851         gst_query_set_position (query, GST_FORMAT_TIME,
852             qtdemux->segment.position);
853         res = TRUE;
854       }
855     }
856       break;
857     case GST_QUERY_DURATION:{
858       GstFormat fmt;
859
860       gst_query_parse_duration (query, &fmt, NULL);
861       if (fmt == GST_FORMAT_TIME) {
862         /* First try to query upstream */
863         res = gst_pad_query_default (pad, parent, query);
864         if (!res) {
865           GstClockTime duration;
866           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
867             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
868             res = TRUE;
869           }
870         }
871       }
872       break;
873     }
874     case GST_QUERY_CONVERT:{
875       GstFormat src_fmt, dest_fmt;
876       gint64 src_value, dest_value = 0;
877
878       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
879
880       res = gst_qtdemux_src_convert (qtdemux, pad,
881           src_fmt, src_value, dest_fmt, &dest_value);
882       if (res) {
883         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
884         res = TRUE;
885       }
886       break;
887     }
888     case GST_QUERY_FORMATS:
889       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
890       res = TRUE;
891       break;
892     case GST_QUERY_SEEKING:{
893       GstFormat fmt;
894       gboolean seekable;
895
896       /* try upstream first */
897       res = gst_pad_query_default (pad, parent, query);
898
899       if (!res) {
900         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
901         if (fmt == GST_FORMAT_TIME) {
902           GstClockTime duration;
903
904           gst_qtdemux_get_duration (qtdemux, &duration);
905           seekable = TRUE;
906           if (!qtdemux->pullbased) {
907             GstQuery *q;
908
909             /* we might be able with help from upstream */
910             seekable = FALSE;
911             q = gst_query_new_seeking (GST_FORMAT_BYTES);
912             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
913               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
914               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
915             }
916             gst_query_unref (q);
917           }
918           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
919           res = TRUE;
920         }
921       }
922       break;
923     }
924     case GST_QUERY_SEGMENT:
925     {
926       GstFormat format;
927       gint64 start, stop;
928
929       format = qtdemux->segment.format;
930
931       start =
932           gst_segment_to_stream_time (&qtdemux->segment, format,
933           qtdemux->segment.start);
934       if ((stop = qtdemux->segment.stop) == -1)
935         stop = qtdemux->segment.duration;
936       else
937         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
938
939       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
940       res = TRUE;
941       break;
942     }
943     default:
944       res = gst_pad_query_default (pad, parent, query);
945       break;
946   }
947
948   return res;
949 }
950
951 static void
952 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
953 {
954   if (G_LIKELY (stream->pad)) {
955     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
956         GST_DEBUG_PAD_NAME (stream->pad));
957
958     if (G_UNLIKELY (stream->pending_tags)) {
959       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
960           stream->pending_tags);
961       gst_pad_push_event (stream->pad,
962           gst_event_new_tag (stream->pending_tags));
963       stream->pending_tags = NULL;
964     }
965
966     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
967       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
968           qtdemux->tag_list);
969       gst_pad_push_event (stream->pad,
970           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
971       stream->send_global_tags = FALSE;
972     }
973   }
974 }
975
976 /* push event on all source pads; takes ownership of the event */
977 static void
978 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
979 {
980   guint n;
981   gboolean has_valid_stream = FALSE;
982   GstEventType etype = GST_EVENT_TYPE (event);
983
984   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
985       GST_EVENT_TYPE_NAME (event));
986
987   for (n = 0; n < qtdemux->n_streams; n++) {
988     GstPad *pad;
989     QtDemuxStream *stream = qtdemux->streams[n];
990     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
991
992     if ((pad = stream->pad)) {
993       has_valid_stream = TRUE;
994
995       if (etype == GST_EVENT_EOS) {
996         /* let's not send twice */
997         if (stream->sent_eos)
998           continue;
999         stream->sent_eos = TRUE;
1000       }
1001
1002       gst_pad_push_event (pad, gst_event_ref (event));
1003     }
1004   }
1005
1006   gst_event_unref (event);
1007
1008   /* if it is EOS and there are no pads, post an error */
1009   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1010     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1011   }
1012 }
1013
1014 /* push a pending newsegment event, if any from the streaming thread */
1015 static void
1016 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1017 {
1018   if (qtdemux->pending_newsegment) {
1019     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1020     qtdemux->pending_newsegment = NULL;
1021   }
1022 }
1023
1024 typedef struct
1025 {
1026   guint64 media_time;
1027 } FindData;
1028
1029 static gint
1030 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1031 {
1032   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1033     return 1;
1034   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1035     return 0;
1036
1037   return -1;
1038 }
1039
1040 /* find the index of the sample that includes the data for @media_time using a
1041  * binary search.  Only to be called in optimized cases of linear search below.
1042  *
1043  * Returns the index of the sample.
1044  */
1045 static guint32
1046 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1047     guint64 media_time)
1048 {
1049   QtDemuxSample *result;
1050   guint32 index;
1051
1052   /* convert media_time to mov format */
1053   media_time =
1054       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1055
1056   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1057       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1058       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1059
1060   if (G_LIKELY (result))
1061     index = result - str->samples;
1062   else
1063     index = 0;
1064
1065   return index;
1066 }
1067
1068
1069
1070 /* find the index of the sample that includes the data for @media_offset using a
1071  * linear search
1072  *
1073  * Returns the index of the sample.
1074  */
1075 static guint32
1076 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1077     QtDemuxStream * str, gint64 media_offset)
1078 {
1079   QtDemuxSample *result = str->samples;
1080   guint32 index = 0;
1081
1082   if (result == NULL || str->n_samples == 0)
1083     return -1;
1084
1085   if (media_offset == result->offset)
1086     return index;
1087
1088   result++;
1089   while (index < str->n_samples - 1) {
1090     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1091       goto parse_failed;
1092
1093     if (media_offset < result->offset)
1094       break;
1095
1096     index++;
1097     result++;
1098   }
1099   return index;
1100
1101   /* ERRORS */
1102 parse_failed:
1103   {
1104     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1105     return -1;
1106   }
1107 }
1108
1109 /* find the index of the sample that includes the data for @media_time using a
1110  * linear search, and keeping in mind that not all samples may have been parsed
1111  * yet.  If possible, it will delegate to binary search.
1112  *
1113  * Returns the index of the sample.
1114  */
1115 static guint32
1116 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1117     GstClockTime media_time)
1118 {
1119   guint32 index = 0;
1120   guint64 mov_time;
1121   QtDemuxSample *sample;
1122
1123   /* convert media_time to mov format */
1124   mov_time =
1125       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1126
1127   sample = str->samples;
1128   if (mov_time == sample->timestamp + sample->pts_offset)
1129     return index;
1130
1131   /* use faster search if requested time in already parsed range */
1132   sample = str->samples + str->stbl_index;
1133   if (str->stbl_index >= 0 &&
1134       mov_time <= (sample->timestamp + sample->pts_offset))
1135     return gst_qtdemux_find_index (qtdemux, str, media_time);
1136
1137   while (index < str->n_samples - 1) {
1138     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1139       goto parse_failed;
1140
1141     sample = str->samples + index + 1;
1142     if (mov_time < (sample->timestamp + sample->pts_offset))
1143       break;
1144
1145     index++;
1146   }
1147   return index;
1148
1149   /* ERRORS */
1150 parse_failed:
1151   {
1152     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1153     return -1;
1154   }
1155 }
1156
1157 /* find the index of the keyframe needed to decode the sample at @index
1158  * of stream @str.
1159  *
1160  * Returns the index of the keyframe.
1161  */
1162 static guint32
1163 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1164     guint32 index)
1165 {
1166   guint32 new_index = index;
1167
1168   if (index >= str->n_samples) {
1169     new_index = str->n_samples;
1170     goto beach;
1171   }
1172
1173   /* all keyframes, return index */
1174   if (str->all_keyframe) {
1175     new_index = index;
1176     goto beach;
1177   }
1178
1179   /* else go back until we have a keyframe */
1180   while (TRUE) {
1181     if (str->samples[new_index].keyframe)
1182       break;
1183
1184     if (new_index == 0)
1185       break;
1186
1187     new_index--;
1188   }
1189
1190 beach:
1191   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1192       "gave %u", index, new_index);
1193
1194   return new_index;
1195 }
1196
1197 /* find the segment for @time_position for @stream
1198  *
1199  * Returns the index of the segment containing @time_position.
1200  * Returns the last segment and sets the @eos variable to TRUE
1201  * if the time is beyond the end. @eos may be NULL
1202  */
1203 static guint32
1204 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1205     GstClockTime time_position)
1206 {
1207   gint i;
1208   guint32 seg_idx;
1209
1210   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1211       GST_TIME_ARGS (time_position));
1212
1213   seg_idx = -1;
1214   for (i = 0; i < stream->n_segments; i++) {
1215     QtDemuxSegment *segment = &stream->segments[i];
1216
1217     GST_LOG_OBJECT (stream->pad,
1218         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1219         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1220
1221     /* For the last segment we include stop_time in the last segment */
1222     if (i < stream->n_segments - 1) {
1223       if (segment->time <= time_position && time_position < segment->stop_time) {
1224         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1225         seg_idx = i;
1226         break;
1227       }
1228     } else {
1229       /* Last segment always matches */
1230       seg_idx = i;
1231       break;
1232     }
1233   }
1234   return seg_idx;
1235 }
1236
1237 /* move the stream @str to the sample position @index.
1238  *
1239  * Updates @str->sample_index and marks discontinuity if needed.
1240  */
1241 static void
1242 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1243     guint32 index)
1244 {
1245   /* no change needed */
1246   if (index == str->sample_index)
1247     return;
1248
1249   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1250       str->n_samples);
1251
1252   /* position changed, we have a discont */
1253   str->sample_index = index;
1254   str->offset_in_sample = 0;
1255   /* Each time we move in the stream we store the position where we are
1256    * starting from */
1257   str->from_sample = index;
1258   str->discont = TRUE;
1259 }
1260
1261 static void
1262 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1263     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1264 {
1265   guint64 min_offset;
1266   gint64 min_byte_offset = -1;
1267   gint n;
1268
1269   min_offset = desired_time;
1270
1271   /* for each stream, find the index of the sample in the segment
1272    * and move back to the previous keyframe. */
1273   for (n = 0; n < qtdemux->n_streams; n++) {
1274     QtDemuxStream *str;
1275     guint32 index, kindex;
1276     guint32 seg_idx;
1277     GstClockTime media_start;
1278     GstClockTime media_time;
1279     GstClockTime seg_time;
1280     QtDemuxSegment *seg;
1281     gboolean empty_segment = FALSE;
1282
1283     str = qtdemux->streams[n];
1284
1285     if (str->sparse && !use_sparse)
1286       continue;
1287
1288     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1289     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1290
1291     /* get segment and time in the segment */
1292     seg = &str->segments[seg_idx];
1293     seg_time = (desired_time - seg->time) * seg->rate;
1294
1295     while (QTSEGMENT_IS_EMPTY (seg)) {
1296       seg_time = 0;
1297       empty_segment = TRUE;
1298       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1299           seg_idx);
1300       seg_idx++;
1301       if (seg_idx == str->n_segments)
1302         break;
1303       seg = &str->segments[seg_idx];
1304     }
1305
1306     if (seg_idx == str->n_segments) {
1307       /* FIXME track shouldn't have the last segment as empty, but if it
1308        * happens we better handle it */
1309       continue;
1310     }
1311
1312     /* get the media time in the segment */
1313     media_start = seg->media_start + seg_time;
1314
1315     /* get the index of the sample with media time */
1316     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1317     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1318         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1319         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1320         empty_segment);
1321
1322     if (!empty_segment) {
1323       /* find previous keyframe */
1324       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1325
1326       /* if the keyframe is at a different position, we need to update the
1327        * requested seek time */
1328       if (index != kindex) {
1329         index = kindex;
1330
1331         /* get timestamp of keyframe */
1332         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1333         GST_DEBUG_OBJECT (qtdemux,
1334             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1335             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1336             str->samples[kindex].offset);
1337
1338         /* keyframes in the segment get a chance to change the
1339          * desired_offset. keyframes out of the segment are
1340          * ignored. */
1341         if (media_time >= seg->media_start) {
1342           GstClockTime seg_time;
1343
1344           /* this keyframe is inside the segment, convert back to
1345            * segment time */
1346           seg_time = (media_time - seg->media_start) + seg->time;
1347           if (seg_time < min_offset)
1348             min_offset = seg_time;
1349         }
1350       }
1351     }
1352
1353     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1354       min_byte_offset = str->samples[index].offset;
1355   }
1356
1357   if (key_time)
1358     *key_time = min_offset;
1359   if (key_offset)
1360     *key_offset = min_byte_offset;
1361 }
1362
1363 static gboolean
1364 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1365     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1366 {
1367   gboolean res;
1368
1369   g_return_val_if_fail (format != NULL, FALSE);
1370   g_return_val_if_fail (cur != NULL, FALSE);
1371   g_return_val_if_fail (stop != NULL, FALSE);
1372
1373   if (*format == GST_FORMAT_TIME)
1374     return TRUE;
1375
1376   res = TRUE;
1377   if (cur_type != GST_SEEK_TYPE_NONE)
1378     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1379   if (res && stop_type != GST_SEEK_TYPE_NONE)
1380     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1381
1382   if (res)
1383     *format = GST_FORMAT_TIME;
1384
1385   return res;
1386 }
1387
1388 /* perform seek in push based mode:
1389    find BYTE position to move to based on time and delegate to upstream
1390 */
1391 static gboolean
1392 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1393 {
1394   gdouble rate;
1395   GstFormat format;
1396   GstSeekFlags flags;
1397   GstSeekType cur_type, stop_type;
1398   gint64 cur, stop, key_cur;
1399   gboolean res;
1400   gint64 byte_cur;
1401   gint64 original_stop;
1402   guint32 seqnum;
1403
1404   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1405
1406   gst_event_parse_seek (event, &rate, &format, &flags,
1407       &cur_type, &cur, &stop_type, &stop);
1408   seqnum = gst_event_get_seqnum (event);
1409
1410   /* only forward streaming and seeking is possible */
1411   if (rate <= 0)
1412     goto unsupported_seek;
1413
1414   /* convert to TIME if needed and possible */
1415   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1416           stop_type, &stop))
1417     goto no_format;
1418
1419   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1420    * the original stop position to use when upstream pushes the new segment
1421    * for this seek */
1422   original_stop = stop;
1423   stop = -1;
1424
1425   /* find reasonable corresponding BYTE position,
1426    * also try to mind about keyframes, since we can not go back a bit for them
1427    * later on */
1428   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1429
1430   if (byte_cur == -1)
1431     goto abort_seek;
1432
1433   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1434       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1435       stop);
1436
1437   GST_OBJECT_LOCK (qtdemux);
1438   qtdemux->seek_offset = byte_cur;
1439   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1440     qtdemux->push_seek_start = cur;
1441   } else {
1442     qtdemux->push_seek_start = key_cur;
1443   }
1444
1445   if (stop_type == GST_SEEK_TYPE_NONE) {
1446     qtdemux->push_seek_stop = qtdemux->segment.stop;
1447   } else {
1448     qtdemux->push_seek_stop = original_stop;
1449   }
1450   GST_OBJECT_UNLOCK (qtdemux);
1451
1452   /* BYTE seek event */
1453   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1454       stop_type, stop);
1455   gst_event_set_seqnum (event, seqnum);
1456   res = gst_pad_push_event (qtdemux->sinkpad, event);
1457
1458   return res;
1459
1460   /* ERRORS */
1461 abort_seek:
1462   {
1463     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1464         "seek aborted.");
1465     return FALSE;
1466   }
1467 unsupported_seek:
1468   {
1469     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1470     return FALSE;
1471   }
1472 no_format:
1473   {
1474     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1475     return FALSE;
1476   }
1477 }
1478
1479 /* perform the seek.
1480  *
1481  * We set all segment_indexes in the streams to unknown and
1482  * adjust the time_position to the desired position. this is enough
1483  * to trigger a segment switch in the streaming thread to start
1484  * streaming from the desired position.
1485  *
1486  * Keyframe seeking is a little more complicated when dealing with
1487  * segments. Ideally we want to move to the previous keyframe in
1488  * the segment but there might not be a keyframe in the segment. In
1489  * fact, none of the segments could contain a keyframe. We take a
1490  * practical approach: seek to the previous keyframe in the segment,
1491  * if there is none, seek to the beginning of the segment.
1492  *
1493  * Called with STREAM_LOCK
1494  */
1495 static gboolean
1496 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1497     guint32 seqnum, GstSeekFlags flags)
1498 {
1499   gint64 desired_offset;
1500   gint n;
1501
1502   desired_offset = segment->position;
1503
1504   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1505       GST_TIME_ARGS (desired_offset));
1506
1507   /* may not have enough fragmented info to do this adjustment,
1508    * and we can't scan (and probably should not) at this time with
1509    * possibly flushing upstream */
1510   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1511     gint64 min_offset;
1512
1513     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1514     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1515         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1516     desired_offset = min_offset;
1517   }
1518
1519   /* and set all streams to the final position */
1520   gst_flow_combiner_reset (qtdemux->flowcombiner);
1521   qtdemux->segment_seqnum = seqnum;
1522   for (n = 0; n < qtdemux->n_streams; n++) {
1523     QtDemuxStream *stream = qtdemux->streams[n];
1524
1525     stream->time_position = desired_offset;
1526     stream->accumulated_base = 0;
1527     stream->sample_index = -1;
1528     stream->offset_in_sample = 0;
1529     stream->segment_index = -1;
1530     stream->sent_eos = FALSE;
1531
1532     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1533       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1534   }
1535   segment->position = desired_offset;
1536   segment->time = desired_offset;
1537   if (segment->rate >= 0) {
1538     segment->start = desired_offset;
1539
1540     /* we stop at the end */
1541     if (segment->stop == -1)
1542       segment->stop = segment->duration;
1543   } else {
1544     segment->stop = desired_offset;
1545   }
1546
1547   if (qtdemux->fragmented)
1548     qtdemux->fragmented_seek_pending = TRUE;
1549
1550   return TRUE;
1551 }
1552
1553 /* do a seek in pull based mode */
1554 static gboolean
1555 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1556 {
1557   gdouble rate;
1558   GstFormat format;
1559   GstSeekFlags flags;
1560   GstSeekType cur_type, stop_type;
1561   gint64 cur, stop;
1562   gboolean flush;
1563   gboolean update;
1564   GstSegment seeksegment;
1565   guint32 seqnum = 0;
1566   GstEvent *flush_event;
1567
1568   if (event) {
1569     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1570
1571     gst_event_parse_seek (event, &rate, &format, &flags,
1572         &cur_type, &cur, &stop_type, &stop);
1573     seqnum = gst_event_get_seqnum (event);
1574
1575     /* we have to have a format as the segment format. Try to convert
1576      * if not. */
1577     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1578             stop_type, &stop))
1579       goto no_format;
1580
1581     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1582   } else {
1583     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1584     flags = 0;
1585   }
1586
1587   flush = flags & GST_SEEK_FLAG_FLUSH;
1588
1589   /* stop streaming, either by flushing or by pausing the task */
1590   if (flush) {
1591     flush_event = gst_event_new_flush_start ();
1592     if (seqnum)
1593       gst_event_set_seqnum (flush_event, seqnum);
1594     /* unlock upstream pull_range */
1595     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1596     /* make sure out loop function exits */
1597     gst_qtdemux_push_event (qtdemux, flush_event);
1598   } else {
1599     /* non flushing seek, pause the task */
1600     gst_pad_pause_task (qtdemux->sinkpad);
1601   }
1602
1603   /* wait for streaming to finish */
1604   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1605
1606   /* copy segment, we need this because we still need the old
1607    * segment when we close the current segment. */
1608   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1609
1610   if (event) {
1611     /* configure the segment with the seek variables */
1612     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1613     gst_segment_do_seek (&seeksegment, rate, format, flags,
1614         cur_type, cur, stop_type, stop, &update);
1615   }
1616
1617   /* now do the seek, this actually never returns FALSE */
1618   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1619
1620   /* prepare for streaming again */
1621   if (flush) {
1622     flush_event = gst_event_new_flush_stop (TRUE);
1623     if (seqnum)
1624       gst_event_set_seqnum (flush_event, seqnum);
1625
1626     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1627     gst_qtdemux_push_event (qtdemux, flush_event);
1628   }
1629
1630   /* commit the new segment */
1631   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1632
1633   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1634     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1635         qtdemux->segment.format, qtdemux->segment.position);
1636     if (seqnum)
1637       gst_message_set_seqnum (msg, seqnum);
1638     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1639   }
1640
1641   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1642   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1643       qtdemux->sinkpad, NULL);
1644
1645   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1646
1647   return TRUE;
1648
1649   /* ERRORS */
1650 no_format:
1651   {
1652     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1653     return FALSE;
1654   }
1655 }
1656
1657 static gboolean
1658 qtdemux_ensure_index (GstQTDemux * qtdemux)
1659 {
1660   guint i;
1661
1662   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1663
1664   /* Build complete index */
1665   for (i = 0; i < qtdemux->n_streams; i++) {
1666     QtDemuxStream *stream = qtdemux->streams[i];
1667
1668     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1669       goto parse_error;
1670   }
1671   return TRUE;
1672
1673   /* ERRORS */
1674 parse_error:
1675   {
1676     GST_LOG_OBJECT (qtdemux,
1677         "Building complete index of stream %u for seeking failed!", i);
1678     return FALSE;
1679   }
1680 }
1681
1682 static gboolean
1683 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1684     GstEvent * event)
1685 {
1686   gboolean res = TRUE;
1687   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1688
1689   switch (GST_EVENT_TYPE (event)) {
1690     case GST_EVENT_SEEK:
1691     {
1692 #ifndef GST_DISABLE_GST_DEBUG
1693       GstClockTime ts = gst_util_get_timestamp ();
1694 #endif
1695
1696       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1697         /* seek should be handled by upstream, we might need to re-download fragments */
1698         GST_DEBUG_OBJECT (qtdemux,
1699             "let upstream handle seek for fragmented playback");
1700         goto upstream;
1701       }
1702
1703       /* Build complete index for seeking;
1704        * if not a fragmented file at least */
1705       if (!qtdemux->fragmented)
1706         if (!qtdemux_ensure_index (qtdemux))
1707           goto index_failed;
1708 #ifndef GST_DISABLE_GST_DEBUG
1709       ts = gst_util_get_timestamp () - ts;
1710       GST_INFO_OBJECT (qtdemux,
1711           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1712 #endif
1713     }
1714       if (qtdemux->pullbased) {
1715         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1716       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1717         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1718         res = TRUE;
1719       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1720           && !qtdemux->fragmented) {
1721         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1722       } else {
1723         GST_DEBUG_OBJECT (qtdemux,
1724             "ignoring seek in push mode in current state");
1725         res = FALSE;
1726       }
1727       gst_event_unref (event);
1728       break;
1729     default:
1730     upstream:
1731       res = gst_pad_event_default (pad, parent, event);
1732       break;
1733   }
1734
1735 done:
1736   return res;
1737
1738   /* ERRORS */
1739 index_failed:
1740   {
1741     GST_ERROR_OBJECT (qtdemux, "Index failed");
1742     gst_event_unref (event);
1743     res = FALSE;
1744     goto done;
1745   }
1746 }
1747
1748 /* stream/index return sample that is min/max w.r.t. byte position,
1749  * time is min/max w.r.t. time of samples,
1750  * the latter need not be time of the former sample */
1751 static void
1752 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1753     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1754 {
1755   gint i, n, index;
1756   gint64 time, min_time;
1757   QtDemuxStream *stream;
1758
1759   min_time = -1;
1760   stream = NULL;
1761   index = -1;
1762
1763   for (n = 0; n < qtdemux->n_streams; ++n) {
1764     QtDemuxStream *str;
1765     gint inc;
1766     gboolean set_sample;
1767
1768     str = qtdemux->streams[n];
1769     set_sample = !set;
1770
1771     if (fw) {
1772       i = 0;
1773       inc = 1;
1774     } else {
1775       i = str->n_samples - 1;
1776       inc = -1;
1777     }
1778
1779     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1780       if (str->samples[i].size == 0)
1781         continue;
1782
1783       if (fw && (str->samples[i].offset < byte_pos))
1784         continue;
1785
1786       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1787         continue;
1788
1789       /* move stream to first available sample */
1790       if (set) {
1791         gst_qtdemux_move_stream (qtdemux, str, i);
1792         set_sample = TRUE;
1793       }
1794
1795       /* avoid index from sparse streams since they might be far away */
1796       if (!str->sparse) {
1797         /* determine min/max time */
1798         time = QTSAMPLE_PTS (str, &str->samples[i]);
1799         if (min_time == -1 || (!fw && time > min_time) ||
1800             (fw && time < min_time)) {
1801           min_time = time;
1802         }
1803
1804         /* determine stream with leading sample, to get its position */
1805         if (!stream ||
1806             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1807             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1808           stream = str;
1809           index = i;
1810         }
1811       }
1812       break;
1813     }
1814
1815     /* no sample for this stream, mark eos */
1816     if (!set_sample)
1817       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1818   }
1819
1820   if (_time)
1821     *_time = min_time;
1822   if (_stream)
1823     *_stream = stream;
1824   if (_index)
1825     *_index = index;
1826 }
1827
1828 static QtDemuxStream *
1829 _create_stream (void)
1830 {
1831   QtDemuxStream *stream;
1832
1833   stream = g_new0 (QtDemuxStream, 1);
1834   /* new streams always need a discont */
1835   stream->discont = TRUE;
1836   /* we enable clipping for raw audio/video streams */
1837   stream->need_clip = FALSE;
1838   stream->need_process = FALSE;
1839   stream->segment_index = -1;
1840   stream->time_position = 0;
1841   stream->sample_index = -1;
1842   stream->offset_in_sample = 0;
1843   stream->new_stream = TRUE;
1844   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1845   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1846   stream->protected = FALSE;
1847   stream->protection_scheme_type = 0;
1848   stream->protection_scheme_version = 0;
1849   stream->protection_scheme_info = NULL;
1850   stream->n_samples_moof = 0;
1851   stream->duration_moof = 0;
1852   stream->duration_last_moof = 0;
1853   stream->alignment = 1;
1854   g_queue_init (&stream->protection_scheme_event_queue);
1855   return stream;
1856 }
1857
1858 static gboolean
1859 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1860 {
1861   GstStructure *structure;
1862   const gchar *variant;
1863   const GstCaps *mediacaps = NULL;
1864
1865   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1866
1867   structure = gst_caps_get_structure (caps, 0);
1868   variant = gst_structure_get_string (structure, "variant");
1869
1870   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1871     QtDemuxStream *stream;
1872     const GValue *value;
1873
1874     demux->fragmented = TRUE;
1875     demux->mss_mode = TRUE;
1876
1877     if (demux->n_streams > 1) {
1878       /* can't do this, we can only renegotiate for another mss format */
1879       return FALSE;
1880     }
1881
1882     value = gst_structure_get_value (structure, "media-caps");
1883     /* create stream */
1884     if (value) {
1885       const GValue *timescale_v;
1886
1887       /* TODO update when stream changes during playback */
1888
1889       if (demux->n_streams == 0) {
1890         stream = _create_stream ();
1891         demux->streams[demux->n_streams] = stream;
1892         demux->n_streams = 1;
1893       } else {
1894         stream = demux->streams[0];
1895       }
1896
1897       timescale_v = gst_structure_get_value (structure, "timescale");
1898       if (timescale_v) {
1899         stream->timescale = g_value_get_uint64 (timescale_v);
1900       } else {
1901         /* default mss timescale */
1902         stream->timescale = 10000000;
1903       }
1904       demux->timescale = stream->timescale;
1905
1906       mediacaps = gst_value_get_caps (value);
1907       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1908         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1909             mediacaps);
1910         stream->new_caps = TRUE;
1911       }
1912       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1913       structure = gst_caps_get_structure (mediacaps, 0);
1914       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1915         stream->subtype = FOURCC_vide;
1916
1917         gst_structure_get_int (structure, "width", &stream->width);
1918         gst_structure_get_int (structure, "height", &stream->height);
1919         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1920             &stream->fps_d);
1921       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1922         gint rate = 0;
1923         stream->subtype = FOURCC_soun;
1924         gst_structure_get_int (structure, "channels", &stream->n_channels);
1925         gst_structure_get_int (structure, "rate", &rate);
1926         stream->rate = rate;
1927       }
1928     }
1929     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1930   } else {
1931     demux->mss_mode = FALSE;
1932   }
1933
1934   return TRUE;
1935 }
1936
1937 static void
1938 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1939 {
1940   gint n;
1941
1942   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1943   gst_pad_stop_task (qtdemux->sinkpad);
1944
1945   if (hard || qtdemux->upstream_format_is_time) {
1946     qtdemux->state = QTDEMUX_STATE_INITIAL;
1947     qtdemux->neededbytes = 16;
1948     qtdemux->todrop = 0;
1949     qtdemux->pullbased = FALSE;
1950     qtdemux->posted_redirect = FALSE;
1951     qtdemux->first_mdat = -1;
1952     qtdemux->header_size = 0;
1953     qtdemux->mdatoffset = -1;
1954     qtdemux->restoredata_offset = -1;
1955     if (qtdemux->mdatbuffer)
1956       gst_buffer_unref (qtdemux->mdatbuffer);
1957     if (qtdemux->restoredata_buffer)
1958       gst_buffer_unref (qtdemux->restoredata_buffer);
1959     qtdemux->mdatbuffer = NULL;
1960     qtdemux->restoredata_buffer = NULL;
1961     qtdemux->mdatleft = 0;
1962     if (qtdemux->comp_brands)
1963       gst_buffer_unref (qtdemux->comp_brands);
1964     qtdemux->comp_brands = NULL;
1965     qtdemux->last_moov_offset = -1;
1966     if (qtdemux->moov_node)
1967       g_node_destroy (qtdemux->moov_node);
1968     qtdemux->moov_node = NULL;
1969     qtdemux->moov_node_compressed = NULL;
1970     if (qtdemux->tag_list)
1971       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1972     qtdemux->tag_list = NULL;
1973 #if 0
1974     if (qtdemux->element_index)
1975       gst_object_unref (qtdemux->element_index);
1976     qtdemux->element_index = NULL;
1977 #endif
1978     qtdemux->major_brand = 0;
1979     if (qtdemux->pending_newsegment)
1980       gst_event_unref (qtdemux->pending_newsegment);
1981     qtdemux->pending_newsegment = NULL;
1982     qtdemux->upstream_format_is_time = FALSE;
1983     qtdemux->upstream_seekable = FALSE;
1984     qtdemux->upstream_size = 0;
1985
1986     qtdemux->fragment_start = -1;
1987     qtdemux->fragment_start_offset = -1;
1988     qtdemux->duration = 0;
1989     qtdemux->moof_offset = 0;
1990     qtdemux->chapters_track_id = 0;
1991     qtdemux->have_group_id = FALSE;
1992     qtdemux->group_id = G_MAXUINT;
1993
1994     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1995         NULL);
1996     g_queue_clear (&qtdemux->protection_event_queue);
1997   }
1998   qtdemux->offset = 0;
1999   gst_adapter_clear (qtdemux->adapter);
2000   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2001   qtdemux->segment_seqnum = 0;
2002
2003   if (hard) {
2004     for (n = 0; n < qtdemux->n_streams; n++) {
2005       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2006       qtdemux->streams[n] = NULL;
2007     }
2008     qtdemux->n_streams = 0;
2009     qtdemux->n_video_streams = 0;
2010     qtdemux->n_audio_streams = 0;
2011     qtdemux->n_sub_streams = 0;
2012     qtdemux->exposed = FALSE;
2013     qtdemux->fragmented = FALSE;
2014     qtdemux->mss_mode = FALSE;
2015     gst_caps_replace (&qtdemux->media_caps, NULL);
2016     qtdemux->timescale = 0;
2017     qtdemux->got_moov = FALSE;
2018     if (qtdemux->protection_system_ids) {
2019       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2020       qtdemux->protection_system_ids = NULL;
2021     }
2022   } else if (qtdemux->mss_mode) {
2023     gst_flow_combiner_reset (qtdemux->flowcombiner);
2024     for (n = 0; n < qtdemux->n_streams; n++)
2025       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2026   } else {
2027     gst_flow_combiner_reset (qtdemux->flowcombiner);
2028     for (n = 0; n < qtdemux->n_streams; n++) {
2029       qtdemux->streams[n]->sent_eos = FALSE;
2030       qtdemux->streams[n]->time_position = 0;
2031       qtdemux->streams[n]->accumulated_base = 0;
2032     }
2033     if (!qtdemux->pending_newsegment) {
2034       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2035       if (qtdemux->segment_seqnum)
2036         gst_event_set_seqnum (qtdemux->pending_newsegment,
2037             qtdemux->segment_seqnum);
2038     }
2039   }
2040 }
2041
2042
2043 /* Maps the @segment to the qt edts internal segments and pushes
2044  * the correspnding segment event.
2045  *
2046  * If it ends up being at a empty segment, a gap will be pushed and the next
2047  * edts segment will be activated in sequence.
2048  *
2049  * To be used in push-mode only */
2050 static void
2051 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2052 {
2053   gint n, i;
2054
2055   for (n = 0; n < qtdemux->n_streams; n++) {
2056     QtDemuxStream *stream = qtdemux->streams[n];
2057
2058     stream->time_position = segment->start;
2059
2060     /* in push mode we should be guaranteed that we will have empty segments
2061      * at the beginning and then one segment after, other scenarios are not
2062      * supported and are discarded when parsing the edts */
2063     for (i = 0; i < stream->n_segments; i++) {
2064       if (stream->segments[i].stop_time > segment->start) {
2065         gst_qtdemux_activate_segment (qtdemux, stream, i,
2066             stream->time_position);
2067         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2068           /* push the empty segment and move to the next one */
2069           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2070               stream->time_position);
2071           continue;
2072         }
2073
2074         g_assert (i == stream->n_segments - 1);
2075       }
2076     }
2077   }
2078 }
2079
2080 static gboolean
2081 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2082     GstEvent * event)
2083 {
2084   GstQTDemux *demux = GST_QTDEMUX (parent);
2085   gboolean res = TRUE;
2086
2087   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2088
2089   switch (GST_EVENT_TYPE (event)) {
2090     case GST_EVENT_SEGMENT:
2091     {
2092       gint64 offset = 0;
2093       QtDemuxStream *stream;
2094       gint idx;
2095       GstSegment segment;
2096
2097       /* some debug output */
2098       gst_event_copy_segment (event, &segment);
2099       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2100           &segment);
2101
2102       /* erase any previously set segment */
2103       gst_event_replace (&demux->pending_newsegment, NULL);
2104
2105       if (segment.format == GST_FORMAT_TIME) {
2106         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2107         gst_event_replace (&demux->pending_newsegment, event);
2108         demux->upstream_format_is_time = TRUE;
2109       } else {
2110         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2111             "not in time format");
2112
2113         /* chain will send initial newsegment after pads have been added */
2114         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2115           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2116           goto exit;
2117         }
2118       }
2119
2120       /* check if this matches a time seek we received previously
2121        * FIXME for backwards compatibility reasons we use the
2122        * seek_offset here to compare. In the future we might want to
2123        * change this to use the seqnum as it uniquely should identify
2124        * the segment that corresponds to the seek. */
2125       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2126           ", received segment offset %" G_GINT64_FORMAT,
2127           demux->seek_offset, segment.start);
2128       if (segment.format == GST_FORMAT_BYTES
2129           && demux->seek_offset == segment.start) {
2130         GST_OBJECT_LOCK (demux);
2131         offset = segment.start;
2132
2133         segment.format = GST_FORMAT_TIME;
2134         segment.start = demux->push_seek_start;
2135         segment.stop = demux->push_seek_stop;
2136         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2137             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2138             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2139         GST_OBJECT_UNLOCK (demux);
2140       }
2141
2142       /* we only expect a BYTE segment, e.g. following a seek */
2143       if (segment.format == GST_FORMAT_BYTES) {
2144         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2145           offset = segment.start;
2146
2147           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2148               NULL, (gint64 *) & segment.start);
2149           if ((gint64) segment.start < 0)
2150             segment.start = 0;
2151         }
2152         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2153           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2154               NULL, (gint64 *) & segment.stop);
2155           /* keyframe seeking should already arrange for start >= stop,
2156            * but make sure in other rare cases */
2157           segment.stop = MAX (segment.stop, segment.start);
2158         }
2159       } else if (segment.format == GST_FORMAT_TIME) {
2160         /* push all data on the adapter before starting this
2161          * new segment */
2162         gst_qtdemux_process_adapter (demux, TRUE);
2163       } else {
2164         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2165         goto exit;
2166       }
2167
2168       /* We shouldn't modify upstream driven TIME FORMAT segment */
2169       if (!demux->upstream_format_is_time) {
2170         /* accept upstream's notion of segment and distribute along */
2171         segment.format = GST_FORMAT_TIME;
2172         segment.position = segment.time = segment.start;
2173         segment.duration = demux->segment.duration;
2174         segment.base = gst_segment_to_running_time (&demux->segment,
2175             GST_FORMAT_TIME, demux->segment.position);
2176       }
2177
2178       gst_segment_copy_into (&segment, &demux->segment);
2179       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2180
2181       /* map segment to internal qt segments and push on each stream */
2182       if (demux->n_streams) {
2183         if (demux->fragmented) {
2184           GstEvent *segment_event = gst_event_new_segment (&segment);
2185
2186           gst_event_replace (&demux->pending_newsegment, NULL);
2187           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2188           gst_qtdemux_push_event (demux, segment_event);
2189         } else {
2190           gst_event_replace (&demux->pending_newsegment, NULL);
2191           gst_qtdemux_map_and_push_segments (demux, &segment);
2192         }
2193       }
2194
2195       /* clear leftover in current segment, if any */
2196       gst_adapter_clear (demux->adapter);
2197
2198       /* set up streaming thread */
2199       demux->offset = offset;
2200       if (demux->upstream_format_is_time) {
2201         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2202             "set values to restart reading from a new atom");
2203         demux->neededbytes = 16;
2204         demux->todrop = 0;
2205       } else {
2206         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2207             NULL);
2208         if (stream) {
2209           demux->todrop = stream->samples[idx].offset - offset;
2210           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2211         } else {
2212           /* set up for EOS */
2213           demux->neededbytes = -1;
2214           demux->todrop = 0;
2215         }
2216       }
2217     exit:
2218       gst_event_unref (event);
2219       res = TRUE;
2220       goto drop;
2221     }
2222     case GST_EVENT_FLUSH_START:
2223     {
2224       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2225         gst_event_unref (event);
2226         goto drop;
2227       }
2228       break;
2229     }
2230     case GST_EVENT_FLUSH_STOP:
2231     {
2232       guint64 dur;
2233
2234       dur = demux->segment.duration;
2235       gst_qtdemux_reset (demux, FALSE);
2236       demux->segment.duration = dur;
2237
2238       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2239         gst_event_unref (event);
2240         goto drop;
2241       }
2242       break;
2243     }
2244     case GST_EVENT_EOS:
2245       /* If we are in push mode, and get an EOS before we've seen any streams,
2246        * then error out - we have nowhere to send the EOS */
2247       if (!demux->pullbased) {
2248         gint i;
2249         gboolean has_valid_stream = FALSE;
2250         for (i = 0; i < demux->n_streams; i++) {
2251           if (demux->streams[i]->pad != NULL) {
2252             has_valid_stream = TRUE;
2253             break;
2254           }
2255         }
2256         if (!has_valid_stream)
2257           gst_qtdemux_post_no_playable_stream_error (demux);
2258         else {
2259           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2260               (guint) gst_adapter_available (demux->adapter));
2261           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2262             res = FALSE;
2263           }
2264         }
2265       }
2266       break;
2267     case GST_EVENT_CAPS:{
2268       GstCaps *caps = NULL;
2269
2270       gst_event_parse_caps (event, &caps);
2271       gst_qtdemux_setcaps (demux, caps);
2272       res = TRUE;
2273       gst_event_unref (event);
2274       goto drop;
2275     }
2276     case GST_EVENT_PROTECTION:
2277     {
2278       const gchar *system_id = NULL;
2279
2280       gst_event_parse_protection (event, &system_id, NULL, NULL);
2281       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2282           system_id);
2283       gst_qtdemux_append_protection_system_id (demux, system_id);
2284       /* save the event for later, for source pads that have not been created */
2285       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2286       /* send it to all pads that already exist */
2287       gst_qtdemux_push_event (demux, event);
2288       res = TRUE;
2289       goto drop;
2290     }
2291     default:
2292       break;
2293   }
2294
2295   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2296
2297 drop:
2298   return res;
2299 }
2300
2301 #if 0
2302 static void
2303 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2304 {
2305   GstQTDemux *demux = GST_QTDEMUX (element);
2306
2307   GST_OBJECT_LOCK (demux);
2308   if (demux->element_index)
2309     gst_object_unref (demux->element_index);
2310   if (index) {
2311     demux->element_index = gst_object_ref (index);
2312   } else {
2313     demux->element_index = NULL;
2314   }
2315   GST_OBJECT_UNLOCK (demux);
2316   /* object lock might be taken again */
2317   if (index)
2318     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2319   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2320       demux->element_index, demux->index_id);
2321 }
2322
2323 static GstIndex *
2324 gst_qtdemux_get_index (GstElement * element)
2325 {
2326   GstIndex *result = NULL;
2327   GstQTDemux *demux = GST_QTDEMUX (element);
2328
2329   GST_OBJECT_LOCK (demux);
2330   if (demux->element_index)
2331     result = gst_object_ref (demux->element_index);
2332   GST_OBJECT_UNLOCK (demux);
2333
2334   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2335
2336   return result;
2337 }
2338 #endif
2339
2340 static void
2341 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2342 {
2343   g_free ((gpointer) stream->stco.data);
2344   stream->stco.data = NULL;
2345   g_free ((gpointer) stream->stsz.data);
2346   stream->stsz.data = NULL;
2347   g_free ((gpointer) stream->stsc.data);
2348   stream->stsc.data = NULL;
2349   g_free ((gpointer) stream->stts.data);
2350   stream->stts.data = NULL;
2351   g_free ((gpointer) stream->stss.data);
2352   stream->stss.data = NULL;
2353   g_free ((gpointer) stream->stps.data);
2354   stream->stps.data = NULL;
2355   g_free ((gpointer) stream->ctts.data);
2356   stream->ctts.data = NULL;
2357 }
2358
2359 static void
2360 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2361     QtDemuxStream * stream)
2362 {
2363   g_free (stream->segments);
2364   stream->segments = NULL;
2365   stream->segment_index = -1;
2366   stream->accumulated_base = 0;
2367 }
2368
2369 static void
2370 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2371     QtDemuxStream * stream)
2372 {
2373   g_free (stream->samples);
2374   stream->samples = NULL;
2375   gst_qtdemux_stbl_free (stream);
2376
2377   /* fragments */
2378   g_free (stream->ra_entries);
2379   stream->ra_entries = NULL;
2380   stream->n_ra_entries = 0;
2381
2382   stream->sample_index = -1;
2383   stream->stbl_index = -1;
2384   stream->n_samples = 0;
2385   stream->time_position = 0;
2386
2387   stream->n_samples_moof = 0;
2388   stream->duration_moof = 0;
2389   stream->duration_last_moof = 0;
2390 }
2391
2392 static void
2393 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2394 {
2395   if (stream->allocator)
2396     gst_object_unref (stream->allocator);
2397   while (stream->buffers) {
2398     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2399     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2400   }
2401   if (stream->rgb8_palette) {
2402     gst_memory_unref (stream->rgb8_palette);
2403     stream->rgb8_palette = NULL;
2404   }
2405
2406   if (stream->pending_tags)
2407     gst_tag_list_unref (stream->pending_tags);
2408   stream->pending_tags = NULL;
2409   g_free (stream->redirect_uri);
2410   stream->redirect_uri = NULL;
2411   stream->sent_eos = FALSE;
2412   stream->sparse = FALSE;
2413   stream->protected = FALSE;
2414   if (stream->protection_scheme_info) {
2415     if (stream->protection_scheme_type == FOURCC_cenc) {
2416       QtDemuxCencSampleSetInfo *info =
2417           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2418       if (info->default_properties)
2419         gst_structure_free (info->default_properties);
2420       if (info->crypto_info)
2421         g_ptr_array_free (info->crypto_info, TRUE);
2422     }
2423     g_free (stream->protection_scheme_info);
2424     stream->protection_scheme_info = NULL;
2425   }
2426   stream->protection_scheme_type = 0;
2427   stream->protection_scheme_version = 0;
2428   g_queue_foreach (&stream->protection_scheme_event_queue,
2429       (GFunc) gst_event_unref, NULL);
2430   g_queue_clear (&stream->protection_scheme_event_queue);
2431   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2432   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2433 }
2434
2435 static void
2436 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2437 {
2438   gst_qtdemux_stream_clear (qtdemux, stream);
2439   if (stream->caps)
2440     gst_caps_unref (stream->caps);
2441   stream->caps = NULL;
2442   if (stream->pad) {
2443     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2444     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2445   }
2446   g_free (stream);
2447 }
2448
2449 static void
2450 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2451 {
2452   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2453
2454   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2455   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2456   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2457   qtdemux->n_streams--;
2458 }
2459
2460 static GstStateChangeReturn
2461 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2462 {
2463   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2464   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2465
2466   switch (transition) {
2467     case GST_STATE_CHANGE_PAUSED_TO_READY:
2468       break;
2469     default:
2470       break;
2471   }
2472
2473   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2474
2475   switch (transition) {
2476     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2477       gst_qtdemux_reset (qtdemux, TRUE);
2478       break;
2479     }
2480     default:
2481       break;
2482   }
2483
2484   return result;
2485 }
2486
2487 static void
2488 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2489 {
2490   /* counts as header data */
2491   qtdemux->header_size += length;
2492
2493   /* only consider at least a sufficiently complete ftyp atom */
2494   if (length >= 20) {
2495     GstBuffer *buf;
2496
2497     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2498     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2499         GST_FOURCC_ARGS (qtdemux->major_brand));
2500     if (qtdemux->comp_brands)
2501       gst_buffer_unref (qtdemux->comp_brands);
2502     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2503     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2504   }
2505 }
2506
2507 static void
2508 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2509     GstTagList * xmptaglist)
2510 {
2511   /* Strip out bogus fields */
2512   if (xmptaglist) {
2513     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2514       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2515       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2516     } else {
2517       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2518     }
2519
2520     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2521
2522     /* prioritize native tags using _KEEP mode */
2523     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2524     gst_tag_list_unref (xmptaglist);
2525   }
2526 }
2527
2528 static void
2529 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2530     guint offset)
2531 {
2532   GstByteReader br;
2533   guint8 version;
2534   guint32 flags = 0;
2535   guint i;
2536   guint8 iv_size = 8;
2537   QtDemuxStream *stream;
2538   GstStructure *structure;
2539   QtDemuxCencSampleSetInfo *ss_info = NULL;
2540   const gchar *system_id;
2541   gboolean uses_sub_sample_encryption = FALSE;
2542
2543   if (qtdemux->n_streams == 0)
2544     return;
2545
2546   stream = qtdemux->streams[0];
2547
2548   structure = gst_caps_get_structure (stream->caps, 0);
2549   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2550     GST_WARNING_OBJECT (qtdemux,
2551         "Attempting PIFF box parsing on an unencrypted stream.");
2552     return;
2553   }
2554
2555   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2556       G_TYPE_STRING, &system_id, NULL);
2557   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2558
2559   stream->protected = TRUE;
2560   stream->protection_scheme_type = FOURCC_cenc;
2561
2562   if (!stream->protection_scheme_info)
2563     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2564
2565   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2566
2567   if (ss_info->default_properties)
2568     gst_structure_free (ss_info->default_properties);
2569
2570   ss_info->default_properties =
2571       gst_structure_new ("application/x-cenc",
2572       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2573
2574   if (ss_info->crypto_info) {
2575     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2576     g_ptr_array_free (ss_info->crypto_info, TRUE);
2577     ss_info->crypto_info = NULL;
2578   }
2579
2580   /* skip UUID */
2581   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2582
2583   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2584     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2585     return;
2586   }
2587
2588   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2589     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2590     return;
2591   }
2592
2593   if ((flags & 0x000001)) {
2594     guint32 algorithm_id = 0;
2595     const guint8 *kid;
2596     GstBuffer *kid_buf;
2597     gboolean is_encrypted = TRUE;
2598
2599     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2600       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2601       return;
2602     }
2603
2604     algorithm_id >>= 8;
2605     if (algorithm_id == 0) {
2606       is_encrypted = FALSE;
2607     } else if (algorithm_id == 1) {
2608       /* FIXME: maybe store this in properties? */
2609       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2610     } else if (algorithm_id == 2) {
2611       /* FIXME: maybe store this in properties? */
2612       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2613     }
2614
2615     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2616       return;
2617
2618     if (!gst_byte_reader_get_data (&br, 16, &kid))
2619       return;
2620
2621     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2622     gst_buffer_fill (kid_buf, 0, kid, 16);
2623     if (ss_info->default_properties)
2624       gst_structure_free (ss_info->default_properties);
2625     ss_info->default_properties =
2626         gst_structure_new ("application/x-cenc",
2627         "iv_size", G_TYPE_UINT, iv_size,
2628         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2629         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2630     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2631         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2632     gst_buffer_unref (kid_buf);
2633   } else if ((flags & 0x000002)) {
2634     uses_sub_sample_encryption = TRUE;
2635   }
2636
2637   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2638     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2639     return;
2640   }
2641
2642   ss_info->crypto_info =
2643       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2644       (GDestroyNotify) qtdemux_gst_structure_free);
2645
2646   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2647     GstStructure *properties;
2648     guint8 *data;
2649     GstBuffer *buf;
2650
2651     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2652     if (properties == NULL) {
2653       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2654       return;
2655     }
2656
2657     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2658       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2659       gst_structure_free (properties);
2660       return;
2661     }
2662     buf = gst_buffer_new_wrapped (data, iv_size);
2663     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2664     gst_buffer_unref (buf);
2665
2666     if (uses_sub_sample_encryption) {
2667       guint16 n_subsamples;
2668
2669       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2670           || n_subsamples == 0) {
2671         GST_ERROR_OBJECT (qtdemux,
2672             "failed to get subsample count for sample %u", i);
2673         gst_structure_free (properties);
2674         return;
2675       }
2676       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2677       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2678         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2679             i);
2680         gst_structure_free (properties);
2681         return;
2682       }
2683       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2684       gst_structure_set (properties,
2685           "subsample_count", G_TYPE_UINT, n_subsamples,
2686           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2687       gst_buffer_unref (buf);
2688     } else {
2689       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2690     }
2691
2692     g_ptr_array_add (ss_info->crypto_info, properties);
2693   }
2694 }
2695
2696 static void
2697 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2698 {
2699   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2700     0x97, 0xA9, 0x42, 0xE8,
2701     0x9C, 0x71, 0x99, 0x94,
2702     0x91, 0xE3, 0xAF, 0xAC
2703   };
2704   static const guint8 playready_uuid[] = {
2705     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2706     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2707   };
2708
2709   static const guint8 piff_sample_encryption_uuid[] = {
2710     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2711     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2712   };
2713
2714   guint offset;
2715
2716   /* counts as header data */
2717   qtdemux->header_size += length;
2718
2719   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2720
2721   if (length <= offset + 16) {
2722     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2723     return;
2724   }
2725
2726   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2727     GstBuffer *buf;
2728     GstTagList *taglist;
2729
2730     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2731         length - offset - 16, NULL);
2732     taglist = gst_tag_list_from_xmp_buffer (buf);
2733     gst_buffer_unref (buf);
2734
2735     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2736
2737   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2738     int len;
2739     const gunichar2 *s_utf16;
2740     char *contents;
2741
2742     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2743     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2744     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2745     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2746
2747     g_free (contents);
2748
2749     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2750         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2751         (NULL));
2752   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2753     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2754   } else {
2755     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2756         GST_READ_UINT32_LE (buffer + offset),
2757         GST_READ_UINT32_LE (buffer + offset + 4),
2758         GST_READ_UINT32_LE (buffer + offset + 8),
2759         GST_READ_UINT32_LE (buffer + offset + 12));
2760   }
2761 }
2762
2763 static void
2764 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2765 {
2766   GstSidxParser sidx_parser;
2767   GstIsoffParserResult res;
2768   guint consumed;
2769
2770   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2771
2772   res =
2773       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2774       &consumed);
2775   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2776   if (res == GST_ISOFF_QT_PARSER_DONE) {
2777     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2778   }
2779   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2780 }
2781
2782 /* caller verifies at least 8 bytes in buf */
2783 static void
2784 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2785     guint64 * plength, guint32 * pfourcc)
2786 {
2787   guint64 length;
2788   guint32 fourcc;
2789
2790   length = QT_UINT32 (data);
2791   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2792   fourcc = QT_FOURCC (data + 4);
2793   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2794
2795   if (length == 0) {
2796     length = G_MAXUINT64;
2797   } else if (length == 1 && size >= 16) {
2798     /* this means we have an extended size, which is the 64 bit value of
2799      * the next 8 bytes */
2800     length = QT_UINT64 (data + 8);
2801     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2802   }
2803
2804   if (plength)
2805     *plength = length;
2806   if (pfourcc)
2807     *pfourcc = fourcc;
2808 }
2809
2810 static gboolean
2811 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2812 {
2813   guint32 version = 0;
2814   GstClockTime duration = 0;
2815
2816   if (!gst_byte_reader_get_uint32_be (br, &version))
2817     goto failed;
2818
2819   version >>= 24;
2820   if (version == 1) {
2821     if (!gst_byte_reader_get_uint64_be (br, &duration))
2822       goto failed;
2823   } else {
2824     guint32 dur = 0;
2825
2826     if (!gst_byte_reader_get_uint32_be (br, &dur))
2827       goto failed;
2828     duration = dur;
2829   }
2830
2831   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2832   qtdemux->duration = duration;
2833
2834   return TRUE;
2835
2836 failed:
2837   {
2838     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2839     return FALSE;
2840   }
2841 }
2842
2843 static gboolean
2844 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2845     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2846 {
2847   if (!stream->parsed_trex && qtdemux->moov_node) {
2848     GNode *mvex, *trex;
2849     GstByteReader trex_data;
2850
2851     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2852     if (mvex) {
2853       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2854           &trex_data);
2855       while (trex) {
2856         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2857
2858         /* skip version/flags */
2859         if (!gst_byte_reader_skip (&trex_data, 4))
2860           goto next;
2861         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2862           goto next;
2863         if (id != stream->track_id)
2864           goto next;
2865         /* sample description index; ignore */
2866         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2867           goto next;
2868         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2869           goto next;
2870         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2871           goto next;
2872         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2873           goto next;
2874
2875         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2876             "duration %d,  size %d, flags 0x%x", stream->track_id,
2877             dur, size, flags);
2878
2879         stream->parsed_trex = TRUE;
2880         stream->def_sample_duration = dur;
2881         stream->def_sample_size = size;
2882         stream->def_sample_flags = flags;
2883
2884       next:
2885         /* iterate all siblings */
2886         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2887             &trex_data);
2888       }
2889     }
2890   }
2891
2892   *ds_duration = stream->def_sample_duration;
2893   *ds_size = stream->def_sample_size;
2894   *ds_flags = stream->def_sample_flags;
2895
2896   /* even then, above values are better than random ... */
2897   if (G_UNLIKELY (!stream->parsed_trex)) {
2898     GST_WARNING_OBJECT (qtdemux,
2899         "failed to find fragment defaults for stream %d", stream->track_id);
2900     return FALSE;
2901   }
2902
2903   return TRUE;
2904 }
2905
2906 /* This method should be called whenever a more accurate duration might
2907  * have been found. It will update all relevant variables if/where needed
2908  */
2909 static void
2910 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2911 {
2912   guint i;
2913   guint64 movdur;
2914   GstClockTime prevdur;
2915
2916   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2917
2918   if (movdur > qtdemux->duration) {
2919     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2920     GST_DEBUG_OBJECT (qtdemux,
2921         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2922         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2923     qtdemux->duration = movdur;
2924     GST_DEBUG_OBJECT (qtdemux,
2925         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2926         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2927         GST_TIME_ARGS (qtdemux->segment.stop));
2928     if (qtdemux->segment.duration == prevdur) {
2929       /* If the current segment has duration/stop identical to previous duration
2930        * update them also (because they were set at that point in time with
2931        * the wrong duration */
2932       /* We convert the value *from* the timescale version to avoid rounding errors */
2933       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2934       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2935       qtdemux->segment.duration = fixeddur;
2936       qtdemux->segment.stop = fixeddur;
2937     }
2938   }
2939   for (i = 0; i < qtdemux->n_streams; i++) {
2940     QtDemuxStream *stream = qtdemux->streams[i];
2941     if (stream) {
2942       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2943       if (movdur > stream->duration) {
2944         GST_DEBUG_OBJECT (qtdemux,
2945             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2946             GST_TIME_ARGS (duration));
2947         stream->duration = movdur;
2948         if (stream->dummy_segment) {
2949           /* Update all dummy values to new duration */
2950           stream->segments[0].stop_time = duration;
2951           stream->segments[0].duration = duration;
2952           stream->segments[0].media_stop = duration;
2953
2954           /* let downstream know we possibly have a new stop time */
2955           if (stream->segment_index != -1) {
2956             GstClockTime pos;
2957
2958             if (qtdemux->segment.rate >= 0) {
2959               pos = stream->segment.start;
2960             } else {
2961               pos = stream->segment.stop;
2962             }
2963
2964             gst_qtdemux_stream_update_segment (qtdemux, stream,
2965                 stream->segment_index, pos, NULL, NULL);
2966           }
2967         }
2968       }
2969     }
2970   }
2971 }
2972
2973 static gboolean
2974 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2975     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2976     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2977     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2978 {
2979   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2980   guint64 timestamp;
2981   gint32 data_offset = 0;
2982   guint32 flags = 0, first_flags = 0, samples_count = 0;
2983   gint i;
2984   guint8 *data;
2985   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2986   QtDemuxSample *sample;
2987   gboolean ismv = FALSE;
2988   gint64 initial_offset;
2989
2990   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2991       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2992       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2993       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2994
2995   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2996     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2997     return TRUE;
2998   }
2999
3000   /* presence of stss or not can't really tell us much,
3001    * and flags and so on tend to be marginally reliable in these files */
3002   if (stream->subtype == FOURCC_soun) {
3003     GST_DEBUG_OBJECT (qtdemux,
3004         "sound track in fragmented file; marking all keyframes");
3005     stream->all_keyframe = TRUE;
3006   }
3007
3008   if (!gst_byte_reader_skip (trun, 1) ||
3009       !gst_byte_reader_get_uint24_be (trun, &flags))
3010     goto fail;
3011
3012   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3013     goto fail;
3014
3015   if (flags & TR_DATA_OFFSET) {
3016     /* note this is really signed */
3017     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3018       goto fail;
3019     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3020     /* default base offset = first byte of moof */
3021     if (*base_offset == -1) {
3022       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3023       *base_offset = moof_offset;
3024     }
3025     *running_offset = *base_offset + data_offset;
3026   } else {
3027     /* if no offset at all, that would mean data starts at moof start,
3028      * which is a bit wrong and is ismv crappy way, so compensate
3029      * assuming data is in mdat following moof */
3030     if (*base_offset == -1) {
3031       *base_offset = moof_offset + moof_length + 8;
3032       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3033       ismv = TRUE;
3034     }
3035     if (*running_offset == -1)
3036       *running_offset = *base_offset;
3037   }
3038
3039   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3040       *running_offset);
3041   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3042       data_offset, flags, samples_count);
3043
3044   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3045     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3046       GST_DEBUG_OBJECT (qtdemux,
3047           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3048       flags ^= TR_FIRST_SAMPLE_FLAGS;
3049     } else {
3050       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3051         goto fail;
3052       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3053     }
3054   }
3055
3056   /* FIXME ? spec says other bits should also be checked to determine
3057    * entry size (and prefix size for that matter) */
3058   entry_size = 0;
3059   dur_offset = size_offset = 0;
3060   if (flags & TR_SAMPLE_DURATION) {
3061     GST_LOG_OBJECT (qtdemux, "entry duration present");
3062     dur_offset = entry_size;
3063     entry_size += 4;
3064   }
3065   if (flags & TR_SAMPLE_SIZE) {
3066     GST_LOG_OBJECT (qtdemux, "entry size present");
3067     size_offset = entry_size;
3068     entry_size += 4;
3069   }
3070   if (flags & TR_SAMPLE_FLAGS) {
3071     GST_LOG_OBJECT (qtdemux, "entry flags present");
3072     flags_offset = entry_size;
3073     entry_size += 4;
3074   }
3075   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3076     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3077     ct_offset = entry_size;
3078     entry_size += 4;
3079   }
3080
3081   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3082     goto fail;
3083   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3084
3085   if (stream->n_samples + samples_count >=
3086       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3087     goto index_too_big;
3088
3089   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3090       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3091       (stream->n_samples + samples_count) *
3092       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3093
3094   /* create a new array of samples if it's the first sample parsed */
3095   if (stream->n_samples == 0) {
3096     g_assert (stream->samples == NULL);
3097     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3098     /* or try to reallocate it with space enough to insert the new samples */
3099   } else
3100     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3101         stream->n_samples + samples_count);
3102   if (stream->samples == NULL)
3103     goto out_of_memory;
3104
3105   if (qtdemux->fragment_start != -1) {
3106     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3107     qtdemux->fragment_start = -1;
3108   } else {
3109     if (stream->n_samples == 0) {
3110       if (decode_ts > 0) {
3111         timestamp = decode_ts;
3112       } else if (stream->pending_seek != NULL) {
3113         /* if we don't have a timestamp from a tfdt box, we'll use the one
3114          * from the mfra seek table */
3115         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3116             GST_TIME_ARGS (stream->pending_seek->ts));
3117
3118         /* FIXME: this is not fully correct, the timestamp refers to the random
3119          * access sample refered to in the tfra entry, which may not necessarily
3120          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3121         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3122       } else {
3123         timestamp = 0;
3124       }
3125
3126       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3127       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3128           GST_TIME_ARGS (gst_ts));
3129     } else {
3130       /* subsequent fragments extend stream */
3131       timestamp =
3132           stream->samples[stream->n_samples - 1].timestamp +
3133           stream->samples[stream->n_samples - 1].duration;
3134
3135       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3136        * difference (1 sec.) between decode_ts and timestamp, prefer the
3137        * former */
3138       if (!qtdemux->upstream_format_is_time
3139           && ABSDIFF (decode_ts, timestamp) >
3140           MAX (stream->duration_last_moof / 2,
3141               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3142         GST_INFO_OBJECT (qtdemux,
3143             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3144             ") are significantly different (more than %" GST_TIME_FORMAT
3145             "), using decode_ts",
3146             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3147             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3148             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3149                     MAX (stream->duration_last_moof / 2,
3150                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3151         timestamp = decode_ts;
3152       }
3153
3154       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3155       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3156           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3157     }
3158   }
3159
3160   initial_offset = *running_offset;
3161
3162   sample = stream->samples + stream->n_samples;
3163   for (i = 0; i < samples_count; i++) {
3164     guint32 dur, size, sflags, ct;
3165
3166     /* first read sample data */
3167     if (flags & TR_SAMPLE_DURATION) {
3168       dur = QT_UINT32 (data + dur_offset);
3169     } else {
3170       dur = d_sample_duration;
3171     }
3172     if (flags & TR_SAMPLE_SIZE) {
3173       size = QT_UINT32 (data + size_offset);
3174     } else {
3175       size = d_sample_size;
3176     }
3177     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3178       if (i == 0) {
3179         sflags = first_flags;
3180       } else {
3181         sflags = d_sample_flags;
3182       }
3183     } else if (flags & TR_SAMPLE_FLAGS) {
3184       sflags = QT_UINT32 (data + flags_offset);
3185     } else {
3186       sflags = d_sample_flags;
3187     }
3188     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3189       ct = QT_UINT32 (data + ct_offset);
3190     } else {
3191       ct = 0;
3192     }
3193     data += entry_size;
3194
3195     /* fill the sample information */
3196     sample->offset = *running_offset;
3197     sample->pts_offset = ct;
3198     sample->size = size;
3199     sample->timestamp = timestamp;
3200     sample->duration = dur;
3201     /* sample-is-difference-sample */
3202     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3203      * now idea how it relates to bitfield other than massive LE/BE confusion */
3204     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3205     *running_offset += size;
3206     timestamp += dur;
3207     stream->duration_moof += dur;
3208     sample++;
3209   }
3210
3211   /* Update total duration if needed */
3212   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3213
3214   /* Pre-emptively figure out size of mdat based on trun information.
3215    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3216    * size, else we will still be able to use this when dealing with gap'ed
3217    * input */
3218   qtdemux->mdatleft = *running_offset - initial_offset;
3219
3220   stream->n_samples += samples_count;
3221   stream->n_samples_moof += samples_count;
3222
3223   if (stream->pending_seek != NULL)
3224     stream->pending_seek = NULL;
3225
3226   return TRUE;
3227
3228 fail:
3229   {
3230     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3231     return FALSE;
3232   }
3233 out_of_memory:
3234   {
3235     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3236         stream->n_samples);
3237     return FALSE;
3238   }
3239 index_too_big:
3240   {
3241     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3242         "be larger than %uMB (broken file?)", stream->n_samples,
3243         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3244     return FALSE;
3245   }
3246 }
3247
3248 /* find stream with @id */
3249 static inline QtDemuxStream *
3250 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3251 {
3252   QtDemuxStream *stream;
3253   gint i;
3254
3255   /* check */
3256   if (G_UNLIKELY (!id)) {
3257     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3258     return NULL;
3259   }
3260
3261   /* try to get it fast and simple */
3262   if (G_LIKELY (id <= qtdemux->n_streams)) {
3263     stream = qtdemux->streams[id - 1];
3264     if (G_LIKELY (stream->track_id == id))
3265       return stream;
3266   }
3267
3268   /* linear search otherwise */
3269   for (i = 0; i < qtdemux->n_streams; i++) {
3270     stream = qtdemux->streams[i];
3271     if (stream->track_id == id)
3272       return stream;
3273   }
3274   if (qtdemux->mss_mode) {
3275     /* mss should have only 1 stream anyway */
3276     return qtdemux->streams[0];
3277   }
3278
3279   return NULL;
3280 }
3281
3282 static gboolean
3283 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3284     guint32 * fragment_number)
3285 {
3286   if (!gst_byte_reader_skip (mfhd, 4))
3287     goto fail;
3288   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3289     goto fail;
3290   return TRUE;
3291 fail:
3292   {
3293     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3294     return FALSE;
3295   }
3296 }
3297
3298 static gboolean
3299 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3300     QtDemuxStream ** stream, guint32 * default_sample_duration,
3301     guint32 * default_sample_size, guint32 * default_sample_flags,
3302     gint64 * base_offset)
3303 {
3304   guint32 flags = 0;
3305   guint32 track_id = 0;
3306
3307   if (!gst_byte_reader_skip (tfhd, 1) ||
3308       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3309     goto invalid_track;
3310
3311   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3312     goto invalid_track;
3313
3314   *stream = qtdemux_find_stream (qtdemux, track_id);
3315   if (G_UNLIKELY (!*stream))
3316     goto unknown_stream;
3317
3318   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3319     *base_offset = qtdemux->moof_offset;
3320
3321   if (flags & TF_BASE_DATA_OFFSET)
3322     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3323       goto invalid_track;
3324
3325   /* obtain stream defaults */
3326   qtdemux_parse_trex (qtdemux, *stream,
3327       default_sample_duration, default_sample_size, default_sample_flags);
3328
3329   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3330   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3331     if (!gst_byte_reader_skip (tfhd, 4))
3332       goto invalid_track;
3333
3334   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3335     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3336       goto invalid_track;
3337
3338   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3339     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3340       goto invalid_track;
3341
3342   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3343     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3344       goto invalid_track;
3345
3346   return TRUE;
3347
3348 invalid_track:
3349   {
3350     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3351     return FALSE;
3352   }
3353 unknown_stream:
3354   {
3355     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3356     return TRUE;
3357   }
3358 }
3359
3360 static gboolean
3361 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3362     guint64 * decode_time)
3363 {
3364   guint32 version = 0;
3365
3366   if (!gst_byte_reader_get_uint32_be (br, &version))
3367     return FALSE;
3368
3369   version >>= 24;
3370   if (version == 1) {
3371     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3372       goto failed;
3373   } else {
3374     guint32 dec_time = 0;
3375     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3376       goto failed;
3377     *decode_time = dec_time;
3378   }
3379
3380   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3381       *decode_time);
3382
3383   return TRUE;
3384
3385 failed:
3386   {
3387     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3388     return FALSE;
3389   }
3390 }
3391
3392 /* Returns a pointer to a GstStructure containing the properties of
3393  * the stream sample identified by @sample_index. The caller must unref
3394  * the returned object after use. Returns NULL if unsuccessful. */
3395 static GstStructure *
3396 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3397     QtDemuxStream * stream, guint sample_index)
3398 {
3399   QtDemuxCencSampleSetInfo *info = NULL;
3400
3401   g_return_val_if_fail (stream != NULL, NULL);
3402   g_return_val_if_fail (stream->protected, NULL);
3403   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3404
3405   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3406
3407   /* Currently, cenc properties for groups of samples are not supported, so
3408    * simply return a copy of the default sample properties */
3409   return gst_structure_copy (info->default_properties);
3410 }
3411
3412 /* Parses the sizes of sample auxiliary information contained within a stream,
3413  * as given in a saiz box. Returns array of sample_count guint8 size values,
3414  * or NULL on failure */
3415 static guint8 *
3416 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3417     GstByteReader * br, guint32 * sample_count)
3418 {
3419   guint32 flags = 0;
3420   guint8 *info_sizes;
3421   guint8 default_info_size;
3422
3423   g_return_val_if_fail (qtdemux != NULL, NULL);
3424   g_return_val_if_fail (stream != NULL, NULL);
3425   g_return_val_if_fail (br != NULL, NULL);
3426   g_return_val_if_fail (sample_count != NULL, NULL);
3427
3428   if (!gst_byte_reader_get_uint32_be (br, &flags))
3429     return NULL;
3430
3431   if (flags & 0x1) {
3432     /* aux_info_type and aux_info_type_parameter are ignored */
3433     if (!gst_byte_reader_skip (br, 8))
3434       return NULL;
3435   }
3436
3437   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3438     return NULL;
3439   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3440
3441   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3442     return NULL;
3443   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3444
3445
3446   if (default_info_size == 0) {
3447     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3448       return NULL;
3449     }
3450   } else {
3451     info_sizes = g_new (guint8, *sample_count);
3452     memset (info_sizes, default_info_size, *sample_count);
3453   }
3454
3455   return info_sizes;
3456 }
3457
3458 /* Parses the offset of sample auxiliary information contained within a stream,
3459  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3460 static gboolean
3461 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3462     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3463     guint64 * offset)
3464 {
3465   guint8 version = 0;
3466   guint32 flags = 0;
3467   guint32 aux_info_type = 0;
3468   guint32 aux_info_type_parameter = 0;
3469   guint32 entry_count;
3470   guint32 off_32;
3471   guint64 off_64;
3472   const guint8 *aux_info_type_data = NULL;
3473
3474   g_return_val_if_fail (qtdemux != NULL, FALSE);
3475   g_return_val_if_fail (stream != NULL, FALSE);
3476   g_return_val_if_fail (br != NULL, FALSE);
3477   g_return_val_if_fail (offset != NULL, FALSE);
3478
3479   if (!gst_byte_reader_get_uint8 (br, &version))
3480     return FALSE;
3481
3482   if (!gst_byte_reader_get_uint24_be (br, &flags))
3483     return FALSE;
3484
3485   if (flags & 0x1) {
3486
3487     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3488       return FALSE;
3489     aux_info_type = QT_FOURCC (aux_info_type_data);
3490
3491     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3492       return FALSE;
3493   } else if (stream->protected) {
3494     aux_info_type = stream->protection_scheme_type;
3495   } else {
3496     aux_info_type = stream->fourcc;
3497   }
3498
3499   if (info_type)
3500     *info_type = aux_info_type;
3501   if (info_type_parameter)
3502     *info_type_parameter = aux_info_type_parameter;
3503
3504   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3505       "aux_info_type_parameter:  %#06x",
3506       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3507
3508   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3509     return FALSE;
3510
3511   if (entry_count != 1) {
3512     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3513     return FALSE;
3514   }
3515
3516   if (version == 0) {
3517     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3518       return FALSE;
3519     *offset = (guint64) off_32;
3520   } else {
3521     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3522       return FALSE;
3523     *offset = off_64;
3524   }
3525
3526   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3527   return TRUE;
3528 }
3529
3530 static void
3531 qtdemux_gst_structure_free (GstStructure * gststructure)
3532 {
3533   if (gststructure) {
3534     gst_structure_free (gststructure);
3535   }
3536 }
3537
3538 /* Parses auxiliary information relating to samples protected using Common
3539  * Encryption (cenc); the format of this information is defined in
3540  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3541 static gboolean
3542 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3543     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3544 {
3545   QtDemuxCencSampleSetInfo *ss_info = NULL;
3546   guint8 size;
3547   gint i;
3548
3549   g_return_val_if_fail (qtdemux != NULL, FALSE);
3550   g_return_val_if_fail (stream != NULL, FALSE);
3551   g_return_val_if_fail (br != NULL, FALSE);
3552   g_return_val_if_fail (stream->protected, FALSE);
3553   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3554
3555   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3556
3557   if (ss_info->crypto_info) {
3558     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3559     g_ptr_array_free (ss_info->crypto_info, TRUE);
3560   }
3561
3562   ss_info->crypto_info =
3563       g_ptr_array_new_full (sample_count,
3564       (GDestroyNotify) qtdemux_gst_structure_free);
3565
3566   for (i = 0; i < sample_count; ++i) {
3567     GstStructure *properties;
3568     guint16 n_subsamples = 0;
3569     guint8 *data;
3570     guint iv_size;
3571     GstBuffer *buf;
3572
3573     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3574     if (properties == NULL) {
3575       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3576       return FALSE;
3577     }
3578     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3579       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3580       gst_structure_free (properties);
3581       return FALSE;
3582     }
3583     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3584       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3585       gst_structure_free (properties);
3586       return FALSE;
3587     }
3588     buf = gst_buffer_new_wrapped (data, iv_size);
3589     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3590     gst_buffer_unref (buf);
3591     size = info_sizes[i];
3592     if (size > iv_size) {
3593       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3594           || !(n_subsamples > 0)) {
3595         gst_structure_free (properties);
3596         GST_ERROR_OBJECT (qtdemux,
3597             "failed to get subsample count for sample %u", i);
3598         return FALSE;
3599       }
3600       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3601       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3602         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3603             i);
3604         gst_structure_free (properties);
3605         return FALSE;
3606       }
3607       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3608       if (!buf) {
3609         gst_structure_free (properties);
3610         return FALSE;
3611       }
3612       gst_structure_set (properties,
3613           "subsample_count", G_TYPE_UINT, n_subsamples,
3614           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3615       gst_buffer_unref (buf);
3616     } else {
3617       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3618     }
3619     g_ptr_array_add (ss_info->crypto_info, properties);
3620   }
3621   return TRUE;
3622 }
3623
3624 /* Converts a UUID in raw byte form to a string representation, as defined in
3625  * RFC 4122. The caller takes ownership of the returned string and is
3626  * responsible for freeing it after use. */
3627 static gchar *
3628 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3629 {
3630   const guint8 *uuid = (const guint8 *) uuid_bytes;
3631
3632   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3633       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3634       uuid[0], uuid[1], uuid[2], uuid[3],
3635       uuid[4], uuid[5], uuid[6], uuid[7],
3636       uuid[8], uuid[9], uuid[10], uuid[11],
3637       uuid[12], uuid[13], uuid[14], uuid[15]);
3638 }
3639
3640 /* Parses a Protection System Specific Header box (pssh), as defined in the
3641  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3642  * information needed by a specific content protection system in order to
3643  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3644  * otherwise. */
3645 static gboolean
3646 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3647 {
3648   gchar *sysid_string;
3649   guint32 pssh_size = QT_UINT32 (node->data);
3650   GstBuffer *pssh = NULL;
3651   GstEvent *event = NULL;
3652   guint32 parent_box_type;
3653   gint i;
3654
3655   if (G_UNLIKELY (pssh_size < 32U)) {
3656     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3657     return FALSE;
3658   }
3659
3660   sysid_string =
3661       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3662
3663   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3664
3665   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3666   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3667       gst_buffer_get_size (pssh));
3668
3669   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3670
3671   /* Push an event containing the pssh box onto the queues of all streams. */
3672   event = gst_event_new_protection (sysid_string, pssh,
3673       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3674   for (i = 0; i < qtdemux->n_streams; ++i) {
3675     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3676         gst_event_ref (event));
3677   }
3678   g_free (sysid_string);
3679   gst_event_unref (event);
3680   gst_buffer_unref (pssh);
3681   return TRUE;
3682 }
3683
3684 static gboolean
3685 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3686     guint64 moof_offset, QtDemuxStream * stream)
3687 {
3688   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3689   GNode *uuid_node;
3690   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3691   GNode *saiz_node, *saio_node, *pssh_node;
3692   GstByteReader saiz_data, saio_data;
3693   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3694   gint64 base_offset, running_offset;
3695   guint32 frag_num;
3696
3697   /* NOTE @stream ignored */
3698
3699   moof_node = g_node_new ((guint8 *) buffer);
3700   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3701   qtdemux_node_dump (qtdemux, moof_node);
3702
3703   /* Get fragment number from mfhd and check it's valid */
3704   mfhd_node =
3705       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3706   if (mfhd_node == NULL)
3707     goto missing_mfhd;
3708   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3709     goto fail;
3710   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3711
3712   /* unknown base_offset to start with */
3713   base_offset = running_offset = -1;
3714   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3715   while (traf_node) {
3716     guint64 decode_time = 0;
3717
3718     /* Fragment Header node */
3719     tfhd_node =
3720         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3721         &tfhd_data);
3722     if (!tfhd_node)
3723       goto missing_tfhd;
3724     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3725             &ds_size, &ds_flags, &base_offset))
3726       goto missing_tfhd;
3727
3728     /* The following code assumes at most a single set of sample auxiliary
3729      * data in the fragment (consisting of a saiz box and a corresponding saio
3730      * box); in theory, however, there could be multiple sets of sample
3731      * auxiliary data in a fragment. */
3732     saiz_node =
3733         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3734         &saiz_data);
3735     if (saiz_node) {
3736       guint32 info_type = 0;
3737       guint64 offset = 0;
3738       guint32 info_type_parameter = 0;
3739
3740       g_free (qtdemux->cenc_aux_info_sizes);
3741
3742       qtdemux->cenc_aux_info_sizes =
3743           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3744           &qtdemux->cenc_aux_sample_count);
3745       if (qtdemux->cenc_aux_info_sizes == NULL) {
3746         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3747         goto fail;
3748       }
3749       saio_node =
3750           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3751           &saio_data);
3752       if (!saio_node) {
3753         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3754         g_free (qtdemux->cenc_aux_info_sizes);
3755         qtdemux->cenc_aux_info_sizes = NULL;
3756         goto fail;
3757       }
3758
3759       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3760                   &info_type, &info_type_parameter, &offset))) {
3761         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3762         g_free (qtdemux->cenc_aux_info_sizes);
3763         qtdemux->cenc_aux_info_sizes = NULL;
3764         goto fail;
3765       }
3766       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3767         offset += (guint64) (base_offset - qtdemux->moof_offset);
3768       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3769         GstByteReader br;
3770         if (offset > length) {
3771           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3772           qtdemux->cenc_aux_info_offset = offset;
3773         } else {
3774           gst_byte_reader_init (&br, buffer + offset, length - offset);
3775           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3776                   qtdemux->cenc_aux_info_sizes,
3777                   qtdemux->cenc_aux_sample_count)) {
3778             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3779             g_free (qtdemux->cenc_aux_info_sizes);
3780             qtdemux->cenc_aux_info_sizes = NULL;
3781             goto fail;
3782           }
3783         }
3784       }
3785     }
3786
3787     tfdt_node =
3788         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3789         &tfdt_data);
3790     if (tfdt_node) {
3791       /* We'll use decode_time to interpolate timestamps
3792        * in case the input timestamps are missing */
3793       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3794
3795       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3796           " (%" GST_TIME_FORMAT ")", decode_time,
3797           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3798
3799       /* Discard the fragment buffer timestamp info to avoid using it.
3800        * Rely on tfdt instead as it is more accurate than the timestamp
3801        * that is fetched from a manifest/playlist and is usually
3802        * less accurate. */
3803       qtdemux->fragment_start = -1;
3804     }
3805
3806     if (G_UNLIKELY (!stream)) {
3807       /* we lost track of offset, we'll need to regain it,
3808        * but can delay complaining until later or avoid doing so altogether */
3809       base_offset = -2;
3810       goto next;
3811     }
3812     if (G_UNLIKELY (base_offset < -1))
3813       goto lost_offset;
3814
3815     if (qtdemux->upstream_format_is_time)
3816       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3817
3818     /* initialise moof sample data */
3819     stream->n_samples_moof = 0;
3820     stream->duration_last_moof = stream->duration_moof;
3821     stream->duration_moof = 0;
3822
3823     /* Track Run node */
3824     trun_node =
3825         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3826         &trun_data);
3827     while (trun_node) {
3828       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3829           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3830           &running_offset, decode_time);
3831       /* iterate all siblings */
3832       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3833           &trun_data);
3834     }
3835
3836     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3837     if (uuid_node) {
3838       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3839       guint32 box_length = QT_UINT32 (uuid_buffer);
3840
3841       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3842     }
3843
3844     /* if no new base_offset provided for next traf,
3845      * base is end of current traf */
3846     base_offset = running_offset;
3847     running_offset = -1;
3848
3849     if (stream->n_samples_moof && stream->duration_moof)
3850       stream->new_caps = TRUE;
3851
3852   next:
3853     /* iterate all siblings */
3854     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3855   }
3856
3857   /* parse any protection system info */
3858   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3859   while (pssh_node) {
3860     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3861     qtdemux_parse_pssh (qtdemux, pssh_node);
3862     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3863   }
3864
3865   g_node_destroy (moof_node);
3866   return TRUE;
3867
3868 missing_tfhd:
3869   {
3870     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3871     goto fail;
3872   }
3873 missing_mfhd:
3874   {
3875     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3876     goto fail;
3877   }
3878 lost_offset:
3879   {
3880     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3881     goto fail;
3882   }
3883 fail:
3884   {
3885     g_node_destroy (moof_node);
3886     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3887         (_("This file is corrupt and cannot be played.")), (NULL));
3888     return FALSE;
3889   }
3890 }
3891
3892 #if 0
3893 /* might be used if some day we actually use mfra & co
3894  * for random access to fragments,
3895  * but that will require quite some modifications and much less relying
3896  * on a sample array */
3897 #endif
3898
3899 static gboolean
3900 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3901 {
3902   QtDemuxStream *stream;
3903   guint32 ver_flags, track_id, len, num_entries, i;
3904   guint value_size, traf_size, trun_size, sample_size;
3905   guint64 time = 0, moof_offset = 0;
3906 #if 0
3907   GstBuffer *buf = NULL;
3908   GstFlowReturn ret;
3909 #endif
3910   GstByteReader tfra;
3911
3912   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3913
3914   if (!gst_byte_reader_skip (&tfra, 8))
3915     return FALSE;
3916
3917   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3918     return FALSE;
3919
3920   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3921       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3922       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3923     return FALSE;
3924
3925   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3926
3927   stream = qtdemux_find_stream (qtdemux, track_id);
3928   if (stream == NULL)
3929     goto unknown_trackid;
3930
3931   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3932   sample_size = (len & 3) + 1;
3933   trun_size = ((len & 12) >> 2) + 1;
3934   traf_size = ((len & 48) >> 4) + 1;
3935
3936   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3937       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3938
3939   if (num_entries == 0)
3940     goto no_samples;
3941
3942   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3943           value_size + value_size + traf_size + trun_size + sample_size))
3944     goto corrupt_file;
3945
3946   g_free (stream->ra_entries);
3947   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3948   stream->n_ra_entries = num_entries;
3949
3950   for (i = 0; i < num_entries; i++) {
3951     qt_atom_parser_get_offset (&tfra, value_size, &time);
3952     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3953     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3954     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3955     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3956
3957     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3958
3959     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3960         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3961
3962     stream->ra_entries[i].ts = time;
3963     stream->ra_entries[i].moof_offset = moof_offset;
3964
3965     /* don't want to go through the entire file and read all moofs at startup */
3966 #if 0
3967     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3968     if (ret != GST_FLOW_OK)
3969       goto corrupt_file;
3970     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3971         moof_offset, stream);
3972     gst_buffer_unref (buf);
3973 #endif
3974   }
3975
3976   check_update_duration (qtdemux, time);
3977
3978   return TRUE;
3979
3980 /* ERRORS */
3981 unknown_trackid:
3982   {
3983     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3984     return FALSE;
3985   }
3986 corrupt_file:
3987   {
3988     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3989     return FALSE;
3990   }
3991 no_samples:
3992   {
3993     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3994     return FALSE;
3995   }
3996 }
3997
3998 static gboolean
3999 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4000 {
4001   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4002   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4003   GstBuffer *mfro = NULL, *mfra = NULL;
4004   GstFlowReturn flow;
4005   gboolean ret = FALSE;
4006   GNode *mfra_node, *tfra_node;
4007   guint64 mfra_offset = 0;
4008   guint32 fourcc, mfra_size;
4009   gint64 len;
4010
4011   /* query upstream size in bytes */
4012   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4013     goto size_query_failed;
4014
4015   /* mfro box should be at the very end of the file */
4016   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4017   if (flow != GST_FLOW_OK)
4018     goto exit;
4019
4020   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4021
4022   fourcc = QT_FOURCC (mfro_map.data + 4);
4023   if (fourcc != FOURCC_mfro)
4024     goto exit;
4025
4026   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4027   if (mfro_map.size < 16)
4028     goto invalid_mfro_size;
4029
4030   mfra_size = QT_UINT32 (mfro_map.data + 12);
4031   if (mfra_size >= len)
4032     goto invalid_mfra_size;
4033
4034   mfra_offset = len - mfra_size;
4035
4036   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4037       mfra_offset, mfra_size);
4038
4039   /* now get and parse mfra box */
4040   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4041   if (flow != GST_FLOW_OK)
4042     goto broken_file;
4043
4044   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4045
4046   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4047   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4048
4049   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4050
4051   while (tfra_node) {
4052     qtdemux_parse_tfra (qtdemux, tfra_node);
4053     /* iterate all siblings */
4054     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4055   }
4056   g_node_destroy (mfra_node);
4057
4058   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4059   ret = TRUE;
4060
4061 exit:
4062
4063   if (mfro) {
4064     if (mfro_map.memory != NULL)
4065       gst_buffer_unmap (mfro, &mfro_map);
4066     gst_buffer_unref (mfro);
4067   }
4068   if (mfra) {
4069     if (mfra_map.memory != NULL)
4070       gst_buffer_unmap (mfra, &mfra_map);
4071     gst_buffer_unref (mfra);
4072   }
4073   return ret;
4074
4075 /* ERRORS */
4076 size_query_failed:
4077   {
4078     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4079     goto exit;
4080   }
4081 invalid_mfro_size:
4082   {
4083     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4084     goto exit;
4085   }
4086 invalid_mfra_size:
4087   {
4088     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4089     goto exit;
4090   }
4091 broken_file:
4092   {
4093     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4094     goto exit;
4095   }
4096 }
4097
4098 static guint64
4099 add_offset (guint64 offset, guint64 advance)
4100 {
4101   /* Avoid 64-bit overflow by clamping */
4102   if (offset > G_MAXUINT64 - advance)
4103     return G_MAXUINT64;
4104   return offset + advance;
4105 }
4106
4107 static GstFlowReturn
4108 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4109 {
4110   guint64 length = 0;
4111   guint32 fourcc = 0;
4112   GstBuffer *buf = NULL;
4113   GstFlowReturn ret = GST_FLOW_OK;
4114   guint64 cur_offset = qtdemux->offset;
4115   GstMapInfo map;
4116
4117   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4118   if (G_UNLIKELY (ret != GST_FLOW_OK))
4119     goto beach;
4120   gst_buffer_map (buf, &map, GST_MAP_READ);
4121   if (G_LIKELY (map.size >= 8))
4122     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4123   gst_buffer_unmap (buf, &map);
4124   gst_buffer_unref (buf);
4125
4126   /* maybe we already got most we needed, so only consider this eof */
4127   if (G_UNLIKELY (length == 0)) {
4128     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4129         (_("Invalid atom size.")),
4130         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4131             GST_FOURCC_ARGS (fourcc)));
4132     ret = GST_FLOW_EOS;
4133     goto beach;
4134   }
4135
4136   switch (fourcc) {
4137     case FOURCC_moof:
4138       /* record for later parsing when needed */
4139       if (!qtdemux->moof_offset) {
4140         qtdemux->moof_offset = qtdemux->offset;
4141       }
4142       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4143         /* FIXME */
4144       } else {
4145         qtdemux->offset += length;      /* skip moof and keep going */
4146       }
4147       if (qtdemux->got_moov) {
4148         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4149         ret = GST_FLOW_EOS;
4150         goto beach;
4151       }
4152       break;
4153     case FOURCC_mdat:
4154     case FOURCC_free:
4155     case FOURCC_wide:
4156     case FOURCC_PICT:
4157     case FOURCC_pnot:
4158     {
4159       GST_LOG_OBJECT (qtdemux,
4160           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4161           GST_FOURCC_ARGS (fourcc), cur_offset);
4162       qtdemux->offset = add_offset (qtdemux->offset, length);
4163       break;
4164     }
4165     case FOURCC_moov:
4166     {
4167       GstBuffer *moov = NULL;
4168
4169       if (qtdemux->got_moov) {
4170         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4171         qtdemux->offset = add_offset (qtdemux->offset, length);
4172         goto beach;
4173       }
4174
4175       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4176       if (ret != GST_FLOW_OK)
4177         goto beach;
4178       gst_buffer_map (moov, &map, GST_MAP_READ);
4179
4180       if (length != map.size) {
4181         /* Some files have a 'moov' atom at the end of the file which contains
4182          * a terminal 'free' atom where the body of the atom is missing.
4183          * Check for, and permit, this special case.
4184          */
4185         if (map.size >= 8) {
4186           guint8 *final_data = map.data + (map.size - 8);
4187           guint32 final_length = QT_UINT32 (final_data);
4188           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4189
4190           if (final_fourcc == FOURCC_free
4191               && map.size + final_length - 8 == length) {
4192             /* Ok, we've found that special case. Allocate a new buffer with
4193              * that free atom actually present. */
4194             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4195             gst_buffer_fill (newmoov, 0, map.data, map.size);
4196             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4197             gst_buffer_unmap (moov, &map);
4198             gst_buffer_unref (moov);
4199             moov = newmoov;
4200             gst_buffer_map (moov, &map, GST_MAP_READ);
4201           }
4202         }
4203       }
4204
4205       if (length != map.size) {
4206         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4207             (_("This file is incomplete and cannot be played.")),
4208             ("We got less than expected (received %" G_GSIZE_FORMAT
4209                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4210                 (guint) length, cur_offset));
4211         gst_buffer_unmap (moov, &map);
4212         gst_buffer_unref (moov);
4213         ret = GST_FLOW_ERROR;
4214         goto beach;
4215       }
4216       qtdemux->offset += length;
4217
4218       qtdemux_parse_moov (qtdemux, map.data, length);
4219       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4220
4221       qtdemux_parse_tree (qtdemux);
4222       g_node_destroy (qtdemux->moov_node);
4223       gst_buffer_unmap (moov, &map);
4224       gst_buffer_unref (moov);
4225       qtdemux->moov_node = NULL;
4226       qtdemux->got_moov = TRUE;
4227
4228       break;
4229     }
4230     case FOURCC_ftyp:
4231     {
4232       GstBuffer *ftyp = NULL;
4233
4234       /* extract major brand; might come in handy for ISO vs QT issues */
4235       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4236       if (ret != GST_FLOW_OK)
4237         goto beach;
4238       qtdemux->offset += length;
4239       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4240       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4241       gst_buffer_unmap (ftyp, &map);
4242       gst_buffer_unref (ftyp);
4243       break;
4244     }
4245     case FOURCC_uuid:
4246     {
4247       GstBuffer *uuid = NULL;
4248
4249       /* uuid are extension atoms */
4250       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4251       if (ret != GST_FLOW_OK)
4252         goto beach;
4253       qtdemux->offset += length;
4254       gst_buffer_map (uuid, &map, GST_MAP_READ);
4255       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4256       gst_buffer_unmap (uuid, &map);
4257       gst_buffer_unref (uuid);
4258       break;
4259     }
4260     case FOURCC_sidx:
4261     {
4262       GstBuffer *sidx = NULL;
4263       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4264       if (ret != GST_FLOW_OK)
4265         goto beach;
4266       qtdemux->offset += length;
4267       gst_buffer_map (sidx, &map, GST_MAP_READ);
4268       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4269       gst_buffer_unmap (sidx, &map);
4270       gst_buffer_unref (sidx);
4271       break;
4272     }
4273     default:
4274     {
4275       GstBuffer *unknown = NULL;
4276
4277       GST_LOG_OBJECT (qtdemux,
4278           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4279           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4280           cur_offset);
4281       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4282       if (ret != GST_FLOW_OK)
4283         goto beach;
4284       gst_buffer_map (unknown, &map, GST_MAP_READ);
4285       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4286       gst_buffer_unmap (unknown, &map);
4287       gst_buffer_unref (unknown);
4288       qtdemux->offset += length;
4289       break;
4290     }
4291   }
4292
4293 beach:
4294   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4295     /* digested all data, show what we have */
4296     qtdemux_prepare_streams (qtdemux);
4297     ret = qtdemux_expose_streams (qtdemux);
4298
4299     qtdemux->state = QTDEMUX_STATE_MOVIE;
4300     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4301         qtdemux->state);
4302     return ret;
4303   }
4304   return ret;
4305 }
4306
4307 /* Seeks to the previous keyframe of the indexed stream and
4308  * aligns other streams with respect to the keyframe timestamp
4309  * of indexed stream. Only called in case of Reverse Playback
4310  */
4311 static GstFlowReturn
4312 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4313 {
4314   guint8 n = 0;
4315   guint32 seg_idx = 0, k_index = 0;
4316   guint32 ref_seg_idx, ref_k_index;
4317   GstClockTime k_pos = 0, last_stop = 0;
4318   QtDemuxSegment *seg = NULL;
4319   QtDemuxStream *ref_str = NULL;
4320   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4321   guint64 target_ts;
4322
4323   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4324    * and finally align all the other streams on that timestamp with their
4325    * respective keyframes */
4326   for (n = 0; n < qtdemux->n_streams; n++) {
4327     QtDemuxStream *str = qtdemux->streams[n];
4328
4329     /* No candidate yet, take the first stream */
4330     if (!ref_str) {
4331       ref_str = str;
4332       continue;
4333     }
4334
4335     /* So that stream has a segment, we prefer video streams */
4336     if (str->subtype == FOURCC_vide) {
4337       ref_str = str;
4338       break;
4339     }
4340   }
4341
4342   if (G_UNLIKELY (!ref_str)) {
4343     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4344     goto eos;
4345   }
4346
4347   if (G_UNLIKELY (!ref_str->from_sample)) {
4348     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4349     goto eos;
4350   }
4351
4352   /* So that stream has been playing from from_sample to to_sample. We will
4353    * get the timestamp of the previous sample and search for a keyframe before
4354    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4355   if (ref_str->subtype == FOURCC_vide) {
4356     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4357         ref_str->from_sample - 1);
4358   } else {
4359     if (ref_str->from_sample >= 10)
4360       k_index = ref_str->from_sample - 10;
4361     else
4362       k_index = 0;
4363   }
4364
4365   target_ts =
4366       ref_str->samples[k_index].timestamp +
4367       ref_str->samples[k_index].pts_offset;
4368
4369   /* get current segment for that stream */
4370   seg = &ref_str->segments[ref_str->segment_index];
4371   /* Use segment start in original timescale for comparisons */
4372   seg_media_start_mov = seg->trak_media_start;
4373
4374   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4375       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4376       k_index, target_ts, seg_media_start_mov,
4377       GST_TIME_ARGS (seg->media_start));
4378
4379   /* Crawl back through segments to find the one containing this I frame */
4380   while (target_ts < seg_media_start_mov) {
4381     GST_DEBUG_OBJECT (qtdemux,
4382         "keyframe position (sample %u) is out of segment %u " " target %"
4383         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4384         ref_str->segment_index, target_ts, seg_media_start_mov);
4385
4386     if (G_UNLIKELY (!ref_str->segment_index)) {
4387       /* Reached first segment, let's consider it's EOS */
4388       goto eos;
4389     }
4390     ref_str->segment_index--;
4391     seg = &ref_str->segments[ref_str->segment_index];
4392     /* Use segment start in original timescale for comparisons */
4393     seg_media_start_mov = seg->trak_media_start;
4394   }
4395   /* Calculate time position of the keyframe and where we should stop */
4396   k_pos =
4397       QTSTREAMTIME_TO_GSTTIME (ref_str,
4398       target_ts - seg->trak_media_start) + seg->time;
4399   last_stop =
4400       QTSTREAMTIME_TO_GSTTIME (ref_str,
4401       ref_str->samples[ref_str->from_sample].timestamp -
4402       seg->trak_media_start) + seg->time;
4403
4404   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4405       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4406       k_index, GST_TIME_ARGS (k_pos));
4407
4408   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4409   qtdemux->segment.position = last_stop;
4410   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4411       GST_TIME_ARGS (last_stop));
4412
4413   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4414     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4415     goto eos;
4416   }
4417
4418   ref_seg_idx = ref_str->segment_index;
4419   ref_k_index = k_index;
4420
4421   /* Align them all on this */
4422   for (n = 0; n < qtdemux->n_streams; n++) {
4423     guint32 index = 0;
4424     GstClockTime seg_time = 0;
4425     QtDemuxStream *str = qtdemux->streams[n];
4426
4427     /* aligning reference stream again might lead to backing up to yet another
4428      * keyframe (due to timestamp rounding issues),
4429      * potentially putting more load on downstream; so let's try to avoid */
4430     if (str == ref_str) {
4431       seg_idx = ref_seg_idx;
4432       seg = &str->segments[seg_idx];
4433       k_index = ref_k_index;
4434       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4435           "sample at index %d", n, ref_str->segment_index, k_index);
4436     } else {
4437       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4438       GST_DEBUG_OBJECT (qtdemux,
4439           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4440           seg_idx, GST_TIME_ARGS (k_pos));
4441
4442       /* get segment and time in the segment */
4443       seg = &str->segments[seg_idx];
4444       seg_time = k_pos - seg->time;
4445
4446       /* get the media time in the segment.
4447        * No adjustment for empty "filler" segments */
4448       if (seg->media_start != GST_CLOCK_TIME_NONE)
4449         seg_time += seg->media_start;
4450
4451       /* get the index of the sample with media time */
4452       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4453       GST_DEBUG_OBJECT (qtdemux,
4454           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4455           GST_TIME_ARGS (seg_time), index);
4456
4457       /* find previous keyframe */
4458       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4459     }
4460
4461     /* Remember until where we want to go */
4462     str->to_sample = str->from_sample - 1;
4463     /* Define our time position */
4464     target_ts =
4465         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4466     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4467     if (seg->media_start != GST_CLOCK_TIME_NONE)
4468       str->time_position -= seg->media_start;
4469
4470     /* Now seek back in time */
4471     gst_qtdemux_move_stream (qtdemux, str, k_index);
4472     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4473         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4474         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4475   }
4476
4477   return GST_FLOW_OK;
4478
4479 eos:
4480   return GST_FLOW_EOS;
4481 }
4482
4483 /*
4484  * Gets the current qt segment start, stop and position for the
4485  * given time offset. This is used in update_segment()
4486  */
4487 static void
4488 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4489     QtDemuxStream * stream, GstClockTime offset,
4490     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4491 {
4492   GstClockTime seg_time;
4493   GstClockTime start, stop, time;
4494   QtDemuxSegment *segment;
4495
4496   segment = &stream->segments[stream->segment_index];
4497
4498   /* get time in this segment */
4499   seg_time = (offset - segment->time) * segment->rate;
4500
4501   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4502       GST_TIME_ARGS (seg_time));
4503
4504   if (G_UNLIKELY (seg_time > segment->duration)) {
4505     GST_LOG_OBJECT (stream->pad,
4506         "seg_time > segment->duration %" GST_TIME_FORMAT,
4507         GST_TIME_ARGS (segment->duration));
4508     seg_time = segment->duration;
4509   }
4510
4511   /* qtdemux->segment.stop is in outside-time-realm, whereas
4512    * segment->media_stop is in track-time-realm.
4513    *
4514    * In order to compare the two, we need to bring segment.stop
4515    * into the track-time-realm
4516    *
4517    * FIXME - does this comment still hold? Don't see any conversion here */
4518
4519   stop = qtdemux->segment.stop;
4520   if (stop == GST_CLOCK_TIME_NONE)
4521     stop = qtdemux->segment.duration;
4522   if (stop == GST_CLOCK_TIME_NONE)
4523     stop = segment->media_stop;
4524   else
4525     stop =
4526         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4527
4528   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4529     start = segment->time + seg_time;
4530     time = offset;
4531     stop = start - seg_time + segment->duration;
4532   } else if (qtdemux->segment.rate >= 0) {
4533     start = MIN (segment->media_start + seg_time, stop);
4534     time = offset;
4535   } else {
4536     if (segment->media_start >= qtdemux->segment.start) {
4537       time = segment->time;
4538     } else {
4539       time = segment->time + (qtdemux->segment.start - segment->media_start);
4540     }
4541
4542     start = MAX (segment->media_start, qtdemux->segment.start);
4543     stop = MIN (segment->media_start + seg_time, stop);
4544   }
4545
4546   *_start = start;
4547   *_stop = stop;
4548   *_time = time;
4549 }
4550
4551 /*
4552  * Updates the qt segment used for the stream and pushes a new segment event
4553  * downstream on this stream's pad.
4554  */
4555 static gboolean
4556 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4557     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4558     GstClockTime * _stop)
4559 {
4560   QtDemuxSegment *segment;
4561   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4562   gdouble rate;
4563   GstEvent *event;
4564
4565   /* update the current segment */
4566   stream->segment_index = seg_idx;
4567
4568   /* get the segment */
4569   segment = &stream->segments[seg_idx];
4570
4571   if (G_UNLIKELY (offset < segment->time)) {
4572     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4573         GST_TIME_ARGS (segment->time));
4574     return FALSE;
4575   }
4576
4577   /* segment lies beyond total indicated duration */
4578   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4579           segment->time > qtdemux->segment.duration)) {
4580     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4581         " < segment->time %" GST_TIME_FORMAT,
4582         GST_TIME_ARGS (qtdemux->segment.duration),
4583         GST_TIME_ARGS (segment->time));
4584     return FALSE;
4585   }
4586
4587   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4588       &start, &stop, &time);
4589
4590   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4591       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4592       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4593
4594   /* combine global rate with that of the segment */
4595   rate = segment->rate * qtdemux->segment.rate;
4596
4597   /* Copy flags from main segment */
4598   stream->segment.flags = qtdemux->segment.flags;
4599
4600   /* update the segment values used for clipping */
4601   stream->segment.offset = qtdemux->segment.offset;
4602   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4603   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4604   stream->segment.rate = rate;
4605   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4606       stream->cslg_shift);
4607   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4608       stream->cslg_shift);
4609   stream->segment.time = time;
4610   stream->segment.position = stream->segment.start;
4611
4612   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4613       &stream->segment);
4614
4615   /* now prepare and send the segment */
4616   if (stream->pad) {
4617     event = gst_event_new_segment (&stream->segment);
4618     if (qtdemux->segment_seqnum) {
4619       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4620     }
4621     gst_pad_push_event (stream->pad, event);
4622     /* assume we can send more data now */
4623     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4624     /* clear to send tags on this pad now */
4625     gst_qtdemux_push_tags (qtdemux, stream);
4626   }
4627
4628   if (_start)
4629     *_start = start;
4630   if (_stop)
4631     *_stop = stop;
4632
4633   return TRUE;
4634 }
4635
4636 /* activate the given segment number @seg_idx of @stream at time @offset.
4637  * @offset is an absolute global position over all the segments.
4638  *
4639  * This will push out a NEWSEGMENT event with the right values and
4640  * position the stream index to the first decodable sample before
4641  * @offset.
4642  */
4643 static gboolean
4644 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4645     guint32 seg_idx, GstClockTime offset)
4646 {
4647   QtDemuxSegment *segment;
4648   guint32 index, kf_index;
4649   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4650
4651   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4652       seg_idx, GST_TIME_ARGS (offset));
4653
4654   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4655           &start, &stop))
4656     return FALSE;
4657
4658   segment = &stream->segments[stream->segment_index];
4659
4660   /* in the fragmented case, we pick a fragment that starts before our
4661    * desired position and rely on downstream to wait for a keyframe
4662    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4663    * tfra entries tells us which trun/sample the key unit is in, but we don't
4664    * make use of this additional information at the moment) */
4665   if (qtdemux->fragmented) {
4666     stream->to_sample = G_MAXUINT32;
4667     return TRUE;
4668   }
4669
4670   /* We don't need to look for a sample in push-based */
4671   if (!qtdemux->pullbased)
4672     return TRUE;
4673
4674   /* and move to the keyframe before the indicated media time of the
4675    * segment */
4676   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4677     if (qtdemux->segment.rate >= 0) {
4678       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4679       stream->to_sample = G_MAXUINT32;
4680       GST_DEBUG_OBJECT (stream->pad,
4681           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4682           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4683           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4684     } else {
4685       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4686       stream->to_sample = index;
4687       GST_DEBUG_OBJECT (stream->pad,
4688           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4689           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4690           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4691     }
4692   } else {
4693     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4694         "this is an empty segment");
4695     return TRUE;
4696   }
4697
4698   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4699    * encountered an error and printed a message so we return appropriately */
4700   if (index == -1)
4701     return FALSE;
4702
4703   /* we're at the right spot */
4704   if (index == stream->sample_index) {
4705     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4706     return TRUE;
4707   }
4708
4709   /* find keyframe of the target index */
4710   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4711
4712 /* *INDENT-OFF* */
4713 /* indent does stupid stuff with stream->samples[].timestamp */
4714
4715   /* if we move forwards, we don't have to go back to the previous
4716    * keyframe since we already sent that. We can also just jump to
4717    * the keyframe right before the target index if there is one. */
4718   if (index > stream->sample_index) {
4719     /* moving forwards check if we move past a keyframe */
4720     if (kf_index > stream->sample_index) {
4721       GST_DEBUG_OBJECT (stream->pad,
4722            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4723            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4724            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4725       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4726     } else {
4727       GST_DEBUG_OBJECT (stream->pad,
4728           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4729           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4730           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4731     }
4732   } else {
4733     GST_DEBUG_OBJECT (stream->pad,
4734         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4735         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4736         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4737     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4738   }
4739
4740 /* *INDENT-ON* */
4741
4742   return TRUE;
4743 }
4744
4745 /* prepare to get the current sample of @stream, getting essential values.
4746  *
4747  * This function will also prepare and send the segment when needed.
4748  *
4749  * Return FALSE if the stream is EOS.
4750  *
4751  * PULL-BASED
4752  */
4753 static gboolean
4754 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4755     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4756     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4757     gboolean * keyframe)
4758 {
4759   QtDemuxSample *sample;
4760   GstClockTime time_position;
4761   guint32 seg_idx;
4762
4763   g_return_val_if_fail (stream != NULL, FALSE);
4764
4765   time_position = stream->time_position;
4766   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4767     goto eos;
4768
4769   seg_idx = stream->segment_index;
4770   if (G_UNLIKELY (seg_idx == -1)) {
4771     /* find segment corresponding to time_position if we are looking
4772      * for a segment. */
4773     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4774   }
4775
4776   /* different segment, activate it, sample_index will be set. */
4777   if (G_UNLIKELY (stream->segment_index != seg_idx))
4778     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4779
4780   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4781                   segment_index]))) {
4782     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4783
4784     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4785         " prepare empty sample");
4786
4787     *empty = TRUE;
4788     *pts = *dts = time_position;
4789     *duration = seg->duration - (time_position - seg->time);
4790
4791     return TRUE;
4792   }
4793
4794   *empty = FALSE;
4795
4796   if (stream->sample_index == -1)
4797     stream->sample_index = 0;
4798
4799   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4800       stream->sample_index, stream->n_samples);
4801
4802   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4803     if (!qtdemux->fragmented)
4804       goto eos;
4805
4806     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4807     do {
4808       GstFlowReturn flow;
4809
4810       GST_OBJECT_LOCK (qtdemux);
4811       flow = qtdemux_add_fragmented_samples (qtdemux);
4812       GST_OBJECT_UNLOCK (qtdemux);
4813
4814       if (flow != GST_FLOW_OK)
4815         goto eos;
4816     }
4817     while (stream->sample_index >= stream->n_samples);
4818   }
4819
4820   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4821     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4822         stream->sample_index);
4823     return FALSE;
4824   }
4825
4826   /* now get the info for the sample we're at */
4827   sample = &stream->samples[stream->sample_index];
4828
4829   *dts = QTSAMPLE_DTS (stream, sample);
4830   *pts = QTSAMPLE_PTS (stream, sample);
4831   *offset = sample->offset;
4832   *size = sample->size;
4833   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4834   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4835
4836   return TRUE;
4837
4838   /* special cases */
4839 eos:
4840   {
4841     stream->time_position = GST_CLOCK_TIME_NONE;
4842     return FALSE;
4843   }
4844 }
4845
4846 /* move to the next sample in @stream.
4847  *
4848  * Moves to the next segment when needed.
4849  */
4850 static void
4851 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4852 {
4853   QtDemuxSample *sample;
4854   QtDemuxSegment *segment;
4855
4856   /* get current segment */
4857   segment = &stream->segments[stream->segment_index];
4858
4859   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4860     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4861     goto next_segment;
4862   }
4863
4864   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4865     /* Mark the stream as EOS */
4866     GST_DEBUG_OBJECT (qtdemux,
4867         "reached max allowed sample %u, mark EOS", stream->to_sample);
4868     stream->time_position = GST_CLOCK_TIME_NONE;
4869     return;
4870   }
4871
4872   /* move to next sample */
4873   stream->sample_index++;
4874   stream->offset_in_sample = 0;
4875
4876   /* reached the last sample, we need the next segment */
4877   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4878     goto next_segment;
4879
4880   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4881     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4882         stream->sample_index);
4883     return;
4884   }
4885
4886   /* get next sample */
4887   sample = &stream->samples[stream->sample_index];
4888
4889   /* see if we are past the segment */
4890   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4891     goto next_segment;
4892
4893   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4894     /* inside the segment, update time_position, looks very familiar to
4895      * GStreamer segments, doesn't it? */
4896     stream->time_position =
4897         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4898   } else {
4899     /* not yet in segment, time does not yet increment. This means
4900      * that we are still prerolling keyframes to the decoder so it can
4901      * decode the first sample of the segment. */
4902     stream->time_position = segment->time;
4903   }
4904   return;
4905
4906   /* move to the next segment */
4907 next_segment:
4908   {
4909     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4910
4911     if (stream->segment_index == stream->n_segments - 1) {
4912       /* are we at the end of the last segment, we're EOS */
4913       stream->time_position = GST_CLOCK_TIME_NONE;
4914     } else {
4915       /* else we're only at the end of the current segment */
4916       stream->time_position = segment->stop_time;
4917     }
4918     /* make sure we select a new segment */
4919
4920     /* accumulate previous segments */
4921     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4922       stream->accumulated_base +=
4923           (stream->segment.stop -
4924           stream->segment.start) / ABS (stream->segment.rate);
4925
4926     stream->segment_index = -1;
4927   }
4928 }
4929
4930 static void
4931 gst_qtdemux_sync_streams (GstQTDemux * demux)
4932 {
4933   gint i;
4934
4935   if (demux->n_streams <= 1)
4936     return;
4937
4938   for (i = 0; i < demux->n_streams; i++) {
4939     QtDemuxStream *stream;
4940     GstClockTime end_time;
4941
4942     stream = demux->streams[i];
4943
4944     if (!stream->pad)
4945       continue;
4946
4947     /* TODO advance time on subtitle streams here, if any some day */
4948
4949     /* some clips/trailers may have unbalanced streams at the end,
4950      * so send EOS on shorter stream to prevent stalling others */
4951
4952     /* do not mess with EOS if SEGMENT seeking */
4953     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4954       continue;
4955
4956     if (demux->pullbased) {
4957       /* loop mode is sample time based */
4958       if (!STREAM_IS_EOS (stream))
4959         continue;
4960     } else {
4961       /* push mode is byte position based */
4962       if (stream->n_samples &&
4963           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4964         continue;
4965     }
4966
4967     if (stream->sent_eos)
4968       continue;
4969
4970     /* only act if some gap */
4971     end_time = stream->segments[stream->n_segments - 1].stop_time;
4972     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4973         ", stream end: %" GST_TIME_FORMAT,
4974         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4975     if (GST_CLOCK_TIME_IS_VALID (end_time)
4976         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4977       GstEvent *event;
4978
4979       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4980           GST_PAD_NAME (stream->pad));
4981       stream->sent_eos = TRUE;
4982       event = gst_event_new_eos ();
4983       if (demux->segment_seqnum)
4984         gst_event_set_seqnum (event, demux->segment_seqnum);
4985       gst_pad_push_event (stream->pad, event);
4986     }
4987   }
4988 }
4989
4990 /* EOS and NOT_LINKED need to be combined. This means that we return:
4991  *
4992  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4993  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4994  */
4995 static GstFlowReturn
4996 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4997     GstFlowReturn ret)
4998 {
4999   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5000
5001   if (stream->pad)
5002     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5003         ret);
5004   else
5005     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5006
5007   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5008   return ret;
5009 }
5010
5011 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5012  * completely clipped
5013  *
5014  * Should be used only with raw buffers */
5015 static GstBuffer *
5016 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5017     GstBuffer * buf)
5018 {
5019   guint64 start, stop, cstart, cstop, diff;
5020   GstClockTime pts, duration;
5021   gsize size, osize;
5022   gint num_rate, denom_rate;
5023   gint frame_size;
5024   gboolean clip_data;
5025   guint offset;
5026
5027   osize = size = gst_buffer_get_size (buf);
5028   offset = 0;
5029
5030   /* depending on the type, setup the clip parameters */
5031   if (stream->subtype == FOURCC_soun) {
5032     frame_size = stream->bytes_per_frame;
5033     num_rate = GST_SECOND;
5034     denom_rate = (gint) stream->rate;
5035     clip_data = TRUE;
5036   } else if (stream->subtype == FOURCC_vide) {
5037     frame_size = size;
5038     num_rate = stream->fps_n;
5039     denom_rate = stream->fps_d;
5040     clip_data = FALSE;
5041   } else
5042     goto wrong_type;
5043
5044   if (frame_size <= 0)
5045     goto bad_frame_size;
5046
5047   /* we can only clip if we have a valid pts */
5048   pts = GST_BUFFER_PTS (buf);
5049   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5050     goto no_pts;
5051
5052   duration = GST_BUFFER_DURATION (buf);
5053
5054   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5055     duration =
5056         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5057   }
5058
5059   start = pts;
5060   stop = start + duration;
5061
5062   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5063               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5064     goto clipped;
5065
5066   /* see if some clipping happened */
5067   diff = cstart - start;
5068   if (diff > 0) {
5069     pts += diff;
5070     duration -= diff;
5071
5072     if (clip_data) {
5073       /* bring clipped time to samples and to bytes */
5074       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5075       diff *= frame_size;
5076
5077       GST_DEBUG_OBJECT (qtdemux,
5078           "clipping start to %" GST_TIME_FORMAT " %"
5079           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5080
5081       offset = diff;
5082       size -= diff;
5083     }
5084   }
5085   diff = stop - cstop;
5086   if (diff > 0) {
5087     duration -= diff;
5088
5089     if (clip_data) {
5090       /* bring clipped time to samples and then to bytes */
5091       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5092       diff *= frame_size;
5093       GST_DEBUG_OBJECT (qtdemux,
5094           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5095           " bytes", GST_TIME_ARGS (cstop), diff);
5096       size -= diff;
5097     }
5098   }
5099
5100   if (offset != 0 || size != osize)
5101     gst_buffer_resize (buf, offset, size);
5102
5103   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5104   GST_BUFFER_PTS (buf) = pts;
5105   GST_BUFFER_DURATION (buf) = duration;
5106
5107   return buf;
5108
5109   /* dropped buffer */
5110 wrong_type:
5111   {
5112     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5113     return buf;
5114   }
5115 bad_frame_size:
5116   {
5117     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5118     return buf;
5119   }
5120 no_pts:
5121   {
5122     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5123     return buf;
5124   }
5125 clipped:
5126   {
5127     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5128     gst_buffer_unref (buf);
5129     return NULL;
5130   }
5131 }
5132
5133 static GstBuffer *
5134 gst_qtdemux_align_buffer (GstQTDemux * demux,
5135     GstBuffer * buffer, gsize alignment)
5136 {
5137   GstMapInfo map;
5138
5139   gst_buffer_map (buffer, &map, GST_MAP_READ);
5140
5141   if (map.size < sizeof (guintptr)) {
5142     gst_buffer_unmap (buffer, &map);
5143     return buffer;
5144   }
5145
5146   if (((guintptr) map.data) & (alignment - 1)) {
5147     GstBuffer *new_buffer;
5148     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5149
5150     new_buffer = gst_buffer_new_allocate (NULL,
5151         gst_buffer_get_size (buffer), &params);
5152
5153     /* Copy data "by hand", so ensure alignment is kept: */
5154     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5155
5156     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5157     GST_DEBUG_OBJECT (demux,
5158         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5159         alignment);
5160
5161     gst_buffer_unmap (buffer, &map);
5162     gst_buffer_unref (buffer);
5163
5164     return new_buffer;
5165   }
5166
5167   gst_buffer_unmap (buffer, &map);
5168   return buffer;
5169 }
5170
5171 /* the input buffer metadata must be writable,
5172  * but time/duration etc not yet set and need not be preserved */
5173 static GstBuffer *
5174 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5175     GstBuffer * buf)
5176 {
5177   GstMapInfo map;
5178   guint nsize = 0;
5179   gchar *str;
5180
5181   /* not many cases for now */
5182   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5183     /* send a one time dvd clut event */
5184     if (stream->pending_event && stream->pad)
5185       gst_pad_push_event (stream->pad, stream->pending_event);
5186     stream->pending_event = NULL;
5187   }
5188
5189   if (G_UNLIKELY (stream->subtype != FOURCC_text
5190           && stream->subtype != FOURCC_sbtl &&
5191           stream->subtype != FOURCC_subp)) {
5192     return buf;
5193   }
5194
5195   gst_buffer_map (buf, &map, GST_MAP_READ);
5196
5197   /* empty buffer is sent to terminate previous subtitle */
5198   if (map.size <= 2) {
5199     gst_buffer_unmap (buf, &map);
5200     gst_buffer_unref (buf);
5201     return NULL;
5202   }
5203   if (stream->subtype == FOURCC_subp) {
5204     /* That's all the processing needed for subpictures */
5205     gst_buffer_unmap (buf, &map);
5206     return buf;
5207   }
5208
5209   nsize = GST_READ_UINT16_BE (map.data);
5210   nsize = MIN (nsize, map.size - 2);
5211
5212   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5213       nsize, map.size);
5214
5215   /* takes care of UTF-8 validation or UTF-16 recognition,
5216    * no other encoding expected */
5217   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5218   gst_buffer_unmap (buf, &map);
5219   if (str) {
5220     gst_buffer_unref (buf);
5221     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5222   } else {
5223     /* this should not really happen unless the subtitle is corrupted */
5224     gst_buffer_unref (buf);
5225     buf = NULL;
5226   }
5227
5228   /* FIXME ? convert optional subsequent style info to markup */
5229
5230   return buf;
5231 }
5232
5233 /* Sets a buffer's attributes properly and pushes it downstream.
5234  * Also checks for additional actions and custom processing that may
5235  * need to be done first.
5236  */
5237 static GstFlowReturn
5238 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5239     QtDemuxStream * stream, GstBuffer * buf,
5240     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5241     gboolean keyframe, GstClockTime position, guint64 byte_position)
5242 {
5243   GstFlowReturn ret = GST_FLOW_OK;
5244
5245   /* offset the timestamps according to the edit list */
5246
5247   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5248     gchar *url;
5249     GstMapInfo map;
5250
5251     gst_buffer_map (buf, &map, GST_MAP_READ);
5252     url = g_strndup ((gchar *) map.data, map.size);
5253     gst_buffer_unmap (buf, &map);
5254     if (url != NULL && strlen (url) != 0) {
5255       /* we have RTSP redirect now */
5256       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5257           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5258               gst_structure_new ("redirect",
5259                   "new-location", G_TYPE_STRING, url, NULL)));
5260       qtdemux->posted_redirect = TRUE;
5261     } else {
5262       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5263           "posting");
5264     }
5265     g_free (url);
5266   }
5267
5268   /* position reporting */
5269   if (qtdemux->segment.rate >= 0) {
5270     qtdemux->segment.position = position;
5271     gst_qtdemux_sync_streams (qtdemux);
5272   }
5273
5274   if (G_UNLIKELY (!stream->pad)) {
5275     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5276     gst_buffer_unref (buf);
5277     goto exit;
5278   }
5279
5280   /* send out pending buffers */
5281   while (stream->buffers) {
5282     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5283
5284     if (G_UNLIKELY (stream->discont)) {
5285       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5286       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5287       stream->discont = FALSE;
5288     } else {
5289       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5290     }
5291
5292     if (stream->alignment > 1)
5293       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5294     gst_pad_push (stream->pad, buffer);
5295
5296     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5297   }
5298
5299   /* we're going to modify the metadata */
5300   buf = gst_buffer_make_writable (buf);
5301
5302   if (G_UNLIKELY (stream->need_process))
5303     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5304
5305   if (!buf) {
5306     goto exit;
5307   }
5308
5309   GST_BUFFER_DTS (buf) = dts;
5310   GST_BUFFER_PTS (buf) = pts;
5311   GST_BUFFER_DURATION (buf) = duration;
5312   GST_BUFFER_OFFSET (buf) = -1;
5313   GST_BUFFER_OFFSET_END (buf) = -1;
5314
5315   if (G_UNLIKELY (stream->rgb8_palette))
5316     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5317
5318   if (G_UNLIKELY (stream->padding)) {
5319     gst_buffer_resize (buf, stream->padding, -1);
5320   }
5321 #if 0
5322   if (G_UNLIKELY (qtdemux->element_index)) {
5323     GstClockTime stream_time;
5324
5325     stream_time =
5326         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5327         timestamp);
5328     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5329       GST_LOG_OBJECT (qtdemux,
5330           "adding association %" GST_TIME_FORMAT "-> %"
5331           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5332       gst_index_add_association (qtdemux->element_index,
5333           qtdemux->index_id,
5334           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5335           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5336           GST_FORMAT_BYTES, byte_position, NULL);
5337     }
5338   }
5339 #endif
5340
5341   if (stream->need_clip)
5342     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5343
5344   if (G_UNLIKELY (buf == NULL))
5345     goto exit;
5346
5347   if (G_UNLIKELY (stream->discont)) {
5348     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5349     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5350     stream->discont = FALSE;
5351   } else {
5352     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5353   }
5354
5355   if (!keyframe) {
5356     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5357     stream->on_keyframe = FALSE;
5358   } else {
5359     stream->on_keyframe = TRUE;
5360   }
5361
5362
5363   GST_LOG_OBJECT (qtdemux,
5364       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5365       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5366       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5367       GST_PAD_NAME (stream->pad));
5368
5369   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5370     GstStructure *crypto_info;
5371     QtDemuxCencSampleSetInfo *info =
5372         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5373     gint index;
5374     GstEvent *event;
5375
5376     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5377       gst_pad_push_event (stream->pad, event);
5378     }
5379
5380     if (info->crypto_info == NULL) {
5381       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5382       gst_buffer_unref (buf);
5383       goto exit;
5384     }
5385
5386     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
5387     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5388       /* steal structure from array */
5389       crypto_info = g_ptr_array_index (info->crypto_info, index);
5390       g_ptr_array_index (info->crypto_info, index) = NULL;
5391       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
5392       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5393         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5394     }
5395   }
5396
5397   if (stream->alignment > 1)
5398     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5399
5400   ret = gst_pad_push (stream->pad, buf);
5401
5402   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5403     /* mark position in stream, we'll need this to know when to send GAP event */
5404     stream->segment.position = pts + duration;
5405   }
5406
5407 exit:
5408   return ret;
5409 }
5410
5411 static const QtDemuxRandomAccessEntry *
5412 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5413     GstClockTime pos, gboolean after)
5414 {
5415   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5416   guint n_entries = stream->n_ra_entries;
5417   guint i;
5418
5419   /* we assume the table is sorted */
5420   for (i = 0; i < n_entries; ++i) {
5421     if (entries[i].ts > pos)
5422       break;
5423   }
5424
5425   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5426    * probably okay to assume that the index lists the very first fragment */
5427   if (i == 0)
5428     return &entries[0];
5429
5430   if (after)
5431     return &entries[i];
5432   else
5433     return &entries[i - 1];
5434 }
5435
5436 static gboolean
5437 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5438 {
5439   const QtDemuxRandomAccessEntry *best_entry = NULL;
5440   guint i;
5441
5442   GST_OBJECT_LOCK (qtdemux);
5443
5444   g_assert (qtdemux->n_streams > 0);
5445
5446   for (i = 0; i < qtdemux->n_streams; i++) {
5447     const QtDemuxRandomAccessEntry *entry;
5448     QtDemuxStream *stream;
5449     gboolean is_audio_or_video;
5450
5451     stream = qtdemux->streams[i];
5452
5453     g_free (stream->samples);
5454     stream->samples = NULL;
5455     stream->n_samples = 0;
5456     stream->stbl_index = -1;    /* no samples have yet been parsed */
5457     stream->sample_index = -1;
5458
5459     if (stream->ra_entries == NULL)
5460       continue;
5461
5462     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5463       is_audio_or_video = TRUE;
5464     else
5465       is_audio_or_video = FALSE;
5466
5467     entry =
5468         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5469         stream->time_position, !is_audio_or_video);
5470
5471     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5472         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5473
5474     stream->pending_seek = entry;
5475
5476     /* decide position to jump to just based on audio/video tracks, not subs */
5477     if (!is_audio_or_video)
5478       continue;
5479
5480     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5481       best_entry = entry;
5482   }
5483
5484   if (best_entry == NULL) {
5485     GST_OBJECT_UNLOCK (qtdemux);
5486     return FALSE;
5487   }
5488
5489   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5490       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5491       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5492       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5493
5494   qtdemux->moof_offset = best_entry->moof_offset;
5495
5496   qtdemux_add_fragmented_samples (qtdemux);
5497
5498   GST_OBJECT_UNLOCK (qtdemux);
5499   return TRUE;
5500 }
5501
5502 static GstFlowReturn
5503 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5504 {
5505   GstFlowReturn ret = GST_FLOW_OK;
5506   GstBuffer *buf = NULL;
5507   QtDemuxStream *stream;
5508   GstClockTime min_time;
5509   guint64 offset = 0;
5510   GstClockTime dts = GST_CLOCK_TIME_NONE;
5511   GstClockTime pts = GST_CLOCK_TIME_NONE;
5512   GstClockTime duration = 0;
5513   gboolean keyframe = FALSE;
5514   guint sample_size = 0;
5515   gboolean empty = 0;
5516   guint size;
5517   gint index;
5518   gint i;
5519
5520   gst_qtdemux_push_pending_newsegment (qtdemux);
5521
5522   if (qtdemux->fragmented_seek_pending) {
5523     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5524     gst_qtdemux_do_fragmented_seek (qtdemux);
5525     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5526     qtdemux->fragmented_seek_pending = FALSE;
5527   }
5528
5529   /* Figure out the next stream sample to output, min_time is expressed in
5530    * global time and runs over the edit list segments. */
5531   min_time = G_MAXUINT64;
5532   index = -1;
5533   for (i = 0; i < qtdemux->n_streams; i++) {
5534     GstClockTime position;
5535
5536     stream = qtdemux->streams[i];
5537     position = stream->time_position;
5538
5539     /* position of -1 is EOS */
5540     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5541       min_time = position;
5542       index = i;
5543     }
5544   }
5545   /* all are EOS */
5546   if (G_UNLIKELY (index == -1)) {
5547     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5548     goto eos;
5549   }
5550
5551   /* check for segment end */
5552   if (G_UNLIKELY (qtdemux->segment.stop != -1
5553           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5554               || (qtdemux->segment.rate < 0
5555                   && qtdemux->segment.start > min_time))
5556           && qtdemux->streams[index]->on_keyframe)) {
5557     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5558     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5559     goto eos_stream;
5560   }
5561
5562   /* gap events for subtitle streams */
5563   for (i = 0; i < qtdemux->n_streams; i++) {
5564     stream = qtdemux->streams[i];
5565     if (stream->pad && (stream->subtype == FOURCC_subp
5566             || stream->subtype == FOURCC_text
5567             || stream->subtype == FOURCC_sbtl)) {
5568       /* send one second gap events until the stream catches up */
5569       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5570       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5571           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5572           stream->segment.position + GST_SECOND < min_time) {
5573         GstEvent *gap =
5574             gst_event_new_gap (stream->segment.position, GST_SECOND);
5575         gst_pad_push_event (stream->pad, gap);
5576         stream->segment.position += GST_SECOND;
5577       }
5578     }
5579   }
5580
5581   stream = qtdemux->streams[index];
5582   if (stream->new_caps) {
5583     gst_qtdemux_configure_stream (qtdemux, stream);
5584     qtdemux_do_allocation (qtdemux, stream);
5585   }
5586
5587   /* fetch info for the current sample of this stream */
5588   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5589               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5590     goto eos_stream;
5591
5592   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5593   if (G_UNLIKELY (qtdemux->
5594           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5595     if (stream->subtype == FOURCC_vide && !keyframe) {
5596       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5597       goto next;
5598     }
5599   }
5600
5601   GST_DEBUG_OBJECT (qtdemux,
5602       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5603       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5604       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5605       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5606
5607   if (G_UNLIKELY (empty)) {
5608     /* empty segment, push a gap and move to the next one */
5609     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5610     stream->segment.position = pts + duration;
5611     goto next;
5612   }
5613
5614   /* hmm, empty sample, skip and move to next sample */
5615   if (G_UNLIKELY (sample_size <= 0))
5616     goto next;
5617
5618   /* last pushed sample was out of boundary, goto next sample */
5619   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5620     goto next;
5621
5622   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5623     size = sample_size;
5624   } else {
5625     GST_DEBUG_OBJECT (qtdemux,
5626         "size %d larger than stream max_buffer_size %d, trimming",
5627         sample_size, stream->max_buffer_size);
5628     size =
5629         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5630   }
5631
5632   if (qtdemux->cenc_aux_info_offset > 0) {
5633     GstMapInfo map;
5634     GstByteReader br;
5635     GstBuffer *aux_info = NULL;
5636
5637     /* pull the data stored before the sample */
5638     ret =
5639         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5640         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5641     if (G_UNLIKELY (ret != GST_FLOW_OK))
5642       goto beach;
5643     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5644     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5645     gst_byte_reader_init (&br, map.data + 8, map.size);
5646     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5647             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5648       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5649       gst_buffer_unmap (aux_info, &map);
5650       gst_buffer_unref (aux_info);
5651       ret = GST_FLOW_ERROR;
5652       goto beach;
5653     }
5654     gst_buffer_unmap (aux_info, &map);
5655     gst_buffer_unref (aux_info);
5656   }
5657
5658   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5659       offset);
5660
5661   if (stream->use_allocator) {
5662     /* if we have a per-stream allocator, use it */
5663     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5664   }
5665
5666   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5667       size, &buf);
5668   if (G_UNLIKELY (ret != GST_FLOW_OK))
5669     goto beach;
5670
5671   if (size != sample_size) {
5672     pts += gst_util_uint64_scale_int (GST_SECOND,
5673         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5674     dts += gst_util_uint64_scale_int (GST_SECOND,
5675         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5676     duration = gst_util_uint64_scale_int (GST_SECOND,
5677         size / stream->bytes_per_frame, stream->timescale);
5678   }
5679
5680   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5681       dts, pts, duration, keyframe, min_time, offset);
5682
5683   if (size != sample_size) {
5684     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5685     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5686
5687     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5688         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5689     if (time_position >= segment->media_start) {
5690       /* inside the segment, update time_position, looks very familiar to
5691        * GStreamer segments, doesn't it? */
5692       stream->time_position = (time_position - segment->media_start) +
5693           segment->time;
5694     } else {
5695       /* not yet in segment, time does not yet increment. This means
5696        * that we are still prerolling keyframes to the decoder so it can
5697        * decode the first sample of the segment. */
5698       stream->time_position = segment->time;
5699     }
5700   }
5701
5702   /* combine flows */
5703   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5704   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5705    * we have no more data for the pad to push */
5706   if (ret == GST_FLOW_EOS)
5707     ret = GST_FLOW_OK;
5708
5709   stream->offset_in_sample += size;
5710   if (stream->offset_in_sample >= sample_size) {
5711     gst_qtdemux_advance_sample (qtdemux, stream);
5712   }
5713   goto beach;
5714
5715 next:
5716   gst_qtdemux_advance_sample (qtdemux, stream);
5717
5718 beach:
5719   return ret;
5720
5721   /* special cases */
5722 eos:
5723   {
5724     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5725     ret = GST_FLOW_EOS;
5726     goto beach;
5727   }
5728 eos_stream:
5729   {
5730     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5731     /* EOS will be raised if all are EOS */
5732     ret = GST_FLOW_OK;
5733     goto beach;
5734   }
5735 }
5736
5737 static void
5738 gst_qtdemux_loop (GstPad * pad)
5739 {
5740   GstQTDemux *qtdemux;
5741   guint64 cur_offset;
5742   GstFlowReturn ret;
5743
5744   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5745
5746   cur_offset = qtdemux->offset;
5747   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5748       cur_offset, qt_demux_state_string (qtdemux->state));
5749
5750   switch (qtdemux->state) {
5751     case QTDEMUX_STATE_INITIAL:
5752     case QTDEMUX_STATE_HEADER:
5753       ret = gst_qtdemux_loop_state_header (qtdemux);
5754       break;
5755     case QTDEMUX_STATE_MOVIE:
5756       ret = gst_qtdemux_loop_state_movie (qtdemux);
5757       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5758         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5759       }
5760       break;
5761     default:
5762       /* ouch */
5763       goto invalid_state;
5764   }
5765
5766   /* if something went wrong, pause */
5767   if (ret != GST_FLOW_OK)
5768     goto pause;
5769
5770 done:
5771   gst_object_unref (qtdemux);
5772   return;
5773
5774   /* ERRORS */
5775 invalid_state:
5776   {
5777     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5778         (NULL), ("streaming stopped, invalid state"));
5779     gst_pad_pause_task (pad);
5780     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5781     goto done;
5782   }
5783 pause:
5784   {
5785     const gchar *reason = gst_flow_get_name (ret);
5786
5787     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5788
5789     gst_pad_pause_task (pad);
5790
5791     /* fatal errors need special actions */
5792     /* check EOS */
5793     if (ret == GST_FLOW_EOS) {
5794       if (qtdemux->n_streams == 0) {
5795         /* we have no streams, post an error */
5796         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5797       }
5798       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5799         gint64 stop;
5800
5801         if ((stop = qtdemux->segment.stop) == -1)
5802           stop = qtdemux->segment.duration;
5803
5804         if (qtdemux->segment.rate >= 0) {
5805           GstMessage *message;
5806           GstEvent *event;
5807
5808           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5809           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5810               GST_FORMAT_TIME, stop);
5811           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5812           if (qtdemux->segment_seqnum) {
5813             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5814             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5815           }
5816           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5817           gst_qtdemux_push_event (qtdemux, event);
5818         } else {
5819           GstMessage *message;
5820           GstEvent *event;
5821
5822           /*  For Reverse Playback */
5823           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5824           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5825               GST_FORMAT_TIME, qtdemux->segment.start);
5826           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5827               qtdemux->segment.start);
5828           if (qtdemux->segment_seqnum) {
5829             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5830             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5831           }
5832           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5833           gst_qtdemux_push_event (qtdemux, event);
5834         }
5835       } else {
5836         GstEvent *event;
5837
5838         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5839         event = gst_event_new_eos ();
5840         if (qtdemux->segment_seqnum)
5841           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5842         gst_qtdemux_push_event (qtdemux, event);
5843       }
5844     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5845       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
5846       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5847     }
5848     goto done;
5849   }
5850 }
5851
5852 /*
5853  * has_next_entry
5854  *
5855  * Returns if there are samples to be played.
5856  */
5857 static gboolean
5858 has_next_entry (GstQTDemux * demux)
5859 {
5860   QtDemuxStream *stream;
5861   int i;
5862
5863   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5864
5865   for (i = 0; i < demux->n_streams; i++) {
5866     stream = demux->streams[i];
5867
5868     if (stream->sample_index == -1) {
5869       stream->sample_index = 0;
5870       stream->offset_in_sample = 0;
5871     }
5872
5873     if (stream->sample_index >= stream->n_samples) {
5874       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5875       continue;
5876     }
5877     GST_DEBUG_OBJECT (demux, "Found a sample");
5878     return TRUE;
5879   }
5880
5881   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5882   return FALSE;
5883 }
5884
5885 /*
5886  * next_entry_size
5887  *
5888  * Returns the size of the first entry at the current offset.
5889  * If -1, there are none (which means EOS or empty file).
5890  */
5891 static guint64
5892 next_entry_size (GstQTDemux * demux)
5893 {
5894   QtDemuxStream *stream;
5895   int i;
5896   int smallidx = -1;
5897   guint64 smalloffs = (guint64) - 1;
5898   QtDemuxSample *sample;
5899
5900   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5901       demux->offset);
5902
5903   for (i = 0; i < demux->n_streams; i++) {
5904     stream = demux->streams[i];
5905
5906     if (stream->sample_index == -1) {
5907       stream->sample_index = 0;
5908       stream->offset_in_sample = 0;
5909     }
5910
5911     if (stream->sample_index >= stream->n_samples) {
5912       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5913       continue;
5914     }
5915
5916     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5917       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5918           stream->sample_index);
5919       return -1;
5920     }
5921
5922     sample = &stream->samples[stream->sample_index];
5923
5924     GST_LOG_OBJECT (demux,
5925         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5926         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5927         sample->offset, sample->size);
5928
5929     if (((smalloffs == -1)
5930             || (sample->offset < smalloffs)) && (sample->size)) {
5931       smallidx = i;
5932       smalloffs = sample->offset;
5933     }
5934   }
5935
5936   GST_LOG_OBJECT (demux,
5937       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5938       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5939
5940   if (smallidx == -1)
5941     return -1;
5942
5943   stream = demux->streams[smallidx];
5944   sample = &stream->samples[stream->sample_index];
5945
5946   if (sample->offset >= demux->offset) {
5947     demux->todrop = sample->offset - demux->offset;
5948     return sample->size + demux->todrop;
5949   }
5950
5951   GST_DEBUG_OBJECT (demux,
5952       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5953   return -1;
5954 }
5955
5956 static void
5957 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5958 {
5959   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5960
5961   gst_element_post_message (GST_ELEMENT_CAST (demux),
5962       gst_message_new_element (GST_OBJECT_CAST (demux),
5963           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5964 }
5965
5966 static gboolean
5967 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5968 {
5969   GstEvent *event;
5970   gboolean res = 0;
5971
5972   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5973
5974   event =
5975       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5976       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5977       GST_SEEK_TYPE_NONE, -1);
5978
5979   /* store seqnum to drop flush events, they don't need to reach downstream */
5980   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5981   res = gst_pad_push_event (demux->sinkpad, event);
5982   demux->offset_seek_seqnum = 0;
5983
5984   return res;
5985 }
5986
5987 /* check for seekable upstream, above and beyond a mere query */
5988 static void
5989 gst_qtdemux_check_seekability (GstQTDemux * demux)
5990 {
5991   GstQuery *query;
5992   gboolean seekable = FALSE;
5993   gint64 start = -1, stop = -1;
5994
5995   if (demux->upstream_size)
5996     return;
5997
5998   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5999   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6000     GST_DEBUG_OBJECT (demux, "seeking query failed");
6001     goto done;
6002   }
6003
6004   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6005
6006   /* try harder to query upstream size if we didn't get it the first time */
6007   if (seekable && stop == -1) {
6008     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6009     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6010   }
6011
6012   /* if upstream doesn't know the size, it's likely that it's not seekable in
6013    * practice even if it technically may be seekable */
6014   if (seekable && (start != 0 || stop <= start)) {
6015     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6016     seekable = FALSE;
6017   }
6018
6019 done:
6020   gst_query_unref (query);
6021
6022   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6023       G_GUINT64_FORMAT ")", seekable, start, stop);
6024   demux->upstream_seekable = seekable;
6025   demux->upstream_size = seekable ? stop : -1;
6026 }
6027
6028 static void
6029 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6030 {
6031   g_return_if_fail (bytes <= demux->todrop);
6032
6033   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6034   gst_adapter_flush (demux->adapter, bytes);
6035   demux->neededbytes -= bytes;
6036   demux->offset += bytes;
6037   demux->todrop -= bytes;
6038 }
6039
6040 static void
6041 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6042 {
6043   if (G_UNLIKELY (demux->pending_newsegment)) {
6044     gint i;
6045
6046     gst_qtdemux_push_pending_newsegment (demux);
6047     /* clear to send tags on all streams */
6048     for (i = 0; i < demux->n_streams; i++) {
6049       QtDemuxStream *stream;
6050       stream = demux->streams[i];
6051       gst_qtdemux_push_tags (demux, stream);
6052       if (stream->sparse) {
6053         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6054         gst_pad_push_event (stream->pad,
6055             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6056       }
6057     }
6058   }
6059 }
6060
6061 static void
6062 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6063     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6064 {
6065   GstClockTime ts, dur;
6066   GstEvent *gap;
6067
6068   ts = pos;
6069   dur =
6070       stream->segments[segment_index].duration - (pos -
6071       stream->segments[segment_index].time);
6072   gap = gst_event_new_gap (ts, dur);
6073   stream->time_position += dur;
6074
6075   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6076       "segment: %" GST_PTR_FORMAT, gap);
6077   gst_pad_push_event (stream->pad, gap);
6078 }
6079
6080 static void
6081 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6082     QtDemuxStream * stream)
6083 {
6084   gint i;
6085
6086   /* Push any initial gap segments before proceeding to the
6087    * 'real' data */
6088   for (i = 0; i < stream->n_segments; i++) {
6089     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6090
6091     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6092       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6093           stream->time_position);
6094     } else {
6095       /* Only support empty segment at the beginning followed by
6096        * one non-empty segment, this was checked when parsing the
6097        * edts atom, arriving here is unexpected */
6098       g_assert (i + 1 == stream->n_segments);
6099       break;
6100     }
6101   }
6102 }
6103
6104 static GstFlowReturn
6105 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6106 {
6107   GstQTDemux *demux;
6108
6109   demux = GST_QTDEMUX (parent);
6110
6111   GST_DEBUG_OBJECT (demux,
6112       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6113       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6114       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6115       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6116       gst_buffer_get_size (inbuf), demux->offset);
6117
6118   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6119     gboolean is_gap_input = FALSE;
6120     gint i;
6121
6122     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6123
6124     for (i = 0; i < demux->n_streams; i++) {
6125       demux->streams[i]->discont = TRUE;
6126     }
6127
6128     /* Check if we can land back on our feet in the case where upstream is
6129      * handling the seeking/pushing of samples with gaps in between (like
6130      * in the case of trick-mode DASH for example) */
6131     if (demux->upstream_format_is_time
6132         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6133       gint i;
6134       for (i = 0; i < demux->n_streams; i++) {
6135         guint32 res;
6136         GST_LOG_OBJECT (demux,
6137             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6138             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6139         res =
6140             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6141             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6142         if (res != -1) {
6143           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6144           GST_LOG_OBJECT (demux,
6145               "Checking if sample %d from stream %d is valid (offset:%"
6146               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6147               sample->offset, sample->size);
6148           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6149             GST_LOG_OBJECT (demux,
6150                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6151                 res);
6152             is_gap_input = TRUE;
6153             /* We can go back to standard playback mode */
6154             demux->state = QTDEMUX_STATE_MOVIE;
6155             /* Remember which sample this stream is at */
6156             demux->streams[i]->sample_index = res;
6157             /* Finally update all push-based values to the expected values */
6158             demux->neededbytes = demux->streams[i]->samples[res].size;
6159             demux->todrop = 0;
6160             demux->offset = GST_BUFFER_OFFSET (inbuf);
6161           }
6162         }
6163       }
6164       if (!is_gap_input) {
6165         /* Reset state if it's a real discont */
6166         demux->neededbytes = 16;
6167         demux->state = QTDEMUX_STATE_INITIAL;
6168         demux->offset = GST_BUFFER_OFFSET (inbuf);
6169       }
6170     }
6171     /* Reverse fragmented playback, need to flush all we have before
6172      * consuming a new fragment.
6173      * The samples array have the timestamps calculated by accumulating the
6174      * durations but this won't work for reverse playback of fragments as
6175      * the timestamps of a subsequent fragment should be smaller than the
6176      * previously received one. */
6177     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6178       gst_qtdemux_process_adapter (demux, TRUE);
6179       for (i = 0; i < demux->n_streams; i++)
6180         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6181     }
6182   }
6183
6184   gst_adapter_push (demux->adapter, inbuf);
6185
6186   GST_DEBUG_OBJECT (demux,
6187       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6188       demux->neededbytes, gst_adapter_available (demux->adapter));
6189
6190   return gst_qtdemux_process_adapter (demux, FALSE);
6191 }
6192
6193 static GstFlowReturn
6194 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6195 {
6196   GstFlowReturn ret = GST_FLOW_OK;
6197
6198   /* we never really mean to buffer that much */
6199   if (demux->neededbytes == -1) {
6200     goto eos;
6201   }
6202
6203   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6204       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6205
6206 #ifndef GST_DISABLE_GST_DEBUG
6207     {
6208       guint64 discont_offset, distance_from_discont;
6209
6210       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6211       distance_from_discont =
6212           gst_adapter_distance_from_discont (demux->adapter);
6213
6214       GST_DEBUG_OBJECT (demux,
6215           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6216           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6217           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6218           demux->offset, discont_offset, distance_from_discont);
6219     }
6220 #endif
6221
6222     switch (demux->state) {
6223       case QTDEMUX_STATE_INITIAL:{
6224         const guint8 *data;
6225         guint32 fourcc;
6226         guint64 size;
6227
6228         gst_qtdemux_check_seekability (demux);
6229
6230         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6231
6232         /* get fourcc/length, set neededbytes */
6233         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6234             &size, &fourcc);
6235         gst_adapter_unmap (demux->adapter);
6236         data = NULL;
6237         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6238             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6239         if (size == 0) {
6240           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6241               (_("This file is invalid and cannot be played.")),
6242               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6243                   GST_FOURCC_ARGS (fourcc)));
6244           ret = GST_FLOW_ERROR;
6245           break;
6246         }
6247         if (fourcc == FOURCC_mdat) {
6248           gint next_entry = next_entry_size (demux);
6249           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6250             /* we have the headers, start playback */
6251             demux->state = QTDEMUX_STATE_MOVIE;
6252             demux->neededbytes = next_entry;
6253             demux->mdatleft = size;
6254           } else {
6255             /* no headers yet, try to get them */
6256             guint bs;
6257             gboolean res;
6258             guint64 old, target;
6259
6260           buffer_data:
6261             old = demux->offset;
6262             target = old + size;
6263
6264             /* try to jump over the atom with a seek */
6265             /* only bother if it seems worth doing so,
6266              * and avoids possible upstream/server problems */
6267             if (demux->upstream_seekable &&
6268                 demux->upstream_size > 4 * (1 << 20)) {
6269               res = qtdemux_seek_offset (demux, target);
6270             } else {
6271               GST_DEBUG_OBJECT (demux, "skipping seek");
6272               res = FALSE;
6273             }
6274
6275             if (res) {
6276               GST_DEBUG_OBJECT (demux, "seek success");
6277               /* remember the offset fo the first mdat so we can seek back to it
6278                * after we have the headers */
6279               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6280                 demux->first_mdat = old;
6281                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6282                     demux->first_mdat);
6283               }
6284               /* seek worked, continue reading */
6285               demux->offset = target;
6286               demux->neededbytes = 16;
6287               demux->state = QTDEMUX_STATE_INITIAL;
6288             } else {
6289               /* seek failed, need to buffer */
6290               demux->offset = old;
6291               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6292               /* there may be multiple mdat (or alike) buffers */
6293               /* sanity check */
6294               if (demux->mdatbuffer)
6295                 bs = gst_buffer_get_size (demux->mdatbuffer);
6296               else
6297                 bs = 0;
6298               if (size + bs > 10 * (1 << 20))
6299                 goto no_moov;
6300               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6301               demux->neededbytes = size;
6302               if (!demux->mdatbuffer)
6303                 demux->mdatoffset = demux->offset;
6304             }
6305           }
6306         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6307           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6308               (_("This file is invalid and cannot be played.")),
6309               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6310                   GST_FOURCC_ARGS (fourcc), size));
6311           ret = GST_FLOW_ERROR;
6312           break;
6313         } else {
6314           /* this means we already started buffering and still no moov header,
6315            * let's continue buffering everything till we get moov */
6316           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6317                   || fourcc == FOURCC_moof))
6318             goto buffer_data;
6319           demux->neededbytes = size;
6320           demux->state = QTDEMUX_STATE_HEADER;
6321         }
6322         break;
6323       }
6324       case QTDEMUX_STATE_HEADER:{
6325         const guint8 *data;
6326         guint32 fourcc;
6327
6328         GST_DEBUG_OBJECT (demux, "In header");
6329
6330         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6331
6332         /* parse the header */
6333         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6334             &fourcc);
6335         if (fourcc == FOURCC_moov) {
6336           gint n;
6337
6338           /* in usual fragmented setup we could try to scan for more
6339            * and end up at the the moov (after mdat) again */
6340           if (demux->got_moov && demux->n_streams > 0 &&
6341               (!demux->fragmented
6342                   || demux->last_moov_offset == demux->offset)) {
6343             GST_DEBUG_OBJECT (demux,
6344                 "Skipping moov atom as we have (this) one already");
6345           } else {
6346             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6347
6348             if (demux->got_moov && demux->fragmented) {
6349               GST_DEBUG_OBJECT (demux,
6350                   "Got a second moov, clean up data from old one");
6351               if (demux->moov_node)
6352                 g_node_destroy (demux->moov_node);
6353               demux->moov_node = NULL;
6354               demux->moov_node_compressed = NULL;
6355             } else {
6356               /* prepare newsegment to send when streaming actually starts */
6357               if (!demux->pending_newsegment) {
6358                 demux->pending_newsegment =
6359                     gst_event_new_segment (&demux->segment);
6360                 if (demux->segment_seqnum)
6361                   gst_event_set_seqnum (demux->pending_newsegment,
6362                       demux->segment_seqnum);
6363               }
6364             }
6365
6366             demux->last_moov_offset = demux->offset;
6367
6368             qtdemux_parse_moov (demux, data, demux->neededbytes);
6369             qtdemux_node_dump (demux, demux->moov_node);
6370             qtdemux_parse_tree (demux);
6371             qtdemux_prepare_streams (demux);
6372             if (!demux->got_moov)
6373               qtdemux_expose_streams (demux);
6374             else {
6375
6376               for (n = 0; n < demux->n_streams; n++) {
6377                 QtDemuxStream *stream = demux->streams[n];
6378
6379                 gst_qtdemux_configure_stream (demux, stream);
6380               }
6381             }
6382
6383             demux->got_moov = TRUE;
6384             gst_qtdemux_check_send_pending_segment (demux);
6385
6386             /* fragmented streams headers shouldn't contain edts atoms */
6387             if (!demux->fragmented) {
6388               for (n = 0; n < demux->n_streams; n++) {
6389                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6390                     demux->streams[n]);
6391               }
6392             }
6393
6394             g_node_destroy (demux->moov_node);
6395             demux->moov_node = NULL;
6396             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6397           }
6398         } else if (fourcc == FOURCC_moof) {
6399           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6400             guint64 dist = 0;
6401             GstClockTime prev_pts;
6402             guint64 prev_offset;
6403             guint64 adapter_discont_offset, adapter_discont_dist;
6404
6405             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6406
6407             /*
6408              * The timestamp of the moof buffer is relevant as some scenarios
6409              * won't have the initial timestamp in the atoms. Whenever a new
6410              * buffer has started, we get that buffer's PTS and use it as a base
6411              * timestamp for the trun entries.
6412              *
6413              * To keep track of the current buffer timestamp and starting point
6414              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6415              * from the beggining of the buffer, with the distance and demux->offset
6416              * we know if it is still the same buffer or not.
6417              */
6418             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6419             prev_offset = demux->offset - dist;
6420             if (demux->fragment_start_offset == -1
6421                 || prev_offset > demux->fragment_start_offset) {
6422               demux->fragment_start_offset = prev_offset;
6423               demux->fragment_start = prev_pts;
6424               GST_DEBUG_OBJECT (demux,
6425                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6426                   GST_TIME_FORMAT, demux->fragment_start_offset,
6427                   GST_TIME_ARGS (demux->fragment_start));
6428             }
6429
6430             /* We can't use prev_offset() here because this would require
6431              * upstream to set consistent and correct offsets on all buffers
6432              * since the discont. Nothing ever did that in the past and we
6433              * would break backwards compatibility here then.
6434              * Instead take the offset we had at the last discont and count
6435              * the bytes from there. This works with old code as there would
6436              * be no discont between moov and moof, and also works with
6437              * adaptivedemux which correctly sets offset and will set the
6438              * DISCONT flag accordingly when needed.
6439              *
6440              * We also only do this for upstream TIME segments as otherwise
6441              * there are potential backwards compatibility problems with
6442              * seeking in PUSH mode and upstream providing inconsistent
6443              * timestamps. */
6444             adapter_discont_offset =
6445                 gst_adapter_offset_at_discont (demux->adapter);
6446             adapter_discont_dist =
6447                 gst_adapter_distance_from_discont (demux->adapter);
6448
6449             GST_DEBUG_OBJECT (demux,
6450                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6451                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6452                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6453
6454             if (demux->upstream_format_is_time) {
6455               demux->moof_offset = adapter_discont_offset;
6456               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6457                 demux->moof_offset += adapter_discont_dist;
6458               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6459                 demux->moof_offset = demux->offset;
6460             } else {
6461               demux->moof_offset = demux->offset;
6462             }
6463
6464             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6465                     demux->moof_offset, NULL)) {
6466               gst_adapter_unmap (demux->adapter);
6467               ret = GST_FLOW_ERROR;
6468               goto done;
6469             }
6470             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6471             if (demux->mss_mode && !demux->exposed) {
6472               if (!demux->pending_newsegment) {
6473                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6474                 demux->pending_newsegment =
6475                     gst_event_new_segment (&demux->segment);
6476                 if (demux->segment_seqnum)
6477                   gst_event_set_seqnum (demux->pending_newsegment,
6478                       demux->segment_seqnum);
6479               }
6480               qtdemux_expose_streams (demux);
6481             }
6482           } else {
6483             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6484           }
6485         } else if (fourcc == FOURCC_ftyp) {
6486           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6487           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6488         } else if (fourcc == FOURCC_uuid) {
6489           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6490           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6491         } else if (fourcc == FOURCC_sidx) {
6492           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6493           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6494         } else {
6495           GST_WARNING_OBJECT (demux,
6496               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6497               GST_FOURCC_ARGS (fourcc));
6498           /* Let's jump that one and go back to initial state */
6499         }
6500         gst_adapter_unmap (demux->adapter);
6501         data = NULL;
6502
6503         if (demux->mdatbuffer && demux->n_streams) {
6504           gsize remaining_data_size = 0;
6505
6506           /* the mdat was before the header */
6507           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6508               demux->n_streams, demux->mdatbuffer);
6509           /* restore our adapter/offset view of things with upstream;
6510            * put preceding buffered data ahead of current moov data.
6511            * This should also handle evil mdat, moov, mdat cases and alike */
6512           gst_adapter_flush (demux->adapter, demux->neededbytes);
6513
6514           /* Store any remaining data after the mdat for later usage */
6515           remaining_data_size = gst_adapter_available (demux->adapter);
6516           if (remaining_data_size > 0) {
6517             g_assert (demux->restoredata_buffer == NULL);
6518             demux->restoredata_buffer =
6519                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6520             demux->restoredata_offset = demux->offset + demux->neededbytes;
6521             GST_DEBUG_OBJECT (demux,
6522                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6523                 G_GUINT64_FORMAT, remaining_data_size,
6524                 demux->restoredata_offset);
6525           }
6526
6527           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6528           demux->mdatbuffer = NULL;
6529           demux->offset = demux->mdatoffset;
6530           demux->neededbytes = next_entry_size (demux);
6531           demux->state = QTDEMUX_STATE_MOVIE;
6532           demux->mdatleft = gst_adapter_available (demux->adapter);
6533         } else {
6534           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6535           gst_adapter_flush (demux->adapter, demux->neededbytes);
6536
6537           /* only go back to the mdat if there are samples to play */
6538           if (demux->got_moov && demux->first_mdat != -1
6539               && has_next_entry (demux)) {
6540             gboolean res;
6541
6542             /* we need to seek back */
6543             res = qtdemux_seek_offset (demux, demux->first_mdat);
6544             if (res) {
6545               demux->offset = demux->first_mdat;
6546             } else {
6547               GST_DEBUG_OBJECT (demux, "Seek back failed");
6548             }
6549           } else {
6550             demux->offset += demux->neededbytes;
6551           }
6552           demux->neededbytes = 16;
6553           demux->state = QTDEMUX_STATE_INITIAL;
6554         }
6555
6556         break;
6557       }
6558       case QTDEMUX_STATE_BUFFER_MDAT:{
6559         GstBuffer *buf;
6560         guint8 fourcc[4];
6561
6562         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6563             demux->offset);
6564         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6565         gst_buffer_extract (buf, 0, fourcc, 4);
6566         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6567             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6568         if (demux->mdatbuffer)
6569           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6570         else
6571           demux->mdatbuffer = buf;
6572         demux->offset += demux->neededbytes;
6573         demux->neededbytes = 16;
6574         demux->state = QTDEMUX_STATE_INITIAL;
6575         gst_qtdemux_post_progress (demux, 1, 1);
6576
6577         break;
6578       }
6579       case QTDEMUX_STATE_MOVIE:{
6580         QtDemuxStream *stream = NULL;
6581         QtDemuxSample *sample;
6582         int i = -1;
6583         GstClockTime dts, pts, duration;
6584         gboolean keyframe;
6585
6586         GST_DEBUG_OBJECT (demux,
6587             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6588
6589         if (demux->fragmented) {
6590           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6591               demux->mdatleft);
6592           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6593             /* if needed data starts within this atom,
6594              * then it should not exceed this atom */
6595             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6596               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6597                   (_("This file is invalid and cannot be played.")),
6598                   ("sample data crosses atom boundary"));
6599               ret = GST_FLOW_ERROR;
6600               break;
6601             }
6602             demux->mdatleft -= demux->neededbytes;
6603           } else {
6604             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6605             /* so we are dropping more than left in this atom */
6606             gst_qtdemux_drop_data (demux, demux->mdatleft);
6607             demux->mdatleft = 0;
6608
6609             /* need to resume atom parsing so we do not miss any other pieces */
6610             demux->state = QTDEMUX_STATE_INITIAL;
6611             demux->neededbytes = 16;
6612
6613             /* check if there was any stored post mdat data from previous buffers */
6614             if (demux->restoredata_buffer) {
6615               g_assert (gst_adapter_available (demux->adapter) == 0);
6616
6617               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6618               demux->restoredata_buffer = NULL;
6619               demux->offset = demux->restoredata_offset;
6620             }
6621
6622             break;
6623           }
6624         }
6625
6626         if (demux->todrop) {
6627           if (demux->cenc_aux_info_offset > 0) {
6628             GstByteReader br;
6629             const guint8 *data;
6630
6631             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6632             data = gst_adapter_map (demux->adapter, demux->todrop);
6633             gst_byte_reader_init (&br, data + 8, demux->todrop);
6634             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6635                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6636               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6637               ret = GST_FLOW_ERROR;
6638               gst_adapter_unmap (demux->adapter);
6639               g_free (demux->cenc_aux_info_sizes);
6640               demux->cenc_aux_info_sizes = NULL;
6641               goto done;
6642             }
6643             demux->cenc_aux_info_offset = 0;
6644             g_free (demux->cenc_aux_info_sizes);
6645             demux->cenc_aux_info_sizes = NULL;
6646             gst_adapter_unmap (demux->adapter);
6647           }
6648           gst_qtdemux_drop_data (demux, demux->todrop);
6649         }
6650
6651         /* first buffer? */
6652         /* initial newsegment sent here after having added pads,
6653          * possible others in sink_event */
6654         gst_qtdemux_check_send_pending_segment (demux);
6655
6656         /* Figure out which stream this packet belongs to */
6657         for (i = 0; i < demux->n_streams; i++) {
6658           stream = demux->streams[i];
6659           if (stream->sample_index >= stream->n_samples)
6660             continue;
6661           GST_LOG_OBJECT (demux,
6662               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6663               " / size:%d)", i, stream->sample_index,
6664               stream->samples[stream->sample_index].offset,
6665               stream->samples[stream->sample_index].size);
6666
6667           if (stream->samples[stream->sample_index].offset == demux->offset)
6668             break;
6669         }
6670
6671         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6672           goto unknown_stream;
6673
6674         if (stream->new_caps) {
6675           gst_qtdemux_configure_stream (demux, stream);
6676         }
6677
6678         /* Put data in a buffer, set timestamps, caps, ... */
6679         sample = &stream->samples[stream->sample_index];
6680
6681         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6682           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6683               GST_FOURCC_ARGS (stream->fourcc));
6684
6685           dts = QTSAMPLE_DTS (stream, sample);
6686           pts = QTSAMPLE_PTS (stream, sample);
6687           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6688           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6689
6690           /* check for segment end */
6691           if (G_UNLIKELY (demux->segment.stop != -1
6692                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6693             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6694             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6695
6696             /* skip this data, stream is EOS */
6697             gst_adapter_flush (demux->adapter, demux->neededbytes);
6698
6699             /* check if all streams are eos */
6700             ret = GST_FLOW_EOS;
6701             for (i = 0; i < demux->n_streams; i++) {
6702               if (!STREAM_IS_EOS (demux->streams[i])) {
6703                 ret = GST_FLOW_OK;
6704                 break;
6705               }
6706             }
6707
6708             if (ret == GST_FLOW_EOS) {
6709               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6710               goto eos;
6711             }
6712           } else {
6713             GstBuffer *outbuf;
6714
6715             outbuf =
6716                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6717
6718             /* FIXME: should either be an assert or a plain check */
6719             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6720
6721             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6722                 dts, pts, duration, keyframe, dts, demux->offset);
6723           }
6724
6725           /* combine flows */
6726           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6727           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6728             goto non_ok_unlinked_flow;
6729         } else {
6730           /* skip this data, stream is EOS */
6731           gst_adapter_flush (demux->adapter, demux->neededbytes);
6732         }
6733
6734         stream->sample_index++;
6735         stream->offset_in_sample = 0;
6736
6737         /* update current offset and figure out size of next buffer */
6738         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6739             demux->offset, demux->neededbytes);
6740         demux->offset += demux->neededbytes;
6741         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6742             demux->offset);
6743
6744         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6745           if (demux->fragmented) {
6746             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6747             /* there may be more to follow, only finish this atom */
6748             demux->todrop = demux->mdatleft;
6749             demux->neededbytes = demux->todrop;
6750             break;
6751           }
6752           goto eos;
6753         }
6754         break;
6755       }
6756       default:
6757         goto invalid_state;
6758     }
6759   }
6760
6761   /* when buffering movie data, at least show user something is happening */
6762   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6763       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6764     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6765         demux->neededbytes);
6766   }
6767 done:
6768
6769   return ret;
6770
6771   /* ERRORS */
6772 non_ok_unlinked_flow:
6773   {
6774     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6775         gst_flow_get_name (ret));
6776     return ret;
6777   }
6778 unknown_stream:
6779   {
6780     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6781     ret = GST_FLOW_ERROR;
6782     goto done;
6783   }
6784 eos:
6785   {
6786     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6787     ret = GST_FLOW_EOS;
6788     goto done;
6789   }
6790 invalid_state:
6791   {
6792     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6793         (NULL), ("qtdemuxer invalid state %d", demux->state));
6794     ret = GST_FLOW_ERROR;
6795     goto done;
6796   }
6797 no_moov:
6798   {
6799     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6800         (NULL), ("no 'moov' atom within the first 10 MB"));
6801     ret = GST_FLOW_ERROR;
6802     goto done;
6803   }
6804 }
6805
6806 static gboolean
6807 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6808 {
6809   GstQuery *query;
6810   gboolean pull_mode;
6811
6812   query = gst_query_new_scheduling ();
6813
6814   if (!gst_pad_peer_query (sinkpad, query)) {
6815     gst_query_unref (query);
6816     goto activate_push;
6817   }
6818
6819   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6820       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6821   gst_query_unref (query);
6822
6823   if (!pull_mode)
6824     goto activate_push;
6825
6826   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6827   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6828
6829 activate_push:
6830   {
6831     GST_DEBUG_OBJECT (sinkpad, "activating push");
6832     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6833   }
6834 }
6835
6836 static gboolean
6837 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6838     GstPadMode mode, gboolean active)
6839 {
6840   gboolean res;
6841   GstQTDemux *demux = GST_QTDEMUX (parent);
6842
6843   switch (mode) {
6844     case GST_PAD_MODE_PUSH:
6845       demux->pullbased = FALSE;
6846       res = TRUE;
6847       break;
6848     case GST_PAD_MODE_PULL:
6849       if (active) {
6850         demux->pullbased = TRUE;
6851         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6852             sinkpad, NULL);
6853       } else {
6854         res = gst_pad_stop_task (sinkpad);
6855       }
6856       break;
6857     default:
6858       res = FALSE;
6859       break;
6860   }
6861   return res;
6862 }
6863
6864 #ifdef HAVE_ZLIB
6865 static void *
6866 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6867 {
6868   return g_malloc (items * size);
6869 }
6870
6871 static void
6872 qtdemux_zfree (void *opaque, void *addr)
6873 {
6874   g_free (addr);
6875 }
6876
6877 static void *
6878 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6879 {
6880   guint8 *buffer;
6881   z_stream *z;
6882   int ret;
6883
6884   z = g_new0 (z_stream, 1);
6885   z->zalloc = qtdemux_zalloc;
6886   z->zfree = qtdemux_zfree;
6887   z->opaque = NULL;
6888
6889   z->next_in = z_buffer;
6890   z->avail_in = z_length;
6891
6892   buffer = (guint8 *) g_malloc (length);
6893   ret = inflateInit (z);
6894   while (z->avail_in > 0) {
6895     if (z->avail_out == 0) {
6896       length += 1024;
6897       buffer = (guint8 *) g_realloc (buffer, length);
6898       z->next_out = buffer + z->total_out;
6899       z->avail_out = 1024;
6900     }
6901     ret = inflate (z, Z_SYNC_FLUSH);
6902     if (ret != Z_OK)
6903       break;
6904   }
6905   if (ret != Z_STREAM_END) {
6906     g_warning ("inflate() returned %d", ret);
6907   }
6908
6909   g_free (z);
6910   return buffer;
6911 }
6912 #endif /* HAVE_ZLIB */
6913
6914 static gboolean
6915 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6916 {
6917   GNode *cmov;
6918
6919   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6920
6921   /* counts as header data */
6922   qtdemux->header_size += length;
6923
6924   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6925   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6926
6927   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6928   if (cmov) {
6929     guint32 method;
6930     GNode *dcom;
6931     GNode *cmvd;
6932
6933     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6934     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6935     if (dcom == NULL || cmvd == NULL)
6936       goto invalid_compression;
6937
6938     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6939     switch (method) {
6940 #ifdef HAVE_ZLIB
6941       case FOURCC_zlib:{
6942         guint uncompressed_length;
6943         guint compressed_length;
6944         guint8 *buf;
6945
6946         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6947         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6948         GST_LOG ("length = %u", uncompressed_length);
6949
6950         buf =
6951             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6952             compressed_length, uncompressed_length);
6953
6954         qtdemux->moov_node_compressed = qtdemux->moov_node;
6955         qtdemux->moov_node = g_node_new (buf);
6956
6957         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6958             uncompressed_length);
6959         break;
6960       }
6961 #endif /* HAVE_ZLIB */
6962       default:
6963         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6964             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6965         break;
6966     }
6967   }
6968   return TRUE;
6969
6970   /* ERRORS */
6971 invalid_compression:
6972   {
6973     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6974     return FALSE;
6975   }
6976 }
6977
6978 static gboolean
6979 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6980     const guint8 * end)
6981 {
6982   while (G_UNLIKELY (buf < end)) {
6983     GNode *child;
6984     guint32 len;
6985
6986     if (G_UNLIKELY (buf + 4 > end)) {
6987       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6988       break;
6989     }
6990     len = QT_UINT32 (buf);
6991     if (G_UNLIKELY (len == 0)) {
6992       GST_LOG_OBJECT (qtdemux, "empty container");
6993       break;
6994     }
6995     if (G_UNLIKELY (len < 8)) {
6996       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6997       break;
6998     }
6999     if (G_UNLIKELY (len > (end - buf))) {
7000       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7001           (gint) (end - buf));
7002       break;
7003     }
7004
7005     child = g_node_new ((guint8 *) buf);
7006     g_node_append (node, child);
7007     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7008     qtdemux_parse_node (qtdemux, child, buf, len);
7009
7010     buf += len;
7011   }
7012   return TRUE;
7013 }
7014
7015 static gboolean
7016 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7017     GNode * xdxt)
7018 {
7019   int len = QT_UINT32 (xdxt->data);
7020   guint8 *buf = xdxt->data;
7021   guint8 *end = buf + len;
7022   GstBuffer *buffer;
7023
7024   /* skip size and type */
7025   buf += 8;
7026   end -= 8;
7027
7028   while (buf < end) {
7029     gint size;
7030     guint32 type;
7031
7032     size = QT_UINT32 (buf);
7033     type = QT_FOURCC (buf + 4);
7034
7035     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7036
7037     if (buf + size > end || size <= 0)
7038       break;
7039
7040     buf += 8;
7041     size -= 8;
7042
7043     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7044         GST_FOURCC_ARGS (type));
7045
7046     switch (type) {
7047       case FOURCC_tCtH:
7048         buffer = gst_buffer_new_and_alloc (size);
7049         gst_buffer_fill (buffer, 0, buf, size);
7050         stream->buffers = g_slist_append (stream->buffers, buffer);
7051         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7052         break;
7053       case FOURCC_tCt_:
7054         buffer = gst_buffer_new_and_alloc (size);
7055         gst_buffer_fill (buffer, 0, buf, size);
7056         stream->buffers = g_slist_append (stream->buffers, buffer);
7057         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7058         break;
7059       case FOURCC_tCtC:
7060         buffer = gst_buffer_new_and_alloc (size);
7061         gst_buffer_fill (buffer, 0, buf, size);
7062         stream->buffers = g_slist_append (stream->buffers, buffer);
7063         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7064         break;
7065       default:
7066         GST_WARNING_OBJECT (qtdemux,
7067             "unknown theora cookie %" GST_FOURCC_FORMAT,
7068             GST_FOURCC_ARGS (type));
7069         break;
7070     }
7071     buf += size;
7072   }
7073   return TRUE;
7074 }
7075
7076 static gboolean
7077 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7078     guint length)
7079 {
7080   guint32 fourcc = 0;
7081   guint32 node_length = 0;
7082   const QtNodeType *type;
7083   const guint8 *end;
7084
7085   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7086
7087   if (G_UNLIKELY (length < 8))
7088     goto not_enough_data;
7089
7090   node_length = QT_UINT32 (buffer);
7091   fourcc = QT_FOURCC (buffer + 4);
7092
7093   /* ignore empty nodes */
7094   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7095     return TRUE;
7096
7097   type = qtdemux_type_get (fourcc);
7098
7099   end = buffer + length;
7100
7101   GST_LOG_OBJECT (qtdemux,
7102       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7103       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7104
7105   if (node_length > length)
7106     goto broken_atom_size;
7107
7108   if (type->flags & QT_FLAG_CONTAINER) {
7109     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7110   } else {
7111     switch (fourcc) {
7112       case FOURCC_stsd:
7113       {
7114         if (node_length < 20) {
7115           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7116           break;
7117         }
7118         GST_DEBUG_OBJECT (qtdemux,
7119             "parsing stsd (sample table, sample description) atom");
7120         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7121         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7122         break;
7123       }
7124       case FOURCC_mp4a:
7125       case FOURCC_alac:
7126       case FOURCC_fLaC:
7127       {
7128         guint32 version;
7129         guint32 offset;
7130         guint min_size;
7131
7132         /* also read alac (or whatever) in stead of mp4a in the following,
7133          * since a similar layout is used in other cases as well */
7134         if (fourcc == FOURCC_mp4a)
7135           min_size = 20;
7136         else if (fourcc == FOURCC_fLaC)
7137           min_size = 86;
7138         else
7139           min_size = 40;
7140
7141         /* There are two things we might encounter here: a true mp4a atom, and
7142            an mp4a entry in an stsd atom. The latter is what we're interested
7143            in, and it looks like an atom, but isn't really one. The true mp4a
7144            atom is short, so we detect it based on length here. */
7145         if (length < min_size) {
7146           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7147               GST_FOURCC_ARGS (fourcc));
7148           break;
7149         }
7150
7151         /* 'version' here is the sound sample description version. Types 0 and
7152            1 are documented in the QTFF reference, but type 2 is not: it's
7153            described in Apple header files instead (struct SoundDescriptionV2
7154            in Movies.h) */
7155         version = QT_UINT16 (buffer + 16);
7156
7157         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7158             GST_FOURCC_ARGS (fourcc), version);
7159
7160         /* parse any esds descriptors */
7161         switch (version) {
7162           case 0:
7163             offset = 0x24;
7164             break;
7165           case 1:
7166             offset = 0x34;
7167             break;
7168           case 2:
7169             offset = 0x48;
7170             break;
7171           default:
7172             GST_WARNING_OBJECT (qtdemux,
7173                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7174                 GST_FOURCC_ARGS (fourcc), version);
7175             offset = 0;
7176             break;
7177         }
7178         if (offset)
7179           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7180         break;
7181       }
7182       case FOURCC_mp4v:
7183       case FOURCC_MP4V:
7184       case FOURCC_fmp4:
7185       case FOURCC_FMP4:
7186       case FOURCC_apcs:
7187       case FOURCC_apch:
7188       case FOURCC_apcn:
7189       case FOURCC_apco:
7190       case FOURCC_ap4h:
7191       {
7192         const guint8 *buf;
7193         guint32 version;
7194         int tlen;
7195
7196         /* codec_data is contained inside these atoms, which all have
7197          * the same format. */
7198
7199         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7200             GST_FOURCC_ARGS (fourcc));
7201         version = QT_UINT32 (buffer + 16);
7202         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7203         if (1 || version == 0x00000000) {
7204           buf = buffer + 0x32;
7205
7206           /* FIXME Quicktime uses PASCAL string while
7207            * the iso format uses C strings. Check the file
7208            * type before attempting to parse the string here. */
7209           tlen = QT_UINT8 (buf);
7210           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
7211           buf++;
7212           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
7213           /* the string has a reserved space of 32 bytes so skip
7214            * the remaining 31 */
7215           buf += 31;
7216           buf += 4;             /* and 4 bytes reserved */
7217
7218           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
7219
7220           qtdemux_parse_container (qtdemux, node, buf, end);
7221         }
7222         break;
7223       }
7224       case FOURCC_H264:
7225       {
7226         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
7227         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7228         break;
7229       }
7230       case FOURCC_avc1:
7231       {
7232         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
7233         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7234         break;
7235       }
7236       case FOURCC_avc3:
7237       {
7238         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
7239         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7240         break;
7241       }
7242       case FOURCC_H265:
7243       {
7244         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
7245         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7246         break;
7247       }
7248       case FOURCC_hvc1:
7249       {
7250         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
7251         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7252         break;
7253       }
7254       case FOURCC_hev1:
7255       {
7256         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
7257         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7258         break;
7259       }
7260       case FOURCC_mjp2:
7261       {
7262         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7263         break;
7264       }
7265       case FOURCC_meta:
7266       {
7267         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7268         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7269         break;
7270       }
7271       case FOURCC_mp4s:
7272       {
7273         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7274         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7275         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7276         break;
7277       }
7278       case FOURCC_XiTh:
7279       {
7280         guint32 version;
7281         guint32 offset;
7282
7283         version = QT_UINT32 (buffer + 12);
7284         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7285
7286         switch (version) {
7287           case 0x00000001:
7288             offset = 0x62;
7289             break;
7290           default:
7291             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7292             offset = 0;
7293             break;
7294         }
7295         if (offset)
7296           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7297         break;
7298       }
7299       case FOURCC_in24:
7300       {
7301         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7302         break;
7303       }
7304       case FOURCC_uuid:
7305       {
7306         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7307         break;
7308       }
7309       case FOURCC_encv:
7310       {
7311         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7312         break;
7313       }
7314       case FOURCC_enca:
7315       {
7316         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7317         break;
7318       }
7319       default:
7320         if (!strcmp (type->name, "unknown"))
7321           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7322         break;
7323     }
7324   }
7325   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7326       GST_FOURCC_ARGS (fourcc));
7327   return TRUE;
7328
7329 /* ERRORS */
7330 not_enough_data:
7331   {
7332     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7333         (_("This file is corrupt and cannot be played.")),
7334         ("Not enough data for an atom header, got only %u bytes", length));
7335     return FALSE;
7336   }
7337 broken_atom_size:
7338   {
7339     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7340         (_("This file is corrupt and cannot be played.")),
7341         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7342             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7343             length));
7344     return FALSE;
7345   }
7346 }
7347
7348 static GNode *
7349 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7350 {
7351   GNode *child;
7352   guint8 *buffer;
7353   guint32 child_fourcc;
7354
7355   for (child = g_node_first_child (node); child;
7356       child = g_node_next_sibling (child)) {
7357     buffer = (guint8 *) child->data;
7358
7359     child_fourcc = QT_FOURCC (buffer + 4);
7360
7361     if (G_UNLIKELY (child_fourcc == fourcc)) {
7362       return child;
7363     }
7364   }
7365   return NULL;
7366 }
7367
7368 static GNode *
7369 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7370     GstByteReader * parser)
7371 {
7372   GNode *child;
7373   guint8 *buffer;
7374   guint32 child_fourcc, child_len;
7375
7376   for (child = g_node_first_child (node); child;
7377       child = g_node_next_sibling (child)) {
7378     buffer = (guint8 *) child->data;
7379
7380     child_len = QT_UINT32 (buffer);
7381     child_fourcc = QT_FOURCC (buffer + 4);
7382
7383     if (G_UNLIKELY (child_fourcc == fourcc)) {
7384       if (G_UNLIKELY (child_len < (4 + 4)))
7385         return NULL;
7386       /* FIXME: must verify if atom length < parent atom length */
7387       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7388       return child;
7389     }
7390   }
7391   return NULL;
7392 }
7393
7394 static GNode *
7395 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7396     GstByteReader * parser)
7397 {
7398   GNode *child;
7399   guint8 *buffer;
7400   guint32 child_fourcc, child_len;
7401
7402   for (child = g_node_next_sibling (node); child;
7403       child = g_node_next_sibling (child)) {
7404     buffer = (guint8 *) child->data;
7405
7406     child_fourcc = QT_FOURCC (buffer + 4);
7407
7408     if (child_fourcc == fourcc) {
7409       if (parser) {
7410         child_len = QT_UINT32 (buffer);
7411         if (G_UNLIKELY (child_len < (4 + 4)))
7412           return NULL;
7413         /* FIXME: must verify if atom length < parent atom length */
7414         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7415       }
7416       return child;
7417     }
7418   }
7419   return NULL;
7420 }
7421
7422 static GNode *
7423 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7424 {
7425   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7426 }
7427
7428 static void
7429 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7430 {
7431 /* FIXME: This can only reliably work if demuxers have a
7432  * separate streaming thread per srcpad. This should be
7433  * done in a demuxer base class, which integrates parts
7434  * of multiqueue
7435  *
7436  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7437  */
7438 #if 0
7439   GstQuery *query;
7440
7441   query = gst_query_new_allocation (stream->caps, FALSE);
7442
7443   if (!gst_pad_peer_query (stream->pad, query)) {
7444     /* not a problem, just debug a little */
7445     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7446   }
7447
7448   if (stream->allocator)
7449     gst_object_unref (stream->allocator);
7450
7451   if (gst_query_get_n_allocation_params (query) > 0) {
7452     /* try the allocator */
7453     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7454         &stream->params);
7455     stream->use_allocator = TRUE;
7456   } else {
7457     stream->allocator = NULL;
7458     gst_allocation_params_init (&stream->params);
7459     stream->use_allocator = FALSE;
7460   }
7461   gst_query_unref (query);
7462 #endif
7463 }
7464
7465 static gboolean
7466 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7467     QtDemuxStream * stream)
7468 {
7469   GstStructure *s;
7470   const gchar *selected_system;
7471
7472   g_return_val_if_fail (qtdemux != NULL, FALSE);
7473   g_return_val_if_fail (stream != NULL, FALSE);
7474   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7475
7476   if (stream->protection_scheme_type != FOURCC_cenc) {
7477     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7478     return FALSE;
7479   }
7480   if (qtdemux->protection_system_ids == NULL) {
7481     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7482         "cenc protection system information has been found");
7483     return FALSE;
7484   }
7485   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7486   selected_system = gst_protection_select_system ((const gchar **)
7487       qtdemux->protection_system_ids->pdata);
7488   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7489       qtdemux->protection_system_ids->len - 1);
7490   if (!selected_system) {
7491     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7492         "suitable decryptor element has been found");
7493     return FALSE;
7494   }
7495
7496   s = gst_caps_get_structure (stream->caps, 0);
7497   if (!gst_structure_has_name (s, "application/x-cenc")) {
7498     gst_structure_set (s,
7499         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7500         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7501         NULL);
7502     gst_structure_set_name (s, "application/x-cenc");
7503   }
7504   return TRUE;
7505 }
7506
7507 static gboolean
7508 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7509 {
7510   if (stream->subtype == FOURCC_vide) {
7511     /* fps is calculated base on the duration of the average framerate since
7512      * qt does not have a fixed framerate. */
7513     gboolean fps_available = TRUE;
7514
7515     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7516       /* still frame */
7517       stream->fps_n = 0;
7518       stream->fps_d = 1;
7519     } else {
7520       if (stream->duration == 0 || stream->n_samples < 2) {
7521         stream->fps_n = stream->timescale;
7522         stream->fps_d = 1;
7523         fps_available = FALSE;
7524       } else {
7525         GstClockTime avg_duration;
7526         guint64 duration;
7527         guint32 n_samples;
7528
7529         /* duration and n_samples can be updated for fragmented format
7530          * so, framerate of fragmented format is calculated using data in a moof */
7531         if (qtdemux->fragmented && stream->n_samples_moof > 0
7532             && stream->duration_moof > 0) {
7533           n_samples = stream->n_samples_moof;
7534           duration = stream->duration_moof;
7535         } else {
7536           n_samples = stream->n_samples;
7537           duration = stream->duration;
7538         }
7539
7540         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7541         /* stream->duration is guint64, timescale, n_samples are guint32 */
7542         avg_duration =
7543             gst_util_uint64_scale_round (duration -
7544             stream->first_duration, GST_SECOND,
7545             (guint64) (stream->timescale) * (n_samples - 1));
7546
7547         GST_LOG_OBJECT (qtdemux,
7548             "Calculating avg sample duration based on stream (or moof) duration %"
7549             G_GUINT64_FORMAT
7550             " minus first sample %u, leaving %d samples gives %"
7551             GST_TIME_FORMAT, duration, stream->first_duration,
7552             n_samples - 1, GST_TIME_ARGS (avg_duration));
7553
7554         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7555             &stream->fps_d);
7556
7557         GST_DEBUG_OBJECT (qtdemux,
7558             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7559             stream->timescale, stream->fps_n, stream->fps_d);
7560       }
7561     }
7562
7563     if (stream->caps) {
7564       stream->caps = gst_caps_make_writable (stream->caps);
7565
7566       gst_caps_set_simple (stream->caps,
7567           "width", G_TYPE_INT, stream->width,
7568           "height", G_TYPE_INT, stream->height, NULL);
7569
7570       /* set framerate if calculated framerate is reliable */
7571       if (fps_available) {
7572         gst_caps_set_simple (stream->caps,
7573             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7574       }
7575
7576       /* calculate pixel-aspect-ratio using display width and height */
7577       GST_DEBUG_OBJECT (qtdemux,
7578           "video size %dx%d, target display size %dx%d", stream->width,
7579           stream->height, stream->display_width, stream->display_height);
7580       /* qt file might have pasp atom */
7581       if (stream->par_w > 0 && stream->par_h > 0) {
7582         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7583         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7584             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7585       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7586           stream->width > 0 && stream->height > 0) {
7587         gint n, d;
7588
7589         /* calculate the pixel aspect ratio using the display and pixel w/h */
7590         n = stream->display_width * stream->height;
7591         d = stream->display_height * stream->width;
7592         if (n == d)
7593           n = d = 1;
7594         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7595         stream->par_w = n;
7596         stream->par_h = d;
7597         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7598             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7599       }
7600
7601       /* Create incomplete colorimetry here if needed */
7602       if (stream->colorimetry.range ||
7603           stream->colorimetry.matrix ||
7604           stream->colorimetry.transfer || stream->colorimetry.primaries) {
7605         gchar *colorimetry =
7606             gst_video_colorimetry_to_string (&stream->colorimetry);
7607         gst_caps_set_simple (stream->caps, "colorimetry", G_TYPE_STRING,
7608             colorimetry, NULL);
7609         g_free (colorimetry);
7610       }
7611
7612       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7613         guint par_w = 1, par_h = 1;
7614
7615         if (stream->par_w > 0 && stream->par_h > 0) {
7616           par_w = stream->par_w;
7617           par_h = stream->par_h;
7618         }
7619
7620         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7621                 stream->width, stream->height, par_w, par_h)) {
7622           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7623         }
7624
7625         gst_caps_set_simple (stream->caps,
7626             "multiview-mode", G_TYPE_STRING,
7627             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7628             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7629             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7630       }
7631     }
7632   }
7633
7634   else if (stream->subtype == FOURCC_soun) {
7635     if (stream->caps) {
7636       stream->caps = gst_caps_make_writable (stream->caps);
7637       if (stream->rate > 0)
7638         gst_caps_set_simple (stream->caps,
7639             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7640       if (stream->n_channels > 0)
7641         gst_caps_set_simple (stream->caps,
7642             "channels", G_TYPE_INT, stream->n_channels, NULL);
7643       if (stream->n_channels > 2) {
7644         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7645          * correctly; this is just the minimum we can do - assume
7646          * we don't actually have any channel positions. */
7647         gst_caps_set_simple (stream->caps,
7648             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7649       }
7650     }
7651   }
7652
7653   if (stream->pad) {
7654     GstCaps *prev_caps = NULL;
7655
7656     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7657     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7658     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7659     gst_pad_set_active (stream->pad, TRUE);
7660
7661     gst_pad_use_fixed_caps (stream->pad);
7662
7663     if (stream->protected) {
7664       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7665         GST_ERROR_OBJECT (qtdemux,
7666             "Failed to configure protected stream caps.");
7667         return FALSE;
7668       }
7669     }
7670
7671     if (stream->new_stream) {
7672       gchar *stream_id;
7673       GstEvent *event;
7674       GstStreamFlags stream_flags;
7675
7676       event =
7677           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7678           0);
7679       if (event) {
7680         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7681           qtdemux->have_group_id = TRUE;
7682         else
7683           qtdemux->have_group_id = FALSE;
7684         gst_event_unref (event);
7685       } else if (!qtdemux->have_group_id) {
7686         qtdemux->have_group_id = TRUE;
7687         qtdemux->group_id = gst_util_group_id_next ();
7688       }
7689
7690       stream->new_stream = FALSE;
7691       stream_id =
7692           gst_pad_create_stream_id_printf (stream->pad,
7693           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7694       event = gst_event_new_stream_start (stream_id);
7695       if (qtdemux->have_group_id)
7696         gst_event_set_group_id (event, qtdemux->group_id);
7697       stream_flags = GST_STREAM_FLAG_NONE;
7698       if (stream->disabled)
7699         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7700       if (stream->sparse)
7701         stream_flags |= GST_STREAM_FLAG_SPARSE;
7702       gst_event_set_stream_flags (event, stream_flags);
7703       gst_pad_push_event (stream->pad, event);
7704       g_free (stream_id);
7705     }
7706
7707     prev_caps = gst_pad_get_current_caps (stream->pad);
7708
7709     if (!prev_caps || !gst_caps_is_equal_fixed (prev_caps, stream->caps)) {
7710       GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7711       gst_pad_set_caps (stream->pad, stream->caps);
7712     } else {
7713       GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7714     }
7715
7716     if (prev_caps)
7717       gst_caps_unref (prev_caps);
7718     stream->new_caps = FALSE;
7719   }
7720   return TRUE;
7721 }
7722
7723 static gboolean
7724 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7725     QtDemuxStream * stream, GstTagList * list)
7726 {
7727   gboolean ret = TRUE;
7728   /* consistent default for push based mode */
7729   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7730
7731   if (stream->subtype == FOURCC_vide) {
7732     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7733
7734     stream->pad =
7735         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7736     g_free (name);
7737
7738     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7739       gst_object_unref (stream->pad);
7740       stream->pad = NULL;
7741       ret = FALSE;
7742       goto done;
7743     }
7744
7745     qtdemux->n_video_streams++;
7746   } else if (stream->subtype == FOURCC_soun) {
7747     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7748
7749     stream->pad =
7750         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7751     g_free (name);
7752     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7753       gst_object_unref (stream->pad);
7754       stream->pad = NULL;
7755       ret = FALSE;
7756       goto done;
7757     }
7758     qtdemux->n_audio_streams++;
7759   } else if (stream->subtype == FOURCC_strm) {
7760     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7761   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7762       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7763     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7764
7765     stream->pad =
7766         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7767     g_free (name);
7768     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7769       gst_object_unref (stream->pad);
7770       stream->pad = NULL;
7771       ret = FALSE;
7772       goto done;
7773     }
7774     qtdemux->n_sub_streams++;
7775   } else if (stream->caps) {
7776     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7777
7778     stream->pad =
7779         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7780     g_free (name);
7781     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7782       gst_object_unref (stream->pad);
7783       stream->pad = NULL;
7784       ret = FALSE;
7785       goto done;
7786     }
7787     qtdemux->n_video_streams++;
7788   } else {
7789     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7790     goto done;
7791   }
7792
7793   if (stream->pad) {
7794     GList *l;
7795
7796     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7797         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7798     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7799     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7800
7801     if (stream->pending_tags)
7802       gst_tag_list_unref (stream->pending_tags);
7803     stream->pending_tags = list;
7804     list = NULL;
7805     /* global tags go on each pad anyway */
7806     stream->send_global_tags = TRUE;
7807     /* send upstream GST_EVENT_PROTECTION events that were received before
7808        this source pad was created */
7809     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7810       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7811   }
7812 done:
7813   if (list)
7814     gst_tag_list_unref (list);
7815   return ret;
7816 }
7817
7818 /* find next atom with @fourcc starting at @offset */
7819 static GstFlowReturn
7820 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7821     guint64 * length, guint32 fourcc)
7822 {
7823   GstFlowReturn ret;
7824   guint32 lfourcc;
7825   GstBuffer *buf;
7826
7827   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7828       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7829
7830   while (TRUE) {
7831     GstMapInfo map;
7832
7833     buf = NULL;
7834     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7835     if (G_UNLIKELY (ret != GST_FLOW_OK))
7836       goto locate_failed;
7837     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7838       /* likely EOF */
7839       ret = GST_FLOW_EOS;
7840       gst_buffer_unref (buf);
7841       goto locate_failed;
7842     }
7843     gst_buffer_map (buf, &map, GST_MAP_READ);
7844     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7845     gst_buffer_unmap (buf, &map);
7846     gst_buffer_unref (buf);
7847
7848     if (G_UNLIKELY (*length == 0)) {
7849       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7850       ret = GST_FLOW_ERROR;
7851       goto locate_failed;
7852     }
7853
7854     if (lfourcc == fourcc) {
7855       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7856           *offset);
7857       break;
7858     } else {
7859       GST_LOG_OBJECT (qtdemux,
7860           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7861           GST_FOURCC_ARGS (fourcc), *offset);
7862       *offset += *length;
7863     }
7864   }
7865
7866   return GST_FLOW_OK;
7867
7868 locate_failed:
7869   {
7870     /* might simply have had last one */
7871     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7872     return ret;
7873   }
7874 }
7875
7876 /* should only do something in pull mode */
7877 /* call with OBJECT lock */
7878 static GstFlowReturn
7879 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7880 {
7881   guint64 length, offset;
7882   GstBuffer *buf = NULL;
7883   GstFlowReturn ret = GST_FLOW_OK;
7884   GstFlowReturn res = GST_FLOW_OK;
7885   GstMapInfo map;
7886
7887   offset = qtdemux->moof_offset;
7888   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7889
7890   if (!offset) {
7891     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7892     return GST_FLOW_EOS;
7893   }
7894
7895   /* best not do pull etc with lock held */
7896   GST_OBJECT_UNLOCK (qtdemux);
7897
7898   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7899   if (ret != GST_FLOW_OK)
7900     goto flow_failed;
7901
7902   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7903   if (G_UNLIKELY (ret != GST_FLOW_OK))
7904     goto flow_failed;
7905   gst_buffer_map (buf, &map, GST_MAP_READ);
7906   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7907     gst_buffer_unmap (buf, &map);
7908     gst_buffer_unref (buf);
7909     buf = NULL;
7910     goto parse_failed;
7911   }
7912
7913   gst_buffer_unmap (buf, &map);
7914   gst_buffer_unref (buf);
7915   buf = NULL;
7916
7917   offset += length;
7918   /* look for next moof */
7919   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7920   if (G_UNLIKELY (ret != GST_FLOW_OK))
7921     goto flow_failed;
7922
7923 exit:
7924   GST_OBJECT_LOCK (qtdemux);
7925
7926   qtdemux->moof_offset = offset;
7927
7928   return res;
7929
7930 parse_failed:
7931   {
7932     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7933     offset = 0;
7934     res = GST_FLOW_ERROR;
7935     goto exit;
7936   }
7937 flow_failed:
7938   {
7939     /* maybe upstream temporarily flushing */
7940     if (ret != GST_FLOW_FLUSHING) {
7941       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7942       offset = 0;
7943     } else {
7944       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7945       /* resume at current position next time */
7946     }
7947     res = ret;
7948     goto exit;
7949   }
7950 }
7951
7952 /* initialise bytereaders for stbl sub-atoms */
7953 static gboolean
7954 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7955 {
7956   stream->stbl_index = -1;      /* no samples have yet been parsed */
7957   stream->sample_index = -1;
7958
7959   /* time-to-sample atom */
7960   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7961     goto corrupt_file;
7962
7963   /* copy atom data into a new buffer for later use */
7964   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7965
7966   /* skip version + flags */
7967   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7968       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7969     goto corrupt_file;
7970   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7971
7972   /* make sure there's enough data */
7973   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7974     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7975     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7976         stream->n_sample_times);
7977     if (!stream->n_sample_times)
7978       goto corrupt_file;
7979   }
7980
7981   /* sync sample atom */
7982   stream->stps_present = FALSE;
7983   if ((stream->stss_present =
7984           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7985               &stream->stss) ? TRUE : FALSE) == TRUE) {
7986     /* copy atom data into a new buffer for later use */
7987     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7988
7989     /* skip version + flags */
7990     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7991         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7992       goto corrupt_file;
7993
7994     if (stream->n_sample_syncs) {
7995       /* make sure there's enough data */
7996       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7997         goto corrupt_file;
7998     }
7999
8000     /* partial sync sample atom */
8001     if ((stream->stps_present =
8002             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8003                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8004       /* copy atom data into a new buffer for later use */
8005       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8006
8007       /* skip version + flags */
8008       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8009           !gst_byte_reader_get_uint32_be (&stream->stps,
8010               &stream->n_sample_partial_syncs))
8011         goto corrupt_file;
8012
8013       /* if there are no entries, the stss table contains the real
8014        * sync samples */
8015       if (stream->n_sample_partial_syncs) {
8016         /* make sure there's enough data */
8017         if (!qt_atom_parser_has_chunks (&stream->stps,
8018                 stream->n_sample_partial_syncs, 4))
8019           goto corrupt_file;
8020       }
8021     }
8022   }
8023
8024   /* sample size */
8025   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8026     goto no_samples;
8027
8028   /* copy atom data into a new buffer for later use */
8029   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8030
8031   /* skip version + flags */
8032   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8033       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8034     goto corrupt_file;
8035
8036   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8037     goto corrupt_file;
8038
8039   if (!stream->n_samples)
8040     goto no_samples;
8041
8042   /* sample-to-chunk atom */
8043   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8044     goto corrupt_file;
8045
8046   /* copy atom data into a new buffer for later use */
8047   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8048
8049   /* skip version + flags */
8050   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8051       !gst_byte_reader_get_uint32_be (&stream->stsc,
8052           &stream->n_samples_per_chunk))
8053     goto corrupt_file;
8054
8055   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8056       stream->n_samples_per_chunk);
8057
8058   /* make sure there's enough data */
8059   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8060           12))
8061     goto corrupt_file;
8062
8063
8064   /* chunk offset */
8065   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8066     stream->co_size = sizeof (guint32);
8067   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8068           &stream->stco))
8069     stream->co_size = sizeof (guint64);
8070   else
8071     goto corrupt_file;
8072
8073   /* copy atom data into a new buffer for later use */
8074   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8075
8076   /* skip version + flags */
8077   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8078     goto corrupt_file;
8079
8080   /* chunks_are_samples == TRUE means treat chunks as samples */
8081   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
8082   if (stream->chunks_are_samples) {
8083     /* treat chunks as samples */
8084     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8085       goto corrupt_file;
8086   } else {
8087     /* skip number of entries */
8088     if (!gst_byte_reader_skip (&stream->stco, 4))
8089       goto corrupt_file;
8090
8091     /* make sure there are enough data in the stsz atom */
8092     if (!stream->sample_size) {
8093       /* different sizes for each sample */
8094       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8095         goto corrupt_file;
8096     }
8097   }
8098
8099   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8100       stream->n_samples, (guint) sizeof (QtDemuxSample),
8101       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8102
8103   if (stream->n_samples >=
8104       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8105     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8106         "be larger than %uMB (broken file?)", stream->n_samples,
8107         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8108     return FALSE;
8109   }
8110
8111   g_assert (stream->samples == NULL);
8112   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8113   if (!stream->samples) {
8114     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8115         stream->n_samples);
8116     return FALSE;
8117   }
8118
8119   /* composition time-to-sample */
8120   if ((stream->ctts_present =
8121           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8122               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8123     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8124
8125     /* copy atom data into a new buffer for later use */
8126     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8127
8128     /* skip version + flags */
8129     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8130         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8131             &stream->n_composition_times))
8132       goto corrupt_file;
8133
8134     /* make sure there's enough data */
8135     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8136             4 + 4))
8137       goto corrupt_file;
8138
8139     /* This is optional, if missing we iterate the ctts */
8140     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8141       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8142           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8143         g_free ((gpointer) cslg.data);
8144         goto corrupt_file;
8145       }
8146     } else {
8147       gint32 cslg_least = 0;
8148       guint num_entries, pos;
8149       gint i;
8150
8151       pos = gst_byte_reader_get_pos (&stream->ctts);
8152       num_entries = stream->n_composition_times;
8153
8154       stream->cslg_shift = 0;
8155
8156       for (i = 0; i < num_entries; i++) {
8157         gint32 offset;
8158
8159         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8160         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8161
8162         if (offset < cslg_least)
8163           cslg_least = offset;
8164       }
8165
8166       if (cslg_least < 0)
8167         stream->cslg_shift = ABS (cslg_least);
8168       else
8169         stream->cslg_shift = 0;
8170
8171       /* reset the reader so we can generate sample table */
8172       gst_byte_reader_set_pos (&stream->ctts, pos);
8173     }
8174   } else {
8175     /* Ensure the cslg_shift value is consistent so we can use it
8176      * unconditionnally to produce TS and Segment */
8177     stream->cslg_shift = 0;
8178   }
8179
8180   return TRUE;
8181
8182 corrupt_file:
8183   {
8184     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8185         (_("This file is corrupt and cannot be played.")), (NULL));
8186     return FALSE;
8187   }
8188 no_samples:
8189   {
8190     gst_qtdemux_stbl_free (stream);
8191     if (!qtdemux->fragmented) {
8192       /* not quite good */
8193       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8194       return FALSE;
8195     } else {
8196       /* may pick up samples elsewhere */
8197       return TRUE;
8198     }
8199   }
8200 }
8201
8202 /* collect samples from the next sample to be parsed up to sample @n for @stream
8203  * by reading the info from @stbl
8204  *
8205  * This code can be executed from both the streaming thread and the seeking
8206  * thread so it takes the object lock to protect itself
8207  */
8208 static gboolean
8209 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8210 {
8211   gint i, j, k;
8212   QtDemuxSample *samples, *first, *cur, *last;
8213   guint32 n_samples_per_chunk;
8214   guint32 n_samples;
8215
8216   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8217       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8218       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8219
8220   n_samples = stream->n_samples;
8221
8222   if (n >= n_samples)
8223     goto out_of_samples;
8224
8225   GST_OBJECT_LOCK (qtdemux);
8226   if (n <= stream->stbl_index)
8227     goto already_parsed;
8228
8229   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8230
8231   if (!stream->stsz.data) {
8232     /* so we already parsed and passed all the moov samples;
8233      * onto fragmented ones */
8234     g_assert (qtdemux->fragmented);
8235     goto done;
8236   }
8237
8238   /* pointer to the sample table */
8239   samples = stream->samples;
8240
8241   /* starts from -1, moves to the next sample index to parse */
8242   stream->stbl_index++;
8243
8244   /* keep track of the first and last sample to fill */
8245   first = &samples[stream->stbl_index];
8246   last = &samples[n];
8247
8248   if (!stream->chunks_are_samples) {
8249     /* set the sample sizes */
8250     if (stream->sample_size == 0) {
8251       /* different sizes for each sample */
8252       for (cur = first; cur <= last; cur++) {
8253         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8254         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8255             (guint) (cur - samples), cur->size);
8256       }
8257     } else {
8258       /* samples have the same size */
8259       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8260       for (cur = first; cur <= last; cur++)
8261         cur->size = stream->sample_size;
8262     }
8263   }
8264
8265   n_samples_per_chunk = stream->n_samples_per_chunk;
8266   cur = first;
8267
8268   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8269     guint32 last_chunk;
8270
8271     if (stream->stsc_chunk_index >= stream->last_chunk
8272         || stream->stsc_chunk_index < stream->first_chunk) {
8273       stream->first_chunk =
8274           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8275       stream->samples_per_chunk =
8276           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8277       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8278
8279       /* chunk numbers are counted from 1 it seems */
8280       if (G_UNLIKELY (stream->first_chunk == 0))
8281         goto corrupt_file;
8282
8283       --stream->first_chunk;
8284
8285       /* the last chunk of each entry is calculated by taking the first chunk
8286        * of the next entry; except if there is no next, where we fake it with
8287        * INT_MAX */
8288       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8289         stream->last_chunk = G_MAXUINT32;
8290       } else {
8291         stream->last_chunk =
8292             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8293         if (G_UNLIKELY (stream->last_chunk == 0))
8294           goto corrupt_file;
8295
8296         --stream->last_chunk;
8297       }
8298
8299       GST_LOG_OBJECT (qtdemux,
8300           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8301           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8302
8303       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8304         goto corrupt_file;
8305
8306       if (stream->last_chunk != G_MAXUINT32) {
8307         if (!qt_atom_parser_peek_sub (&stream->stco,
8308                 stream->first_chunk * stream->co_size,
8309                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8310                 &stream->co_chunk))
8311           goto corrupt_file;
8312
8313       } else {
8314         stream->co_chunk = stream->stco;
8315         if (!gst_byte_reader_skip (&stream->co_chunk,
8316                 stream->first_chunk * stream->co_size))
8317           goto corrupt_file;
8318       }
8319
8320       stream->stsc_chunk_index = stream->first_chunk;
8321     }
8322
8323     last_chunk = stream->last_chunk;
8324
8325     if (stream->chunks_are_samples) {
8326       cur = &samples[stream->stsc_chunk_index];
8327
8328       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8329         if (j > n) {
8330           /* save state */
8331           stream->stsc_chunk_index = j;
8332           goto done;
8333         }
8334
8335         cur->offset =
8336             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8337             stream->co_size);
8338
8339         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8340             "%" G_GUINT64_FORMAT, j, cur->offset);
8341
8342         if (stream->samples_per_frame * stream->bytes_per_frame) {
8343           cur->size =
8344               (stream->samples_per_chunk * stream->n_channels) /
8345               stream->samples_per_frame * stream->bytes_per_frame;
8346         } else {
8347           cur->size = stream->samples_per_chunk;
8348         }
8349
8350         GST_DEBUG_OBJECT (qtdemux,
8351             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8352             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8353                     stream->stco_sample_index)), cur->size);
8354
8355         cur->timestamp = stream->stco_sample_index;
8356         cur->duration = stream->samples_per_chunk;
8357         cur->keyframe = TRUE;
8358         cur++;
8359
8360         stream->stco_sample_index += stream->samples_per_chunk;
8361       }
8362       stream->stsc_chunk_index = j;
8363     } else {
8364       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8365         guint32 samples_per_chunk;
8366         guint64 chunk_offset;
8367
8368         if (!stream->stsc_sample_index
8369             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8370                 &stream->chunk_offset))
8371           goto corrupt_file;
8372
8373         samples_per_chunk = stream->samples_per_chunk;
8374         chunk_offset = stream->chunk_offset;
8375
8376         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8377           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8378               G_GUINT64_FORMAT " and size %d",
8379               (guint) (cur - samples), chunk_offset, cur->size);
8380
8381           cur->offset = chunk_offset;
8382           chunk_offset += cur->size;
8383           cur++;
8384
8385           if (G_UNLIKELY (cur > last)) {
8386             /* save state */
8387             stream->stsc_sample_index = k + 1;
8388             stream->chunk_offset = chunk_offset;
8389             stream->stsc_chunk_index = j;
8390             goto done2;
8391           }
8392         }
8393         stream->stsc_sample_index = 0;
8394       }
8395       stream->stsc_chunk_index = j;
8396     }
8397     stream->stsc_index++;
8398   }
8399
8400   if (stream->chunks_are_samples)
8401     goto ctts;
8402 done2:
8403   {
8404     guint32 n_sample_times;
8405
8406     n_sample_times = stream->n_sample_times;
8407     cur = first;
8408
8409     for (i = stream->stts_index; i < n_sample_times; i++) {
8410       guint32 stts_samples;
8411       gint32 stts_duration;
8412       gint64 stts_time;
8413
8414       if (stream->stts_sample_index >= stream->stts_samples
8415           || !stream->stts_sample_index) {
8416
8417         stream->stts_samples =
8418             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8419         stream->stts_duration =
8420             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8421
8422         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8423             i, stream->stts_samples, stream->stts_duration);
8424
8425         stream->stts_sample_index = 0;
8426       }
8427
8428       stts_samples = stream->stts_samples;
8429       stts_duration = stream->stts_duration;
8430       stts_time = stream->stts_time;
8431
8432       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8433         GST_DEBUG_OBJECT (qtdemux,
8434             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8435             (guint) (cur - samples), j,
8436             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8437
8438         cur->timestamp = stts_time;
8439         cur->duration = stts_duration;
8440
8441         /* avoid 32-bit wrap-around,
8442          * but still mind possible 'negative' duration */
8443         stts_time += (gint64) stts_duration;
8444         cur++;
8445
8446         if (G_UNLIKELY (cur > last)) {
8447           /* save values */
8448           stream->stts_time = stts_time;
8449           stream->stts_sample_index = j + 1;
8450           goto done3;
8451         }
8452       }
8453       stream->stts_sample_index = 0;
8454       stream->stts_time = stts_time;
8455       stream->stts_index++;
8456     }
8457     /* fill up empty timestamps with the last timestamp, this can happen when
8458      * the last samples do not decode and so we don't have timestamps for them.
8459      * We however look at the last timestamp to estimate the track length so we
8460      * need something in here. */
8461     for (; cur < last; cur++) {
8462       GST_DEBUG_OBJECT (qtdemux,
8463           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8464           (guint) (cur - samples),
8465           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8466       cur->timestamp = stream->stts_time;
8467       cur->duration = -1;
8468     }
8469   }
8470 done3:
8471   {
8472     /* sample sync, can be NULL */
8473     if (stream->stss_present == TRUE) {
8474       guint32 n_sample_syncs;
8475
8476       n_sample_syncs = stream->n_sample_syncs;
8477
8478       if (!n_sample_syncs) {
8479         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8480         stream->all_keyframe = TRUE;
8481       } else {
8482         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8483           /* note that the first sample is index 1, not 0 */
8484           guint32 index;
8485
8486           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8487
8488           if (G_LIKELY (index > 0 && index <= n_samples)) {
8489             index -= 1;
8490             samples[index].keyframe = TRUE;
8491             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8492             /* and exit if we have enough samples */
8493             if (G_UNLIKELY (index >= n)) {
8494               i++;
8495               break;
8496             }
8497           }
8498         }
8499         /* save state */
8500         stream->stss_index = i;
8501       }
8502
8503       /* stps marks partial sync frames like open GOP I-Frames */
8504       if (stream->stps_present == TRUE) {
8505         guint32 n_sample_partial_syncs;
8506
8507         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8508
8509         /* if there are no entries, the stss table contains the real
8510          * sync samples */
8511         if (n_sample_partial_syncs) {
8512           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8513             /* note that the first sample is index 1, not 0 */
8514             guint32 index;
8515
8516             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8517
8518             if (G_LIKELY (index > 0 && index <= n_samples)) {
8519               index -= 1;
8520               samples[index].keyframe = TRUE;
8521               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8522               /* and exit if we have enough samples */
8523               if (G_UNLIKELY (index >= n)) {
8524                 i++;
8525                 break;
8526               }
8527             }
8528           }
8529           /* save state */
8530           stream->stps_index = i;
8531         }
8532       }
8533     } else {
8534       /* no stss, all samples are keyframes */
8535       stream->all_keyframe = TRUE;
8536       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8537     }
8538   }
8539
8540 ctts:
8541   /* composition time to sample */
8542   if (stream->ctts_present == TRUE) {
8543     guint32 n_composition_times;
8544     guint32 ctts_count;
8545     gint32 ctts_soffset;
8546
8547     /* Fill in the pts_offsets */
8548     cur = first;
8549     n_composition_times = stream->n_composition_times;
8550
8551     for (i = stream->ctts_index; i < n_composition_times; i++) {
8552       if (stream->ctts_sample_index >= stream->ctts_count
8553           || !stream->ctts_sample_index) {
8554         stream->ctts_count =
8555             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8556         stream->ctts_soffset =
8557             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8558         stream->ctts_sample_index = 0;
8559       }
8560
8561       ctts_count = stream->ctts_count;
8562       ctts_soffset = stream->ctts_soffset;
8563
8564       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8565         cur->pts_offset = ctts_soffset;
8566         cur++;
8567
8568         if (G_UNLIKELY (cur > last)) {
8569           /* save state */
8570           stream->ctts_sample_index = j + 1;
8571           goto done;
8572         }
8573       }
8574       stream->ctts_sample_index = 0;
8575       stream->ctts_index++;
8576     }
8577   }
8578 done:
8579   stream->stbl_index = n;
8580   /* if index has been completely parsed, free data that is no-longer needed */
8581   if (n + 1 == stream->n_samples) {
8582     gst_qtdemux_stbl_free (stream);
8583     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8584     if (qtdemux->pullbased) {
8585       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8586       while (n + 1 == stream->n_samples)
8587         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8588           break;
8589     }
8590   }
8591   GST_OBJECT_UNLOCK (qtdemux);
8592
8593   return TRUE;
8594
8595   /* SUCCESS */
8596 already_parsed:
8597   {
8598     GST_LOG_OBJECT (qtdemux,
8599         "Tried to parse up to sample %u but this sample has already been parsed",
8600         n);
8601     /* if fragmented, there may be more */
8602     if (qtdemux->fragmented && n == stream->stbl_index)
8603       goto done;
8604     GST_OBJECT_UNLOCK (qtdemux);
8605     return TRUE;
8606   }
8607   /* ERRORS */
8608 out_of_samples:
8609   {
8610     GST_LOG_OBJECT (qtdemux,
8611         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8612         stream->n_samples);
8613     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8614         (_("This file is corrupt and cannot be played.")), (NULL));
8615     return FALSE;
8616   }
8617 corrupt_file:
8618   {
8619     GST_OBJECT_UNLOCK (qtdemux);
8620     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8621         (_("This file is corrupt and cannot be played.")), (NULL));
8622     return FALSE;
8623   }
8624 }
8625
8626 /* collect all segment info for @stream.
8627  */
8628 static gboolean
8629 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8630     GNode * trak)
8631 {
8632   GNode *edts;
8633   /* accept edts if they contain gaps at start and there is only
8634    * one media segment */
8635   gboolean allow_pushbased_edts = TRUE;
8636   gint media_segments_count = 0;
8637
8638   /* parse and prepare segment info from the edit list */
8639   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8640   stream->n_segments = 0;
8641   stream->segments = NULL;
8642   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8643     GNode *elst;
8644     gint n_segments;
8645     gint i, count, entry_size;
8646     guint64 time;
8647     GstClockTime stime;
8648     guint8 *buffer;
8649     guint8 version;
8650
8651     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8652     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8653       goto done;
8654
8655     buffer = elst->data;
8656
8657     version = QT_UINT8 (buffer + 8);
8658     entry_size = (version == 1) ? 20 : 12;
8659
8660     n_segments = QT_UINT32 (buffer + 12);
8661
8662     /* we might allocate a bit too much, at least allocate 1 segment */
8663     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8664
8665     /* segments always start from 0 */
8666     time = 0;
8667     stime = 0;
8668     count = 0;
8669     for (i = 0; i < n_segments; i++) {
8670       guint64 duration;
8671       guint64 media_time;
8672       gboolean time_valid = TRUE;
8673       QtDemuxSegment *segment;
8674       guint32 rate_int;
8675       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8676
8677       if (version == 1) {
8678         media_time = QT_UINT64 (buffer + 24 + i * entry_size);
8679         duration = QT_UINT64 (buffer + 16 + i * entry_size);
8680         if (media_time == G_MAXUINT64)
8681           time_valid = FALSE;
8682       } else {
8683         media_time = QT_UINT32 (buffer + 20 + i * entry_size);
8684         duration = QT_UINT32 (buffer + 16 + i * entry_size);
8685         if (media_time == G_MAXUINT32)
8686           time_valid = FALSE;
8687       }
8688
8689       if (time_valid)
8690         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8691
8692       segment = &stream->segments[count++];
8693
8694       /* time and duration expressed in global timescale */
8695       segment->time = stime;
8696       /* add non scaled values so we don't cause roundoff errors */
8697       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8698         time += duration;
8699         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8700         segment->duration = stime - segment->time;
8701       } else {
8702         /* zero duration does not imply media_start == media_stop
8703          * but, only specify media_start.*/
8704         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8705         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8706             && stime >= media_start) {
8707           segment->duration = stime - media_start;
8708         } else {
8709           segment->duration = GST_CLOCK_TIME_NONE;
8710         }
8711       }
8712       segment->stop_time = stime;
8713
8714       segment->trak_media_start = media_time;
8715       /* media_time expressed in stream timescale */
8716       if (time_valid) {
8717         segment->media_start = media_start;
8718         segment->media_stop = segment->media_start + segment->duration;
8719         media_segments_count++;
8720       } else {
8721         segment->media_start = GST_CLOCK_TIME_NONE;
8722         segment->media_stop = GST_CLOCK_TIME_NONE;
8723       }
8724       rate_int =
8725           QT_UINT32 (buffer + ((version == 1) ? 32 : 24) + i * entry_size);
8726
8727       if (rate_int <= 1) {
8728         /* 0 is not allowed, some programs write 1 instead of the floating point
8729          * value */
8730         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8731             rate_int);
8732         segment->rate = 1;
8733       } else {
8734         segment->rate = rate_int / 65536.0;
8735       }
8736
8737       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8738           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8739           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8740           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8741           i, GST_TIME_ARGS (segment->time),
8742           GST_TIME_ARGS (segment->duration),
8743           GST_TIME_ARGS (segment->media_start), media_time,
8744           GST_TIME_ARGS (segment->media_stop),
8745           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8746           stream->timescale);
8747       if (segment->stop_time > qtdemux->segment.stop) {
8748         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8749             " extends to %" GST_TIME_FORMAT
8750             " past the end of the file duration %" GST_TIME_FORMAT
8751             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8752             GST_TIME_ARGS (qtdemux->segment.stop));
8753         qtdemux->segment.stop = segment->stop_time;
8754       }
8755     }
8756     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8757     stream->n_segments = count;
8758     if (media_segments_count != 1)
8759       allow_pushbased_edts = FALSE;
8760   }
8761 done:
8762
8763   /* push based does not handle segments, so act accordingly here,
8764    * and warn if applicable */
8765   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8766     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8767     /* remove and use default one below, we stream like it anyway */
8768     g_free (stream->segments);
8769     stream->segments = NULL;
8770     stream->n_segments = 0;
8771   }
8772
8773   /* no segments, create one to play the complete trak */
8774   if (stream->n_segments == 0) {
8775     GstClockTime stream_duration =
8776         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8777
8778     if (stream->segments == NULL)
8779       stream->segments = g_new (QtDemuxSegment, 1);
8780
8781     /* represent unknown our way */
8782     if (stream_duration == 0)
8783       stream_duration = GST_CLOCK_TIME_NONE;
8784
8785     stream->segments[0].time = 0;
8786     stream->segments[0].stop_time = stream_duration;
8787     stream->segments[0].duration = stream_duration;
8788     stream->segments[0].media_start = 0;
8789     stream->segments[0].media_stop = stream_duration;
8790     stream->segments[0].rate = 1.0;
8791     stream->segments[0].trak_media_start = 0;
8792
8793     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8794         GST_TIME_ARGS (stream_duration));
8795     stream->n_segments = 1;
8796     stream->dummy_segment = TRUE;
8797   }
8798   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8799
8800   return TRUE;
8801 }
8802
8803 /*
8804  * Parses the stsd atom of a svq3 trak looking for
8805  * the SMI and gama atoms.
8806  */
8807 static void
8808 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8809     guint8 ** gamma, GstBuffer ** seqh)
8810 {
8811   guint8 *_gamma = NULL;
8812   GstBuffer *_seqh = NULL;
8813   guint8 *stsd_data = stsd->data;
8814   guint32 length = QT_UINT32 (stsd_data);
8815   guint16 version;
8816
8817   if (length < 32) {
8818     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8819     goto end;
8820   }
8821
8822   stsd_data += 32;
8823   length -= 32;
8824   version = QT_UINT16 (stsd_data);
8825   if (version == 3) {
8826     if (length >= 70) {
8827       length -= 70;
8828       stsd_data += 70;
8829       while (length > 8) {
8830         guint32 fourcc, size;
8831         guint8 *data;
8832         size = QT_UINT32 (stsd_data);
8833         fourcc = QT_FOURCC (stsd_data + 4);
8834         data = stsd_data + 8;
8835
8836         if (size == 0) {
8837           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8838               "svq3 atom parsing");
8839           goto end;
8840         }
8841
8842         switch (fourcc) {
8843           case FOURCC_gama:{
8844             if (size == 12) {
8845               _gamma = data;
8846             } else {
8847               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8848                   " for gama atom, expected 12", size);
8849             }
8850             break;
8851           }
8852           case FOURCC_SMI_:{
8853             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8854               guint32 seqh_size;
8855               if (_seqh != NULL) {
8856                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8857                     " found, ignoring");
8858               } else {
8859                 seqh_size = QT_UINT32 (data + 4);
8860                 if (seqh_size > 0) {
8861                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8862                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8863                 }
8864               }
8865             }
8866             break;
8867           }
8868           default:{
8869             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8870                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8871           }
8872         }
8873
8874         if (size <= length) {
8875           length -= size;
8876           stsd_data += size;
8877         }
8878       }
8879     } else {
8880       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8881     }
8882   } else {
8883     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8884         G_GUINT16_FORMAT, version);
8885     goto end;
8886   }
8887
8888 end:
8889   if (gamma) {
8890     *gamma = _gamma;
8891   }
8892   if (seqh) {
8893     *seqh = _seqh;
8894   } else if (_seqh) {
8895     gst_buffer_unref (_seqh);
8896   }
8897 }
8898
8899 static gchar *
8900 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8901 {
8902   GNode *dinf;
8903   GstByteReader dref;
8904   gchar *uri = NULL;
8905
8906   /*
8907    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8908    * atom that might contain a 'data' atom with the rtsp uri.
8909    * This case was reported in bug #597497, some info about
8910    * the hndl atom can be found in TN1195
8911    */
8912   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8913   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8914
8915   if (dinf) {
8916     guint32 dref_num_entries = 0;
8917     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8918         gst_byte_reader_skip (&dref, 4) &&
8919         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8920       gint i;
8921
8922       /* search dref entries for hndl atom */
8923       for (i = 0; i < dref_num_entries; i++) {
8924         guint32 size = 0, type;
8925         guint8 string_len = 0;
8926         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8927             qt_atom_parser_get_fourcc (&dref, &type)) {
8928           if (type == FOURCC_hndl) {
8929             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8930
8931             /* skip data reference handle bytes and the
8932              * following pascal string and some extra 4
8933              * bytes I have no idea what are */
8934             if (!gst_byte_reader_skip (&dref, 4) ||
8935                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8936                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8937               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8938               break;
8939             }
8940
8941             /* iterate over the atoms to find the data atom */
8942             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8943               guint32 atom_size;
8944               guint32 atom_type;
8945
8946               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8947                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8948                 if (atom_type == FOURCC_data) {
8949                   const guint8 *uri_aux = NULL;
8950
8951                   /* found the data atom that might contain the rtsp uri */
8952                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8953                       "hndl atom, interpreting it as an URI");
8954                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8955                           &uri_aux)) {
8956                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8957                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8958                     else
8959                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8960                           "didn't contain a rtsp address");
8961                   } else {
8962                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8963                         "atom contents");
8964                   }
8965                   break;
8966                 }
8967                 /* skipping to the next entry */
8968                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8969                   break;
8970               } else {
8971                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8972                     "atom header");
8973                 break;
8974               }
8975             }
8976             break;
8977           }
8978           /* skip to the next entry */
8979           if (!gst_byte_reader_skip (&dref, size - 8))
8980             break;
8981         } else {
8982           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8983         }
8984       }
8985       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8986     }
8987   }
8988   return uri;
8989 }
8990
8991 #define AMR_NB_ALL_MODES        0x81ff
8992 #define AMR_WB_ALL_MODES        0x83ff
8993 static guint
8994 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8995 {
8996   /* The 'damr' atom is of the form:
8997    *
8998    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8999    *    32 b       8 b          16 b           8 b                 8 b
9000    *
9001    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9002    * represents the highest mode used in the stream (and thus the maximum
9003    * bitrate), with a couple of special cases as seen below.
9004    */
9005
9006   /* Map of frame type ID -> bitrate */
9007   static const guint nb_bitrates[] = {
9008     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9009   };
9010   static const guint wb_bitrates[] = {
9011     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9012   };
9013   GstMapInfo map;
9014   gsize max_mode;
9015   guint16 mode_set;
9016
9017   gst_buffer_map (buf, &map, GST_MAP_READ);
9018
9019   if (map.size != 0x11) {
9020     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9021     goto bad_data;
9022   }
9023
9024   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9025     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9026         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9027     goto bad_data;
9028   }
9029
9030   mode_set = QT_UINT16 (map.data + 13);
9031
9032   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9033     max_mode = 7 + (wb ? 1 : 0);
9034   else
9035     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9036     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9037
9038   if (max_mode == -1) {
9039     GST_DEBUG ("No mode indication was found (mode set) = %x",
9040         (guint) mode_set);
9041     goto bad_data;
9042   }
9043
9044   gst_buffer_unmap (buf, &map);
9045   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9046
9047 bad_data:
9048   gst_buffer_unmap (buf, &map);
9049   return 0;
9050 }
9051
9052 static gboolean
9053 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9054     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9055 {
9056   /*
9057    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9058    * [0 1 2]
9059    * [3 4 5]
9060    * [6 7 8]
9061    */
9062
9063   if (gst_byte_reader_get_remaining (reader) < 36)
9064     return FALSE;
9065
9066   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9067   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9068   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9069   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9070   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9071   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9072   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9073   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9074   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9075
9076   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9077   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9078       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9079       matrix[2] & 0xFF);
9080   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9081       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9082       matrix[5] & 0xFF);
9083   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9084       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9085       matrix[8] & 0xFF);
9086
9087   return TRUE;
9088 }
9089
9090 static void
9091 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9092     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9093 {
9094
9095 /* [a b c]
9096  * [d e f]
9097  * [g h i]
9098  *
9099  * This macro will only compare value abdegh, it expects cfi to have already
9100  * been checked
9101  */
9102 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9103                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9104
9105   /* only handle the cases where the last column has standard values */
9106   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9107     const gchar *rotation_tag = NULL;
9108
9109     /* no rotation needed */
9110     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9111       /* NOP */
9112     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9113       rotation_tag = "rotate-90";
9114     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9115       rotation_tag = "rotate-180";
9116     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9117       rotation_tag = "rotate-270";
9118     } else {
9119       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9120     }
9121
9122     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9123         rotation_tag);
9124     if (rotation_tag != NULL) {
9125       if (*taglist == NULL)
9126         *taglist = gst_tag_list_new_empty ();
9127       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9128           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9129     }
9130   } else {
9131     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9132   }
9133 }
9134
9135 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9136  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9137  * Common Encryption (cenc), the function will also parse the tenc box (defined
9138  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9139  * (typically an enc[v|a|t|s] sample entry); the function will set
9140  * @original_fmt to the fourcc of the original unencrypted stream format.
9141  * Returns TRUE if successful; FALSE otherwise. */
9142 static gboolean
9143 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9144     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9145 {
9146   GNode *sinf;
9147   GNode *frma;
9148   GNode *schm;
9149   GNode *schi;
9150
9151   g_return_val_if_fail (qtdemux != NULL, FALSE);
9152   g_return_val_if_fail (stream != NULL, FALSE);
9153   g_return_val_if_fail (container != NULL, FALSE);
9154   g_return_val_if_fail (original_fmt != NULL, FALSE);
9155
9156   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9157   if (G_UNLIKELY (!sinf)) {
9158     if (stream->protection_scheme_type == FOURCC_cenc) {
9159       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9160           "mandatory for Common Encryption");
9161       return FALSE;
9162     }
9163     return TRUE;
9164   }
9165
9166   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9167   if (G_UNLIKELY (!frma)) {
9168     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9169     return FALSE;
9170   }
9171
9172   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9173   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9174       GST_FOURCC_ARGS (*original_fmt));
9175
9176   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9177   if (!schm) {
9178     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9179     return FALSE;
9180   }
9181   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9182   stream->protection_scheme_version =
9183       QT_UINT32 ((const guint8 *) schm->data + 16);
9184
9185   GST_DEBUG_OBJECT (qtdemux,
9186       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9187       "protection_scheme_version: %#010x",
9188       GST_FOURCC_ARGS (stream->protection_scheme_type),
9189       stream->protection_scheme_version);
9190
9191   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9192   if (!schi) {
9193     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9194     return FALSE;
9195   }
9196   if (stream->protection_scheme_type == FOURCC_cenc) {
9197     QtDemuxCencSampleSetInfo *info;
9198     GNode *tenc;
9199     const guint8 *tenc_data;
9200     guint32 isEncrypted;
9201     guint8 iv_size;
9202     const guint8 *default_kid;
9203     GstBuffer *kid_buf;
9204
9205     if (G_UNLIKELY (!stream->protection_scheme_info))
9206       stream->protection_scheme_info =
9207           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9208
9209     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9210
9211     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9212     if (!tenc) {
9213       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9214           "which is mandatory for Common Encryption");
9215       return FALSE;
9216     }
9217     tenc_data = (const guint8 *) tenc->data + 12;
9218     isEncrypted = QT_UINT24 (tenc_data);
9219     iv_size = QT_UINT8 (tenc_data + 3);
9220     default_kid = (tenc_data + 4);
9221     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9222     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9223     if (info->default_properties)
9224       gst_structure_free (info->default_properties);
9225     info->default_properties =
9226         gst_structure_new ("application/x-cenc",
9227         "iv_size", G_TYPE_UINT, iv_size,
9228         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9229         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9230     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9231         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9232     gst_buffer_unref (kid_buf);
9233   }
9234   return TRUE;
9235 }
9236
9237 /* parse the traks.
9238  * With each track we associate a new QtDemuxStream that contains all the info
9239  * about the trak.
9240  * traks that do not decode to something (like strm traks) will not have a pad.
9241  */
9242 static gboolean
9243 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9244 {
9245   GstByteReader tkhd;
9246   int offset;
9247   GNode *mdia;
9248   GNode *mdhd;
9249   GNode *hdlr;
9250   GNode *minf;
9251   GNode *stbl;
9252   GNode *stsd;
9253   GNode *mp4a;
9254   GNode *mp4v;
9255   GNode *wave;
9256   GNode *esds;
9257   GNode *pasp;
9258   GNode *colr;
9259   GNode *tref;
9260   GNode *udta;
9261   GNode *svmi;
9262
9263   QtDemuxStream *stream = NULL;
9264   gboolean new_stream = FALSE;
9265   gchar *codec = NULL;
9266   const guint8 *stsd_data;
9267   guint16 lang_code;            /* quicktime lang code or packed iso code */
9268   guint32 version;
9269   guint32 tkhd_flags = 0;
9270   guint8 tkhd_version = 0;
9271   guint32 fourcc;
9272   guint value_size, stsd_len, len;
9273   guint32 track_id;
9274   guint32 dummy;
9275
9276   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9277
9278   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9279       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9280       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9281     goto corrupt_file;
9282
9283   /* pick between 64 or 32 bits */
9284   value_size = tkhd_version == 1 ? 8 : 4;
9285   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9286       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9287     goto corrupt_file;
9288
9289   if (!qtdemux->got_moov) {
9290     if (qtdemux_find_stream (qtdemux, track_id))
9291       goto existing_stream;
9292     stream = _create_stream ();
9293     stream->track_id = track_id;
9294     new_stream = TRUE;
9295   } else {
9296     stream = qtdemux_find_stream (qtdemux, track_id);
9297     if (!stream) {
9298       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9299       goto skip_track;
9300     }
9301
9302     /* flush samples data from this track from previous moov */
9303     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9304     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9305   }
9306   /* need defaults for fragments */
9307   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9308
9309   if (stream->pending_tags == NULL)
9310     stream->pending_tags = gst_tag_list_new_empty ();
9311
9312   if ((tkhd_flags & 1) == 0)
9313     stream->disabled = TRUE;
9314
9315   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9316       tkhd_version, tkhd_flags, stream->track_id);
9317
9318   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9319     goto corrupt_file;
9320
9321   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9322     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9323     if (qtdemux->major_brand != FOURCC_mjp2 ||
9324         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9325       goto corrupt_file;
9326   }
9327
9328   len = QT_UINT32 ((guint8 *) mdhd->data);
9329   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9330   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9331   if (version == 0x01000000) {
9332     if (len < 38)
9333       goto corrupt_file;
9334     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9335     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9336     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9337   } else {
9338     if (len < 30)
9339       goto corrupt_file;
9340     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9341     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9342     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9343   }
9344
9345   if (lang_code < 0x400) {
9346     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9347   } else if (lang_code == 0x7fff) {
9348     stream->lang_id[0] = 0;     /* unspecified */
9349   } else {
9350     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9351     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9352     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9353     stream->lang_id[3] = 0;
9354   }
9355
9356   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9357       stream->timescale);
9358   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9359       stream->duration);
9360   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9361       lang_code, stream->lang_id);
9362
9363   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9364     goto corrupt_file;
9365
9366   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9367     /* chapters track reference */
9368     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9369     if (chap) {
9370       gsize length = GST_READ_UINT32_BE (chap->data);
9371       if (qtdemux->chapters_track_id)
9372         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9373
9374       if (length >= 12) {
9375         qtdemux->chapters_track_id =
9376             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9377       }
9378     }
9379   }
9380
9381   /* fragmented files may have bogus duration in moov */
9382   if (!qtdemux->fragmented &&
9383       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9384     guint64 tdur1, tdur2;
9385
9386     /* don't overflow */
9387     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9388     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9389
9390     /* HACK:
9391      * some of those trailers, nowadays, have prologue images that are
9392      * themselves video tracks as well. I haven't really found a way to
9393      * identify those yet, except for just looking at their duration. */
9394     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9395       GST_WARNING_OBJECT (qtdemux,
9396           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9397           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9398           "found, assuming preview image or something; skipping track",
9399           stream->duration, stream->timescale, qtdemux->duration,
9400           qtdemux->timescale);
9401       if (new_stream)
9402         gst_qtdemux_stream_free (qtdemux, stream);
9403       return TRUE;
9404     }
9405   }
9406
9407   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9408     goto corrupt_file;
9409
9410   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9411       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9412
9413   len = QT_UINT32 ((guint8 *) hdlr->data);
9414   if (len >= 20)
9415     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9416   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9417       GST_FOURCC_ARGS (stream->subtype));
9418
9419   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9420     goto corrupt_file;
9421
9422   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9423     goto corrupt_file;
9424
9425   /*parse svmi header if existing */
9426   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9427   if (svmi) {
9428     len = QT_UINT32 ((guint8 *) svmi->data);
9429     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9430     if (!version) {
9431       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9432       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9433       guint8 frame_type, frame_layout;
9434
9435       /* MPEG-A stereo video */
9436       if (qtdemux->major_brand == FOURCC_ss02)
9437         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9438
9439       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9440       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9441       switch (frame_type) {
9442         case 0:
9443           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9444           break;
9445         case 1:
9446           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9447           break;
9448         case 2:
9449           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9450           break;
9451         case 3:
9452           /* mode 3 is primary/secondary view sequence, ie
9453            * left/right views in separate tracks. See section 7.2
9454            * of ISO/IEC 23000-11:2009 */
9455           GST_FIXME_OBJECT (qtdemux,
9456               "Implement stereo video in separate streams");
9457       }
9458
9459       if ((frame_layout & 0x1) == 0)
9460         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9461
9462       GST_LOG_OBJECT (qtdemux,
9463           "StereoVideo: composition type: %u, is_left_first: %u",
9464           frame_type, frame_layout);
9465       stream->multiview_mode = mode;
9466       stream->multiview_flags = flags;
9467     }
9468   }
9469
9470   /* parse stsd */
9471   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9472     goto corrupt_file;
9473   stsd_data = (const guint8 *) stsd->data;
9474
9475   /* stsd should at least have one entry */
9476   stsd_len = QT_UINT32 (stsd_data);
9477   if (stsd_len < 24) {
9478     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9479     if (stream->subtype == FOURCC_vivo) {
9480       if (new_stream)
9481         gst_qtdemux_stream_free (qtdemux, stream);
9482       return TRUE;
9483     } else {
9484       goto corrupt_file;
9485     }
9486   }
9487
9488   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9489
9490   /* and that entry should fit within stsd */
9491   len = QT_UINT32 (stsd_data + 16);
9492   if (len > stsd_len + 16)
9493     goto corrupt_file;
9494
9495   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9496   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9497       GST_FOURCC_ARGS (stream->fourcc));
9498   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9499
9500   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9501     goto error_encrypted;
9502
9503   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9504     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9505     stream->protected = TRUE;
9506     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9507       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9508   }
9509
9510   if (stream->subtype == FOURCC_vide) {
9511     guint32 w = 0, h = 0;
9512     gboolean gray;
9513     gint depth, palette_size, palette_count;
9514     guint32 matrix[9];
9515     guint32 *palette_data = NULL;
9516
9517     stream->sampled = TRUE;
9518
9519     /* version 1 uses some 64-bit ints */
9520     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9521       goto corrupt_file;
9522
9523     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9524       goto corrupt_file;
9525
9526     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9527         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9528       goto corrupt_file;
9529
9530     stream->display_width = w >> 16;
9531     stream->display_height = h >> 16;
9532
9533     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9534         &stream->pending_tags);
9535
9536     offset = 16;
9537     if (len < 86)
9538       goto corrupt_file;
9539
9540     stream->width = QT_UINT16 (stsd_data + offset + 32);
9541     stream->height = QT_UINT16 (stsd_data + offset + 34);
9542     stream->fps_n = 0;          /* this is filled in later */
9543     stream->fps_d = 0;          /* this is filled in later */
9544     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9545     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9546
9547     /* if color_table_id is 0, ctab atom must follow; however some files
9548      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9549      * if color table is not present we'll correct the value */
9550     if (stream->color_table_id == 0 &&
9551         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9552       stream->color_table_id = -1;
9553     }
9554
9555     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9556         stream->width, stream->height, stream->bits_per_sample,
9557         stream->color_table_id);
9558
9559     depth = stream->bits_per_sample;
9560
9561     /* more than 32 bits means grayscale */
9562     gray = (depth > 32);
9563     /* low 32 bits specify the depth  */
9564     depth &= 0x1F;
9565
9566     /* different number of palette entries is determined by depth. */
9567     palette_count = 0;
9568     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9569       palette_count = (1 << depth);
9570     palette_size = palette_count * 4;
9571
9572     if (stream->color_table_id) {
9573       switch (palette_count) {
9574         case 0:
9575           break;
9576         case 2:
9577           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9578           break;
9579         case 4:
9580           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9581           break;
9582         case 16:
9583           if (gray)
9584             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9585           else
9586             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9587           break;
9588         case 256:
9589           if (gray)
9590             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9591           else
9592             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9593           break;
9594         default:
9595           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9596               (_("The video in this file might not play correctly.")),
9597               ("unsupported palette depth %d", depth));
9598           break;
9599       }
9600     } else {
9601       gint i, j, start, end;
9602
9603       if (len < 94)
9604         goto corrupt_file;
9605
9606       /* read table */
9607       start = QT_UINT32 (stsd_data + offset + 86);
9608       palette_count = QT_UINT16 (stsd_data + offset + 90);
9609       end = QT_UINT16 (stsd_data + offset + 92);
9610
9611       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9612           start, end, palette_count);
9613
9614       if (end > 255)
9615         end = 255;
9616       if (start > end)
9617         start = end;
9618
9619       if (len < 94 + (end - start) * 8)
9620         goto corrupt_file;
9621
9622       /* palette is always the same size */
9623       palette_data = g_malloc0 (256 * 4);
9624       palette_size = 256 * 4;
9625
9626       for (j = 0, i = start; i <= end; j++, i++) {
9627         guint32 a, r, g, b;
9628
9629         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9630         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9631         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9632         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9633
9634         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9635             (g & 0xff00) | (b >> 8);
9636       }
9637     }
9638
9639     if (stream->caps)
9640       gst_caps_unref (stream->caps);
9641
9642     stream->caps =
9643         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9644     if (G_UNLIKELY (!stream->caps)) {
9645       g_free (palette_data);
9646       goto unknown_stream;
9647     }
9648
9649     if (codec) {
9650       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9651           GST_TAG_VIDEO_CODEC, codec, NULL);
9652       g_free (codec);
9653       codec = NULL;
9654     }
9655
9656
9657     if (palette_data) {
9658       GstStructure *s;
9659
9660       if (stream->rgb8_palette)
9661         gst_memory_unref (stream->rgb8_palette);
9662       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9663           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9664
9665       s = gst_caps_get_structure (stream->caps, 0);
9666
9667       /* non-raw video has a palette_data property. raw video has the palette as
9668        * an extra plane that we append to the output buffers before we push
9669        * them*/
9670       if (!gst_structure_has_name (s, "video/x-raw")) {
9671         GstBuffer *palette;
9672
9673         palette = gst_buffer_new ();
9674         gst_buffer_append_memory (palette, stream->rgb8_palette);
9675         stream->rgb8_palette = NULL;
9676
9677         gst_caps_set_simple (stream->caps, "palette_data",
9678             GST_TYPE_BUFFER, palette, NULL);
9679         gst_buffer_unref (palette);
9680       }
9681     } else if (palette_count != 0) {
9682       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9683           (NULL), ("Unsupported palette depth %d", depth));
9684     }
9685
9686     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9687         QT_UINT16 (stsd_data + offset + 48));
9688
9689     esds = NULL;
9690     pasp = NULL;
9691     colr = NULL;
9692     /* pick 'the' stsd child */
9693     if (!stream->protected)
9694       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9695     else
9696       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9697
9698     if (mp4v) {
9699       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9700       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9701       colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
9702     }
9703
9704     if (pasp) {
9705       const guint8 *pasp_data = (const guint8 *) pasp->data;
9706
9707       stream->par_w = QT_UINT32 (pasp_data + 8);
9708       stream->par_h = QT_UINT32 (pasp_data + 12);
9709     } else {
9710       stream->par_w = 0;
9711       stream->par_h = 0;
9712     }
9713
9714     if (colr) {
9715       const guint8 *colr_data = (const guint8 *) colr->data;
9716       gint len = QT_UINT32 (colr_data);
9717
9718       if (len == 19 || len == 18) {
9719         guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
9720
9721         if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
9722           guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
9723           guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
9724           guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
9725           gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
9726
9727           switch (primaries) {
9728             case 1:
9729               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
9730               break;
9731             case 5:
9732               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
9733               break;
9734             case 6:
9735               stream->colorimetry.primaries =
9736                   GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
9737               break;
9738             case 9:
9739               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT2020;
9740               break;
9741             default:
9742               break;
9743           }
9744
9745           switch (transfer_function) {
9746             case 1:
9747               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
9748               break;
9749             case 7:
9750               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE240M;
9751               break;
9752             default:
9753               break;
9754           }
9755
9756           switch (matrix) {
9757             case 1:
9758               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
9759               break;
9760             case 6:
9761               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
9762               break;
9763             case 7:
9764               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_SMPTE240M;
9765               break;
9766             case 9:
9767               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT2020;
9768               break;
9769             default:
9770               break;
9771           }
9772
9773           stream->colorimetry.range =
9774               full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
9775               GST_VIDEO_COLOR_RANGE_16_235;
9776         } else {
9777           GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
9778         }
9779       } else {
9780         GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
9781       }
9782     }
9783
9784     if (esds) {
9785       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9786     } else {
9787       switch (fourcc) {
9788         case FOURCC_H264:
9789         case FOURCC_avc1:
9790         case FOURCC_avc3:
9791         {
9792           gint len = QT_UINT32 (stsd_data) - 0x66;
9793           const guint8 *avc_data = stsd_data + 0x66;
9794
9795           /* find avcC */
9796           while (len >= 0x8) {
9797             gint size;
9798
9799             if (QT_UINT32 (avc_data) <= len)
9800               size = QT_UINT32 (avc_data) - 0x8;
9801             else
9802               size = len - 0x8;
9803
9804             if (size < 1)
9805               /* No real data, so break out */
9806               break;
9807
9808             switch (QT_FOURCC (avc_data + 0x4)) {
9809               case FOURCC_avcC:
9810               {
9811                 /* parse, if found */
9812                 GstBuffer *buf;
9813
9814                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9815
9816                 /* First 4 bytes are the length of the atom, the next 4 bytes
9817                  * are the fourcc, the next 1 byte is the version, and the
9818                  * subsequent bytes are profile_tier_level structure like data. */
9819                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9820                     avc_data + 8 + 1, size - 1);
9821                 buf = gst_buffer_new_and_alloc (size);
9822                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9823                 gst_caps_set_simple (stream->caps,
9824                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9825                 gst_buffer_unref (buf);
9826
9827                 break;
9828               }
9829               case FOURCC_strf:
9830               {
9831                 GstBuffer *buf;
9832
9833                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9834
9835                 /* First 4 bytes are the length of the atom, the next 4 bytes
9836                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9837                  * next 1 byte is the version, and the
9838                  * subsequent bytes are sequence parameter set like data. */
9839
9840                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9841                 if (size > 1) {
9842                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9843                       avc_data + 8 + 40 + 1, size - 1);
9844
9845                   buf = gst_buffer_new_and_alloc (size);
9846                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9847                   gst_caps_set_simple (stream->caps,
9848                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9849                   gst_buffer_unref (buf);
9850                 }
9851                 break;
9852               }
9853               case FOURCC_btrt:
9854               {
9855                 guint avg_bitrate, max_bitrate;
9856
9857                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9858                 if (size < 12)
9859                   break;
9860
9861                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9862                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9863
9864                 if (!max_bitrate && !avg_bitrate)
9865                   break;
9866
9867                 /* Some muxers seem to swap the average and maximum bitrates
9868                  * (I'm looking at you, YouTube), so we swap for sanity. */
9869                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9870                   guint temp = avg_bitrate;
9871
9872                   avg_bitrate = max_bitrate;
9873                   max_bitrate = temp;
9874                 }
9875
9876                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9877                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9878                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9879                 }
9880                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9881                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9882                       GST_TAG_BITRATE, avg_bitrate, NULL);
9883                 }
9884
9885                 break;
9886               }
9887
9888               default:
9889                 break;
9890             }
9891
9892             len -= size + 8;
9893             avc_data += size + 8;
9894           }
9895
9896           break;
9897         }
9898         case FOURCC_H265:
9899         case FOURCC_hvc1:
9900         case FOURCC_hev1:
9901         {
9902           gint len = QT_UINT32 (stsd_data) - 0x66;
9903           const guint8 *hevc_data = stsd_data + 0x66;
9904
9905           /* find hevc */
9906           while (len >= 0x8) {
9907             gint size;
9908
9909             if (QT_UINT32 (hevc_data) <= len)
9910               size = QT_UINT32 (hevc_data) - 0x8;
9911             else
9912               size = len - 0x8;
9913
9914             if (size < 1)
9915               /* No real data, so break out */
9916               break;
9917
9918             switch (QT_FOURCC (hevc_data + 0x4)) {
9919               case FOURCC_hvcC:
9920               {
9921                 /* parse, if found */
9922                 GstBuffer *buf;
9923
9924                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9925
9926                 /* First 4 bytes are the length of the atom, the next 4 bytes
9927                  * are the fourcc, the next 1 byte is the version, and the
9928                  * subsequent bytes are sequence parameter set like data. */
9929                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9930                     (stream->caps, hevc_data + 8 + 1, size - 1);
9931
9932                 buf = gst_buffer_new_and_alloc (size);
9933                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9934                 gst_caps_set_simple (stream->caps,
9935                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9936                 gst_buffer_unref (buf);
9937                 break;
9938               }
9939               default:
9940                 break;
9941             }
9942             len -= size + 8;
9943             hevc_data += size + 8;
9944           }
9945           break;
9946         }
9947         case FOURCC_mp4v:
9948         case FOURCC_MP4V:
9949         case FOURCC_fmp4:
9950         case FOURCC_FMP4:
9951         {
9952           GNode *glbl;
9953
9954           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9955               GST_FOURCC_ARGS (fourcc));
9956
9957           /* codec data might be in glbl extension atom */
9958           glbl = mp4v ?
9959               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9960           if (glbl) {
9961             guint8 *data;
9962             GstBuffer *buf;
9963             gint len;
9964
9965             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9966             data = glbl->data;
9967             len = QT_UINT32 (data);
9968             if (len > 0x8) {
9969               len -= 0x8;
9970               buf = gst_buffer_new_and_alloc (len);
9971               gst_buffer_fill (buf, 0, data + 8, len);
9972               gst_caps_set_simple (stream->caps,
9973                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9974               gst_buffer_unref (buf);
9975             }
9976           }
9977           break;
9978         }
9979         case FOURCC_mjp2:
9980         {
9981           /* see annex I of the jpeg2000 spec */
9982           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9983           const guint8 *data;
9984           const gchar *colorspace = NULL;
9985           gint ncomp = 0;
9986           guint32 ncomp_map = 0;
9987           gint32 *comp_map = NULL;
9988           guint32 nchan_def = 0;
9989           gint32 *chan_def = NULL;
9990
9991           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9992           /* some required atoms */
9993           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9994           if (!mjp2)
9995             break;
9996           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9997           if (!jp2h)
9998             break;
9999
10000           /* number of components; redundant with info in codestream, but useful
10001              to a muxer */
10002           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10003           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10004             break;
10005           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10006
10007           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10008           if (!colr)
10009             break;
10010           GST_DEBUG_OBJECT (qtdemux, "found colr");
10011           /* extract colour space info */
10012           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10013             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10014               case 16:
10015                 colorspace = "sRGB";
10016                 break;
10017               case 17:
10018                 colorspace = "GRAY";
10019                 break;
10020               case 18:
10021                 colorspace = "sYUV";
10022                 break;
10023               default:
10024                 colorspace = NULL;
10025                 break;
10026             }
10027           }
10028           if (!colorspace)
10029             /* colr is required, and only values 16, 17, and 18 are specified,
10030                so error if we have no colorspace */
10031             break;
10032
10033           /* extract component mapping */
10034           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10035           if (cmap) {
10036             guint32 cmap_len = 0;
10037             int i;
10038             cmap_len = QT_UINT32 (cmap->data);
10039             if (cmap_len >= 8) {
10040               /* normal box, subtract off header */
10041               cmap_len -= 8;
10042               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10043               if (cmap_len % 4 == 0) {
10044                 ncomp_map = (cmap_len / 4);
10045                 comp_map = g_new0 (gint32, ncomp_map);
10046                 for (i = 0; i < ncomp_map; i++) {
10047                   guint16 cmp;
10048                   guint8 mtyp, pcol;
10049                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10050                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10051                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10052                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10053                 }
10054               }
10055             }
10056           }
10057           /* extract channel definitions */
10058           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10059           if (cdef) {
10060             guint32 cdef_len = 0;
10061             int i;
10062             cdef_len = QT_UINT32 (cdef->data);
10063             if (cdef_len >= 10) {
10064               /* normal box, subtract off header and len */
10065               cdef_len -= 10;
10066               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10067               if (cdef_len % 6 == 0) {
10068                 nchan_def = (cdef_len / 6);
10069                 chan_def = g_new0 (gint32, nchan_def);
10070                 for (i = 0; i < nchan_def; i++)
10071                   chan_def[i] = -1;
10072                 for (i = 0; i < nchan_def; i++) {
10073                   guint16 cn, typ, asoc;
10074                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10075                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10076                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10077                   if (cn < nchan_def) {
10078                     switch (typ) {
10079                       case 0:
10080                         chan_def[cn] = asoc;
10081                         break;
10082                       case 1:
10083                         chan_def[cn] = 0;       /* alpha */
10084                         break;
10085                       default:
10086                         chan_def[cn] = -typ;
10087                     }
10088                   }
10089                 }
10090               }
10091             }
10092           }
10093
10094           gst_caps_set_simple (stream->caps,
10095               "num-components", G_TYPE_INT, ncomp, NULL);
10096           gst_caps_set_simple (stream->caps,
10097               "colorspace", G_TYPE_STRING, colorspace, NULL);
10098
10099           if (comp_map) {
10100             GValue arr = { 0, };
10101             GValue elt = { 0, };
10102             int i;
10103             g_value_init (&arr, GST_TYPE_ARRAY);
10104             g_value_init (&elt, G_TYPE_INT);
10105             for (i = 0; i < ncomp_map; i++) {
10106               g_value_set_int (&elt, comp_map[i]);
10107               gst_value_array_append_value (&arr, &elt);
10108             }
10109             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10110                 "component-map", &arr);
10111             g_value_unset (&elt);
10112             g_value_unset (&arr);
10113             g_free (comp_map);
10114           }
10115
10116           if (chan_def) {
10117             GValue arr = { 0, };
10118             GValue elt = { 0, };
10119             int i;
10120             g_value_init (&arr, GST_TYPE_ARRAY);
10121             g_value_init (&elt, G_TYPE_INT);
10122             for (i = 0; i < nchan_def; i++) {
10123               g_value_set_int (&elt, chan_def[i]);
10124               gst_value_array_append_value (&arr, &elt);
10125             }
10126             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10127                 "channel-definitions", &arr);
10128             g_value_unset (&elt);
10129             g_value_unset (&arr);
10130             g_free (chan_def);
10131           }
10132
10133           /* some optional atoms */
10134           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10135           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10136
10137           /* indicate possible fields in caps */
10138           if (field) {
10139             data = (guint8 *) field->data + 8;
10140             if (*data != 1)
10141               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
10142                   (gint) * data, NULL);
10143           }
10144           /* add codec_data if provided */
10145           if (prefix) {
10146             GstBuffer *buf;
10147             gint len;
10148
10149             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10150             data = prefix->data;
10151             len = QT_UINT32 (data);
10152             if (len > 0x8) {
10153               len -= 0x8;
10154               buf = gst_buffer_new_and_alloc (len);
10155               gst_buffer_fill (buf, 0, data + 8, len);
10156               gst_caps_set_simple (stream->caps,
10157                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10158               gst_buffer_unref (buf);
10159             }
10160           }
10161           break;
10162         }
10163         case FOURCC_jpeg:
10164         {
10165           /* https://developer.apple.com/standards/qtff-2001.pdf,
10166            * page 92, "Video Sample Description", under table 3.1 */
10167           GstByteReader br;
10168
10169           const off_t compressor_offset =
10170               16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10171           const off_t min_size = compressor_offset + 32 + 2 + 2;
10172           GNode *jpeg;
10173           guint32 len;
10174           guint16 color_table_id = 0;
10175           gboolean ok;
10176
10177           GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10178
10179           /* recover information on interlaced/progressive */
10180           jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10181           if (!jpeg)
10182             break;
10183
10184           len = QT_UINT32 (jpeg->data);
10185           GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %lu", len,
10186               min_size);
10187           if (len >= min_size) {
10188             gst_byte_reader_init (&br, jpeg->data, len);
10189
10190             gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10191             gst_byte_reader_get_uint16_le (&br, &color_table_id);
10192             if (color_table_id != 0) {
10193               /* the spec says there can be concatenated chunks in the data, and we want
10194                * to find one called field. Walk through them. */
10195               off_t offset = min_size;
10196               while (offset + 8 < len) {
10197                 guint32 size = 0, tag;
10198                 ok = gst_byte_reader_get_uint32_le (&br, &size);
10199                 ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10200                 if (!ok || size < 8) {
10201                   GST_WARNING_OBJECT (qtdemux,
10202                       "Failed to walk optional chunk list");
10203                   break;
10204                 }
10205                 GST_DEBUG_OBJECT (qtdemux,
10206                     "Found optional %4.4s chunk, size %u", (const char *) &tag,
10207                     size);
10208                 if (tag == FOURCC_fiel) {
10209                   guint8 n_fields, ordering;
10210                   gst_byte_reader_get_uint8 (&br, &n_fields);
10211                   gst_byte_reader_get_uint8 (&br, &ordering);
10212                   if (n_fields == 1 || n_fields == 2) {
10213                     GST_DEBUG_OBJECT (qtdemux,
10214                         "Found fiel tag with %u fields, ordering %u", n_fields,
10215                         ordering);
10216                     if (n_fields == 2)
10217                       gst_caps_set_simple (stream->caps, "interlace-mode",
10218                           G_TYPE_STRING, "interleaved", NULL);
10219                   } else {
10220                     GST_WARNING_OBJECT (qtdemux,
10221                         "Found fiel tag with invalid fields (%u)", n_fields);
10222                   }
10223                 }
10224                 offset += size;
10225               }
10226             } else {
10227               GST_DEBUG_OBJECT (qtdemux,
10228                   "Color table ID is 0, not trying to get interlacedness");
10229             }
10230           } else {
10231             GST_WARNING_OBJECT (qtdemux,
10232                 "Length of jpeg chunk is too small, not trying to get interlacedness");
10233           }
10234
10235           break;
10236         }
10237         case FOURCC_SVQ3:
10238         case FOURCC_VP31:
10239         {
10240           GstBuffer *buf;
10241           GstBuffer *seqh = NULL;
10242           guint8 *gamma_data = NULL;
10243           gint len = QT_UINT32 (stsd_data);
10244
10245           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
10246           if (gamma_data) {
10247             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
10248                 QT_FP32 (gamma_data), NULL);
10249           }
10250           if (seqh) {
10251             /* sorry for the bad name, but we don't know what this is, other
10252              * than its own fourcc */
10253             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
10254                 NULL);
10255           }
10256
10257           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10258           buf = gst_buffer_new_and_alloc (len);
10259           gst_buffer_fill (buf, 0, stsd_data, len);
10260           gst_caps_set_simple (stream->caps,
10261               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10262           gst_buffer_unref (buf);
10263           break;
10264         }
10265         case FOURCC_rle_:
10266         case FOURCC_WRLE:
10267         {
10268           gst_caps_set_simple (stream->caps,
10269               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
10270           break;
10271         }
10272         case FOURCC_XiTh:
10273         {
10274           GNode *xith, *xdxt;
10275
10276           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10277           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
10278           if (!xith)
10279             break;
10280
10281           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10282           if (!xdxt)
10283             break;
10284
10285           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10286           /* collect the headers and store them in a stream list so that we can
10287            * send them out first */
10288           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10289           break;
10290         }
10291         case FOURCC_ovc1:
10292         {
10293           GNode *ovc1;
10294           guint8 *ovc1_data;
10295           guint ovc1_len;
10296           GstBuffer *buf;
10297
10298           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10299           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
10300           if (!ovc1)
10301             break;
10302           ovc1_data = ovc1->data;
10303           ovc1_len = QT_UINT32 (ovc1_data);
10304           if (ovc1_len <= 198) {
10305             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10306             break;
10307           }
10308           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10309           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10310           gst_caps_set_simple (stream->caps,
10311               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10312           gst_buffer_unref (buf);
10313           break;
10314         }
10315         case FOURCC_vc_1:
10316         {
10317           gint len = QT_UINT32 (stsd_data) - 0x66;
10318           const guint8 *vc1_data = stsd_data + 0x66;
10319
10320           /* find dvc1 */
10321           while (len >= 8) {
10322             gint size;
10323
10324             if (QT_UINT32 (vc1_data) <= len)
10325               size = QT_UINT32 (vc1_data) - 8;
10326             else
10327               size = len - 8;
10328
10329             if (size < 1)
10330               /* No real data, so break out */
10331               break;
10332
10333             switch (QT_FOURCC (vc1_data + 0x4)) {
10334               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10335               {
10336                 GstBuffer *buf;
10337
10338                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10339                 buf = gst_buffer_new_and_alloc (size);
10340                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
10341                 gst_caps_set_simple (stream->caps,
10342                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10343                 gst_buffer_unref (buf);
10344                 break;
10345               }
10346               default:
10347                 break;
10348             }
10349             len -= size + 8;
10350             vc1_data += size + 8;
10351           }
10352           break;
10353         }
10354         default:
10355           break;
10356       }
10357     }
10358
10359     GST_INFO_OBJECT (qtdemux,
10360         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10361         GST_FOURCC_ARGS (fourcc), stream->caps);
10362
10363   } else if (stream->subtype == FOURCC_soun) {
10364     int version, samplesize;
10365     guint16 compression_id;
10366     gboolean amrwb = FALSE;
10367
10368     offset = 32;
10369     /* sample description entry (16) + sound sample description v0 (20) */
10370     if (len < 36)
10371       goto corrupt_file;
10372
10373     version = QT_UINT32 (stsd_data + offset);
10374     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10375     samplesize = QT_UINT16 (stsd_data + offset + 10);
10376     compression_id = QT_UINT16 (stsd_data + offset + 12);
10377     stream->rate = QT_FP32 (stsd_data + offset + 16);
10378
10379     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10380     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10381         QT_UINT32 (stsd_data + offset + 4));
10382     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10383     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10384     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10385     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10386         QT_UINT16 (stsd_data + offset + 14));
10387     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10388
10389     if (compression_id == 0xfffe)
10390       stream->sampled = TRUE;
10391
10392     /* first assume uncompressed audio */
10393     stream->bytes_per_sample = samplesize / 8;
10394     stream->samples_per_frame = stream->n_channels;
10395     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10396     stream->samples_per_packet = stream->samples_per_frame;
10397     stream->bytes_per_packet = stream->bytes_per_sample;
10398
10399     offset = 52;
10400     switch (fourcc) {
10401         /* Yes, these have to be hard-coded */
10402       case FOURCC_MAC6:
10403       {
10404         stream->samples_per_packet = 6;
10405         stream->bytes_per_packet = 1;
10406         stream->bytes_per_frame = 1 * stream->n_channels;
10407         stream->bytes_per_sample = 1;
10408         stream->samples_per_frame = 6 * stream->n_channels;
10409         break;
10410       }
10411       case FOURCC_MAC3:
10412       {
10413         stream->samples_per_packet = 3;
10414         stream->bytes_per_packet = 1;
10415         stream->bytes_per_frame = 1 * stream->n_channels;
10416         stream->bytes_per_sample = 1;
10417         stream->samples_per_frame = 3 * stream->n_channels;
10418         break;
10419       }
10420       case FOURCC_ima4:
10421       {
10422         stream->samples_per_packet = 64;
10423         stream->bytes_per_packet = 34;
10424         stream->bytes_per_frame = 34 * stream->n_channels;
10425         stream->bytes_per_sample = 2;
10426         stream->samples_per_frame = 64 * stream->n_channels;
10427         break;
10428       }
10429       case FOURCC_ulaw:
10430       case FOURCC_alaw:
10431       {
10432         stream->samples_per_packet = 1;
10433         stream->bytes_per_packet = 1;
10434         stream->bytes_per_frame = 1 * stream->n_channels;
10435         stream->bytes_per_sample = 1;
10436         stream->samples_per_frame = 1 * stream->n_channels;
10437         break;
10438       }
10439       case FOURCC_agsm:
10440       {
10441         stream->samples_per_packet = 160;
10442         stream->bytes_per_packet = 33;
10443         stream->bytes_per_frame = 33 * stream->n_channels;
10444         stream->bytes_per_sample = 2;
10445         stream->samples_per_frame = 160 * stream->n_channels;
10446         break;
10447       }
10448       default:
10449         break;
10450     }
10451
10452     if (version == 0x00010000) {
10453       /* sample description entry (16) + sound sample description v1 (20+16) */
10454       if (len < 52)
10455         goto corrupt_file;
10456
10457       switch (fourcc) {
10458         case FOURCC_twos:
10459         case FOURCC_sowt:
10460         case FOURCC_raw_:
10461           break;
10462         default:
10463         {
10464           /* only parse extra decoding config for non-pcm audio */
10465           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10466           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10467           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10468           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10469
10470           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10471               stream->samples_per_packet);
10472           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10473               stream->bytes_per_packet);
10474           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10475               stream->bytes_per_frame);
10476           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10477               stream->bytes_per_sample);
10478
10479           if (!stream->sampled && stream->bytes_per_packet) {
10480             stream->samples_per_frame = (stream->bytes_per_frame /
10481                 stream->bytes_per_packet) * stream->samples_per_packet;
10482             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10483                 stream->samples_per_frame);
10484           }
10485           break;
10486         }
10487       }
10488     } else if (version == 0x00020000) {
10489       union
10490       {
10491         gdouble fp;
10492         guint64 val;
10493       } qtfp;
10494
10495       /* sample description entry (16) + sound sample description v2 (56) */
10496       if (len < 72)
10497         goto corrupt_file;
10498
10499       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10500       stream->rate = qtfp.fp;
10501       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10502
10503       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10504       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10505       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10506       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10507           QT_UINT32 (stsd_data + offset + 20));
10508       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10509           QT_UINT32 (stsd_data + offset + 24));
10510       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10511           QT_UINT32 (stsd_data + offset + 28));
10512       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10513           QT_UINT32 (stsd_data + offset + 32));
10514     } else if (version != 0x00000) {
10515       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10516     }
10517
10518     if (stream->caps)
10519       gst_caps_unref (stream->caps);
10520
10521     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10522         stsd_data + 32, len - 16, &codec);
10523
10524     switch (fourcc) {
10525       case FOURCC_in24:
10526       {
10527         GNode *enda;
10528         GNode *in24;
10529
10530         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10531
10532         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10533         if (!enda) {
10534           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10535           if (wave)
10536             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10537         }
10538         if (enda) {
10539           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10540           gst_caps_set_simple (stream->caps,
10541               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10542         }
10543         break;
10544       }
10545       case FOURCC_owma:
10546       {
10547         GNode *owma;
10548         const guint8 *owma_data;
10549         const gchar *codec_name = NULL;
10550         guint owma_len;
10551         GstBuffer *buf;
10552         gint version = 1;
10553         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10554         /* FIXME this should also be gst_riff_strf_auds,
10555          * but the latter one is actually missing bits-per-sample :( */
10556         typedef struct
10557         {
10558           gint16 wFormatTag;
10559           gint16 nChannels;
10560           gint32 nSamplesPerSec;
10561           gint32 nAvgBytesPerSec;
10562           gint16 nBlockAlign;
10563           gint16 wBitsPerSample;
10564           gint16 cbSize;
10565         } WAVEFORMATEX;
10566         WAVEFORMATEX *wfex;
10567
10568         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10569         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10570         if (!owma)
10571           break;
10572         owma_data = owma->data;
10573         owma_len = QT_UINT32 (owma_data);
10574         if (owma_len <= 54) {
10575           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10576           break;
10577         }
10578         wfex = (WAVEFORMATEX *) (owma_data + 36);
10579         buf = gst_buffer_new_and_alloc (owma_len - 54);
10580         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10581         if (wfex->wFormatTag == 0x0161) {
10582           codec_name = "Windows Media Audio";
10583           version = 2;
10584         } else if (wfex->wFormatTag == 0x0162) {
10585           codec_name = "Windows Media Audio 9 Pro";
10586           version = 3;
10587         } else if (wfex->wFormatTag == 0x0163) {
10588           codec_name = "Windows Media Audio 9 Lossless";
10589           /* is that correct? gstffmpegcodecmap.c is missing it, but
10590            * fluendo codec seems to support it */
10591           version = 4;
10592         }
10593
10594         gst_caps_set_simple (stream->caps,
10595             "codec_data", GST_TYPE_BUFFER, buf,
10596             "wmaversion", G_TYPE_INT, version,
10597             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10598             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10599             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10600             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10601             NULL);
10602         gst_buffer_unref (buf);
10603
10604         if (codec_name) {
10605           g_free (codec);
10606           codec = g_strdup (codec_name);
10607         }
10608         break;
10609       }
10610       case FOURCC_wma_:
10611       {
10612         gint len = QT_UINT32 (stsd_data) - offset;
10613         const guint8 *wfex_data = stsd_data + offset;
10614         const gchar *codec_name = NULL;
10615         gint version = 1;
10616         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10617         /* FIXME this should also be gst_riff_strf_auds,
10618          * but the latter one is actually missing bits-per-sample :( */
10619         typedef struct
10620         {
10621           gint16 wFormatTag;
10622           gint16 nChannels;
10623           gint32 nSamplesPerSec;
10624           gint32 nAvgBytesPerSec;
10625           gint16 nBlockAlign;
10626           gint16 wBitsPerSample;
10627           gint16 cbSize;
10628         } WAVEFORMATEX;
10629         WAVEFORMATEX wfex;
10630
10631         /* FIXME: unify with similar wavformatex parsing code above */
10632         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10633
10634         /* find wfex */
10635         while (len >= 8) {
10636           gint size;
10637
10638           if (QT_UINT32 (wfex_data) <= len)
10639             size = QT_UINT32 (wfex_data) - 8;
10640           else
10641             size = len - 8;
10642
10643           if (size < 1)
10644             /* No real data, so break out */
10645             break;
10646
10647           switch (QT_FOURCC (wfex_data + 4)) {
10648             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10649             {
10650               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10651
10652               if (size < 8 + 18)
10653                 break;
10654
10655               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10656               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10657               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10658               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10659               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10660               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10661               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10662
10663               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10664               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10665                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10666                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10667                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10668                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10669
10670               if (wfex.wFormatTag == 0x0161) {
10671                 codec_name = "Windows Media Audio";
10672                 version = 2;
10673               } else if (wfex.wFormatTag == 0x0162) {
10674                 codec_name = "Windows Media Audio 9 Pro";
10675                 version = 3;
10676               } else if (wfex.wFormatTag == 0x0163) {
10677                 codec_name = "Windows Media Audio 9 Lossless";
10678                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10679                  * fluendo codec seems to support it */
10680                 version = 4;
10681               }
10682
10683               gst_caps_set_simple (stream->caps,
10684                   "wmaversion", G_TYPE_INT, version,
10685                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10686                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10687                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10688                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10689
10690               if (size > wfex.cbSize) {
10691                 GstBuffer *buf;
10692
10693                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10694                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10695                     size - wfex.cbSize);
10696                 gst_caps_set_simple (stream->caps,
10697                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10698                 gst_buffer_unref (buf);
10699               } else {
10700                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10701               }
10702
10703               if (codec_name) {
10704                 g_free (codec);
10705                 codec = g_strdup (codec_name);
10706               }
10707               break;
10708             }
10709             default:
10710               break;
10711           }
10712           len -= size + 8;
10713           wfex_data += size + 8;
10714         }
10715         break;
10716       }
10717       case FOURCC_opus:
10718       {
10719         GNode *opus;
10720         const guint8 *opus_data;
10721         guint8 *channel_mapping = NULL;
10722         guint32 rate;
10723         guint8 channels;
10724         guint8 channel_mapping_family;
10725         guint8 stream_count;
10726         guint8 coupled_count;
10727         guint8 i;
10728
10729         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10730         opus_data = opus->data;
10731
10732         channels = GST_READ_UINT8 (opus_data + 45);
10733         rate = GST_READ_UINT32_LE (opus_data + 48);
10734         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10735         stream_count = GST_READ_UINT8 (opus_data + 55);
10736         coupled_count = GST_READ_UINT8 (opus_data + 56);
10737
10738         if (channels > 0) {
10739           channel_mapping = g_malloc (channels * sizeof (guint8));
10740           for (i = 0; i < channels; i++)
10741             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10742         }
10743
10744         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10745             channel_mapping_family, stream_count, coupled_count,
10746             channel_mapping);
10747         break;
10748       }
10749       default:
10750         break;
10751     }
10752
10753     if (codec) {
10754       GstStructure *s;
10755       gint bitrate = 0;
10756
10757       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10758           GST_TAG_AUDIO_CODEC, codec, NULL);
10759       g_free (codec);
10760       codec = NULL;
10761
10762       /* some bitrate info may have ended up in caps */
10763       s = gst_caps_get_structure (stream->caps, 0);
10764       gst_structure_get_int (s, "bitrate", &bitrate);
10765       if (bitrate > 0)
10766         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10767             GST_TAG_BITRATE, bitrate, NULL);
10768     }
10769
10770     if (stream->protected && fourcc == FOURCC_mp4a)
10771       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10772     else
10773       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10774
10775     wave = NULL;
10776     esds = NULL;
10777     if (mp4a) {
10778       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10779       if (wave)
10780         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10781       if (!esds)
10782         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10783     }
10784
10785
10786     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10787        16 bits is a byte-swapped wave-style codec identifier,
10788        and we can find a WAVE header internally to a 'wave' atom here.
10789        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10790        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10791        is big-endian).
10792      */
10793     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10794       if (len < offset + 20) {
10795         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10796       } else {
10797         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10798         const guint8 *data = stsd_data + offset + 16;
10799         GNode *wavenode;
10800         GNode *waveheadernode;
10801
10802         wavenode = g_node_new ((guint8 *) data);
10803         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10804           const guint8 *waveheader;
10805           guint32 headerlen;
10806
10807           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10808           if (waveheadernode) {
10809             waveheader = (const guint8 *) waveheadernode->data;
10810             headerlen = QT_UINT32 (waveheader);
10811
10812             if (headerlen > 8) {
10813               gst_riff_strf_auds *header = NULL;
10814               GstBuffer *headerbuf;
10815               GstBuffer *extra;
10816
10817               waveheader += 8;
10818               headerlen -= 8;
10819
10820               headerbuf = gst_buffer_new_and_alloc (headerlen);
10821               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10822
10823               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10824                       headerbuf, &header, &extra)) {
10825                 gst_caps_unref (stream->caps);
10826                 /* FIXME: Need to do something with the channel reorder map */
10827                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10828                     header, extra, NULL, NULL, NULL);
10829
10830                 if (extra)
10831                   gst_buffer_unref (extra);
10832                 g_free (header);
10833               }
10834             }
10835           } else
10836             GST_DEBUG ("Didn't find waveheadernode for this codec");
10837         }
10838         g_node_destroy (wavenode);
10839       }
10840     } else if (esds) {
10841       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10842     } else {
10843       switch (fourcc) {
10844 #if 0
10845           /* FIXME: what is in the chunk? */
10846         case FOURCC_QDMC:
10847         {
10848           gint len = QT_UINT32 (stsd_data);
10849
10850           /* seems to be always = 116 = 0x74 */
10851           break;
10852         }
10853 #endif
10854         case FOURCC_QDM2:
10855         {
10856           gint len = QT_UINT32 (stsd_data);
10857
10858           if (len > 0x4C) {
10859             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10860
10861             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10862             gst_caps_set_simple (stream->caps,
10863                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10864             gst_buffer_unref (buf);
10865           }
10866           gst_caps_set_simple (stream->caps,
10867               "samplesize", G_TYPE_INT, samplesize, NULL);
10868           break;
10869         }
10870         case FOURCC_alac:
10871         {
10872           GNode *alac, *wave = NULL;
10873
10874           /* apparently, m4a has this atom appended directly in the stsd entry,
10875            * while mov has it in a wave atom */
10876           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10877           if (alac) {
10878             /* alac now refers to stsd entry atom */
10879             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10880             if (wave)
10881               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10882             else
10883               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10884           }
10885           if (alac) {
10886             const guint8 *alac_data = alac->data;
10887             gint len = QT_UINT32 (alac->data);
10888             GstBuffer *buf;
10889
10890             if (len < 36) {
10891               GST_DEBUG_OBJECT (qtdemux,
10892                   "discarding alac atom with unexpected len %d", len);
10893             } else {
10894               /* codec-data contains alac atom size and prefix,
10895                * ffmpeg likes it that way, not quite gst-ish though ...*/
10896               buf = gst_buffer_new_and_alloc (len);
10897               gst_buffer_fill (buf, 0, alac->data, len);
10898               gst_caps_set_simple (stream->caps,
10899                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10900               gst_buffer_unref (buf);
10901
10902               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10903               stream->n_channels = QT_UINT8 (alac_data + 21);
10904               stream->rate = QT_UINT32 (alac_data + 32);
10905             }
10906           }
10907           gst_caps_set_simple (stream->caps,
10908               "samplesize", G_TYPE_INT, samplesize, NULL);
10909           break;
10910         }
10911         case FOURCC_fLaC:
10912         {
10913           /* The codingname of the sample entry is 'fLaC' */
10914           GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
10915
10916           if (flac) {
10917             /* The 'dfLa' box is added to the sample entry to convey
10918                initializing information for the decoder. */
10919             const GNode *dfla =
10920                 qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
10921
10922             if (dfla) {
10923               const guint32 len = QT_UINT32 (dfla->data);
10924
10925               /* Must contain at least dfLa box header (12),
10926                * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
10927               if (len < 50) {
10928                 GST_DEBUG_OBJECT (qtdemux,
10929                     "discarding dfla atom with unexpected len %d", len);
10930               } else {
10931                 /* skip dfLa header to get the METADATA_BLOCKs */
10932                 const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
10933                 const guint32 metadata_blocks_len = len - 12;
10934
10935                 gchar *stream_marker = g_strdup ("fLaC");
10936                 GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
10937                     strlen (stream_marker));
10938
10939                 guint index = 0;
10940                 gboolean is_last = FALSE;
10941
10942                 GValue array = G_VALUE_INIT;
10943                 GValue value = G_VALUE_INIT;
10944
10945                 g_value_init (&array, GST_TYPE_ARRAY);
10946                 g_value_init (&value, GST_TYPE_BUFFER);
10947
10948                 gst_value_set_buffer (&value, block);
10949                 gst_value_array_append_value (&array, &value);
10950                 g_value_reset (&value);
10951
10952                 gst_buffer_unref (block);
10953
10954                 while (is_last == FALSE && index < metadata_blocks_len) {
10955                   /* add the METADATA_BLOCK_HEADER size to the signalled size */
10956                   const guint block_size = 4 +
10957                       (metadata_blocks[index + 1] << 16) +
10958                       (metadata_blocks[index + 2] << 8) +
10959                       metadata_blocks[index + 3];
10960
10961                   is_last = metadata_blocks[index] >> 7;
10962
10963                   block = gst_buffer_new_and_alloc (block_size);
10964
10965                   gst_buffer_fill (block, 0, &metadata_blocks[index],
10966                       block_size);
10967
10968                   gst_value_set_buffer (&value, block);
10969                   gst_value_array_append_value (&array, &value);
10970                   g_value_reset (&value);
10971
10972                   gst_buffer_unref (block);
10973
10974                   index += block_size;
10975                 }
10976
10977                 gst_structure_set_value (gst_caps_get_structure (stream->caps,
10978                         0), "streamheader", &array);
10979
10980                 g_value_unset (&value);
10981                 g_value_unset (&array);
10982
10983                 /* The sample rate obtained from the stsd may not be accurate
10984                  * since it cannot represent rates greater than 65535Hz, so
10985                  * override that value with the sample rate from the
10986                  * METADATA_BLOCK_STREAMINFO block */
10987                 stream->rate =
10988                     (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
10989               }
10990             }
10991           }
10992           break;
10993         }
10994         case FOURCC_sawb:
10995           /* Fallthrough! */
10996           amrwb = TRUE;
10997         case FOURCC_samr:
10998         {
10999           gint len = QT_UINT32 (stsd_data);
11000
11001           if (len > 0x34) {
11002             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
11003             guint bitrate;
11004
11005             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
11006
11007             /* If we have enough data, let's try to get the 'damr' atom. See
11008              * the 3GPP container spec (26.244) for more details. */
11009             if ((len - 0x34) > 8 &&
11010                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11011               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11012                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11013             }
11014
11015             gst_caps_set_simple (stream->caps,
11016                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11017             gst_buffer_unref (buf);
11018           }
11019           break;
11020         }
11021         case FOURCC_mp4a:
11022         {
11023           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11024           gint len = QT_UINT32 (stsd_data);
11025
11026           if (len >= 50) {
11027             guint16 sound_version = QT_UINT16 (stsd_data + 32);
11028
11029             if (sound_version == 1) {
11030               guint16 channels = QT_UINT16 (stsd_data + 40);
11031               guint32 time_scale = QT_UINT32 (stsd_data + 46);
11032               guint8 codec_data[2];
11033               GstBuffer *buf;
11034               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11035
11036               gint sample_rate_index =
11037                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11038
11039               /* build AAC codec data */
11040               codec_data[0] = profile << 3;
11041               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11042               codec_data[1] = (sample_rate_index & 0x01) << 7;
11043               codec_data[1] |= (channels & 0xF) << 3;
11044
11045               buf = gst_buffer_new_and_alloc (2);
11046               gst_buffer_fill (buf, 0, codec_data, 2);
11047               gst_caps_set_simple (stream->caps,
11048                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11049               gst_buffer_unref (buf);
11050             }
11051           }
11052           break;
11053         }
11054         default:
11055           GST_INFO_OBJECT (qtdemux,
11056               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11057           break;
11058       }
11059     }
11060     GST_INFO_OBJECT (qtdemux,
11061         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11062         GST_FOURCC_ARGS (fourcc), stream->caps);
11063
11064   } else if (stream->subtype == FOURCC_strm) {
11065     if (fourcc == FOURCC_rtsp) {
11066       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11067     } else {
11068       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11069           GST_FOURCC_ARGS (fourcc));
11070       goto unknown_stream;
11071     }
11072     stream->sampled = TRUE;
11073   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11074       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11075
11076     stream->sampled = TRUE;
11077     stream->sparse = TRUE;
11078
11079     stream->caps =
11080         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
11081     if (codec) {
11082       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11083           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11084       g_free (codec);
11085       codec = NULL;
11086     }
11087
11088     /* hunt for sort-of codec data */
11089     switch (fourcc) {
11090       case FOURCC_mp4s:
11091       {
11092         GNode *mp4s = NULL;
11093         GNode *esds = NULL;
11094
11095         /* look for palette in a stsd->mp4s->esds sub-atom */
11096         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11097         if (mp4s)
11098           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11099         if (esds == NULL) {
11100           /* Invalid STSD */
11101           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11102           break;
11103         }
11104
11105         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
11106         break;
11107       }
11108       default:
11109         GST_INFO_OBJECT (qtdemux,
11110             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11111         break;
11112     }
11113     GST_INFO_OBJECT (qtdemux,
11114         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11115         GST_FOURCC_ARGS (fourcc), stream->caps);
11116   } else {
11117     /* everything in 1 sample */
11118     stream->sampled = TRUE;
11119
11120     stream->caps =
11121         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
11122
11123     if (stream->caps == NULL)
11124       goto unknown_stream;
11125
11126     if (codec) {
11127       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11128           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11129       g_free (codec);
11130       codec = NULL;
11131     }
11132   }
11133
11134   /* promote to sampled format */
11135   if (stream->fourcc == FOURCC_samr) {
11136     /* force mono 8000 Hz for AMR */
11137     stream->sampled = TRUE;
11138     stream->n_channels = 1;
11139     stream->rate = 8000;
11140   } else if (stream->fourcc == FOURCC_sawb) {
11141     /* force mono 16000 Hz for AMR-WB */
11142     stream->sampled = TRUE;
11143     stream->n_channels = 1;
11144     stream->rate = 16000;
11145   } else if (stream->fourcc == FOURCC_mp4a) {
11146     stream->sampled = TRUE;
11147   }
11148
11149   /* collect sample information */
11150   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11151     goto samples_failed;
11152
11153   if (qtdemux->fragmented) {
11154     guint64 offset;
11155
11156     /* need all moov samples as basis; probably not many if any at all */
11157     /* prevent moof parsing taking of at this time */
11158     offset = qtdemux->moof_offset;
11159     qtdemux->moof_offset = 0;
11160     if (stream->n_samples &&
11161         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11162       qtdemux->moof_offset = offset;
11163       goto samples_failed;
11164     }
11165     qtdemux->moof_offset = 0;
11166     /* movie duration more reliable in this case (e.g. mehd) */
11167     if (qtdemux->segment.duration &&
11168         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11169       stream->duration =
11170           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11171   }
11172
11173   /* configure segments */
11174   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11175     goto segments_failed;
11176
11177   /* add some language tag, if useful */
11178   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11179       strcmp (stream->lang_id, "und")) {
11180     const gchar *lang_code;
11181
11182     /* convert ISO 639-2 code to ISO 639-1 */
11183     lang_code = gst_tag_get_language_code (stream->lang_id);
11184     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11185         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11186   }
11187
11188   /* Check for UDTA tags */
11189   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11190     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
11191   }
11192
11193   /* now we are ready to add the stream */
11194   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11195     goto too_many_streams;
11196
11197   if (!qtdemux->got_moov) {
11198     qtdemux->streams[qtdemux->n_streams] = stream;
11199     qtdemux->n_streams++;
11200     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11201   }
11202
11203   return TRUE;
11204
11205 /* ERRORS */
11206 skip_track:
11207   {
11208     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11209     if (new_stream)
11210       gst_qtdemux_stream_free (qtdemux, stream);
11211     return TRUE;
11212   }
11213 corrupt_file:
11214   {
11215     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11216         (_("This file is corrupt and cannot be played.")), (NULL));
11217     if (new_stream)
11218       gst_qtdemux_stream_free (qtdemux, stream);
11219     return FALSE;
11220   }
11221 error_encrypted:
11222   {
11223     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11224     if (new_stream)
11225       gst_qtdemux_stream_free (qtdemux, stream);
11226     return FALSE;
11227   }
11228 samples_failed:
11229 segments_failed:
11230   {
11231     /* we posted an error already */
11232     /* free stbl sub-atoms */
11233     gst_qtdemux_stbl_free (stream);
11234     if (new_stream)
11235       gst_qtdemux_stream_free (qtdemux, stream);
11236     return FALSE;
11237   }
11238 existing_stream:
11239   {
11240     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11241         track_id);
11242     if (new_stream)
11243       gst_qtdemux_stream_free (qtdemux, stream);
11244     return TRUE;
11245   }
11246 unknown_stream:
11247   {
11248     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11249         GST_FOURCC_ARGS (stream->subtype));
11250     if (new_stream)
11251       gst_qtdemux_stream_free (qtdemux, stream);
11252     return TRUE;
11253   }
11254 too_many_streams:
11255   {
11256     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11257         (_("This file contains too many streams. Only playing first %d"),
11258             GST_QTDEMUX_MAX_STREAMS), (NULL));
11259     return TRUE;
11260   }
11261 }
11262
11263 /* If we can estimate the overall bitrate, and don't have information about the
11264  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11265  * the overall bitrate minus the sum of the bitrates of all other streams. This
11266  * should be useful for the common case where we have one audio and one video
11267  * stream and can estimate the bitrate of one, but not the other. */
11268 static void
11269 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11270 {
11271   QtDemuxStream *stream = NULL;
11272   gint64 size, sys_bitrate, sum_bitrate = 0;
11273   GstClockTime duration;
11274   gint i;
11275   guint bitrate;
11276
11277   if (qtdemux->fragmented)
11278     return;
11279
11280   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11281
11282   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11283       || size <= 0) {
11284     GST_DEBUG_OBJECT (qtdemux,
11285         "Size in bytes of the stream not known - bailing");
11286     return;
11287   }
11288
11289   /* Subtract the header size */
11290   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11291       size, qtdemux->header_size);
11292
11293   if (size < qtdemux->header_size)
11294     return;
11295
11296   size = size - qtdemux->header_size;
11297
11298   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11299     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11300     return;
11301   }
11302
11303   for (i = 0; i < qtdemux->n_streams; i++) {
11304     switch (qtdemux->streams[i]->subtype) {
11305       case FOURCC_soun:
11306       case FOURCC_vide:
11307         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11308             qtdemux->streams[i]->caps);
11309         /* retrieve bitrate, prefer avg then max */
11310         bitrate = 0;
11311         if (qtdemux->streams[i]->pending_tags) {
11312           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11313               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11314           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11315           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11316               GST_TAG_NOMINAL_BITRATE, &bitrate);
11317           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11318           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11319               GST_TAG_BITRATE, &bitrate);
11320           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11321         }
11322         if (bitrate)
11323           sum_bitrate += bitrate;
11324         else {
11325           if (stream) {
11326             GST_DEBUG_OBJECT (qtdemux,
11327                 ">1 stream with unknown bitrate - bailing");
11328             return;
11329           } else
11330             stream = qtdemux->streams[i];
11331         }
11332
11333       default:
11334         /* For other subtypes, we assume no significant impact on bitrate */
11335         break;
11336     }
11337   }
11338
11339   if (!stream) {
11340     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11341     return;
11342   }
11343
11344   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11345
11346   if (sys_bitrate < sum_bitrate) {
11347     /* This can happen, since sum_bitrate might be derived from maximum
11348      * bitrates and not average bitrates */
11349     GST_DEBUG_OBJECT (qtdemux,
11350         "System bitrate less than sum bitrate - bailing");
11351     return;
11352   }
11353
11354   bitrate = sys_bitrate - sum_bitrate;
11355   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11356       ", Stream bitrate = %u", sys_bitrate, bitrate);
11357
11358   if (!stream->pending_tags)
11359     stream->pending_tags = gst_tag_list_new_empty ();
11360
11361   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11362       GST_TAG_BITRATE, bitrate, NULL);
11363 }
11364
11365 static GstFlowReturn
11366 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11367 {
11368   gint i;
11369   GstFlowReturn ret = GST_FLOW_OK;
11370
11371   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11372
11373   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11374     QtDemuxStream *stream = qtdemux->streams[i];
11375     guint32 sample_num = 0;
11376
11377     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11378         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11379
11380     if (qtdemux->fragmented) {
11381       /* need all moov samples first */
11382       GST_OBJECT_LOCK (qtdemux);
11383       while (stream->n_samples == 0)
11384         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11385           break;
11386       GST_OBJECT_UNLOCK (qtdemux);
11387     } else {
11388       /* discard any stray moof */
11389       qtdemux->moof_offset = 0;
11390     }
11391
11392     /* prepare braking */
11393     if (ret != GST_FLOW_ERROR)
11394       ret = GST_FLOW_OK;
11395
11396     /* in pull mode, we should have parsed some sample info by now;
11397      * and quite some code will not handle no samples.
11398      * in push mode, we'll just have to deal with it */
11399     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11400       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11401       gst_qtdemux_remove_stream (qtdemux, i);
11402       i--;
11403       continue;
11404     }
11405
11406     /* parse the initial sample for use in setting the frame rate cap */
11407     while (sample_num == 0 && sample_num < stream->n_samples) {
11408       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11409         break;
11410       ++sample_num;
11411     }
11412     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11413       stream->first_duration = stream->samples[0].duration;
11414       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11415           stream->track_id, stream->first_duration);
11416     }
11417   }
11418
11419   return ret;
11420 }
11421
11422 static GstFlowReturn
11423 qtdemux_expose_streams (GstQTDemux * qtdemux)
11424 {
11425   gint i;
11426   GSList *oldpads = NULL;
11427   GSList *iter;
11428
11429   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11430
11431   for (i = 0; i < qtdemux->n_streams; i++) {
11432     QtDemuxStream *stream = qtdemux->streams[i];
11433     GstPad *oldpad = stream->pad;
11434     GstTagList *list;
11435
11436     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11437         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11438
11439     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11440         stream->track_id == qtdemux->chapters_track_id) {
11441       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11442          so that it doesn't look like a subtitle track */
11443       gst_qtdemux_remove_stream (qtdemux, i);
11444       i--;
11445       continue;
11446     }
11447
11448     /* now we have all info and can expose */
11449     list = stream->pending_tags;
11450     stream->pending_tags = NULL;
11451     if (oldpad)
11452       oldpads = g_slist_prepend (oldpads, oldpad);
11453     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11454       return GST_FLOW_ERROR;
11455   }
11456
11457   gst_qtdemux_guess_bitrate (qtdemux);
11458
11459   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11460
11461   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11462     GstPad *oldpad = iter->data;
11463     GstEvent *event;
11464
11465     event = gst_event_new_eos ();
11466     if (qtdemux->segment_seqnum)
11467       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11468
11469     gst_pad_push_event (oldpad, event);
11470     gst_pad_set_active (oldpad, FALSE);
11471     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11472     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11473     gst_object_unref (oldpad);
11474   }
11475
11476   /* check if we should post a redirect in case there is a single trak
11477    * and it is a redirecting trak */
11478   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11479     GstMessage *m;
11480
11481     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11482         "an external content");
11483     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11484         gst_structure_new ("redirect",
11485             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11486             NULL));
11487     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11488     qtdemux->posted_redirect = TRUE;
11489   }
11490
11491   for (i = 0; i < qtdemux->n_streams; i++) {
11492     QtDemuxStream *stream = qtdemux->streams[i];
11493
11494     qtdemux_do_allocation (qtdemux, stream);
11495   }
11496
11497   qtdemux->exposed = TRUE;
11498   return GST_FLOW_OK;
11499 }
11500
11501 /* check if major or compatible brand is 3GP */
11502 static inline gboolean
11503 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11504 {
11505   if (major) {
11506     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11507         FOURCC_3g__);
11508   } else if (qtdemux->comp_brands != NULL) {
11509     GstMapInfo map;
11510     guint8 *data;
11511     gsize size;
11512     gboolean res = FALSE;
11513
11514     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11515     data = map.data;
11516     size = map.size;
11517     while (size >= 4) {
11518       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11519           FOURCC_3g__);
11520       data += 4;
11521       size -= 4;
11522     }
11523     gst_buffer_unmap (qtdemux->comp_brands, &map);
11524     return res;
11525   } else {
11526     return FALSE;
11527   }
11528 }
11529
11530 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11531 static inline gboolean
11532 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11533 {
11534   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11535       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11536       || fourcc == FOURCC_albm;
11537 }
11538
11539 static void
11540 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11541     const char *tag, const char *dummy, GNode * node)
11542 {
11543   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11544   int offset;
11545   char *name;
11546   gchar *data;
11547   gdouble longitude, latitude, altitude;
11548   gint len;
11549
11550   len = QT_UINT32 (node->data);
11551   if (len <= 14)
11552     goto short_read;
11553
11554   data = node->data;
11555   offset = 14;
11556
11557   /* TODO: language code skipped */
11558
11559   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11560
11561   if (!name) {
11562     /* do not alarm in trivial case, but bail out otherwise */
11563     if (*(data + offset) != 0) {
11564       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11565           "giving up", tag);
11566     }
11567   } else {
11568     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11569         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11570     offset += strlen (name);
11571     g_free (name);
11572   }
11573
11574   if (len < offset + 2 + 4 + 4 + 4)
11575     goto short_read;
11576
11577   /* +1 +1 = skip null-terminator and location role byte */
11578   offset += 1 + 1;
11579   /* table in spec says unsigned, semantics say negative has meaning ... */
11580   longitude = QT_SFP32 (data + offset);
11581
11582   offset += 4;
11583   latitude = QT_SFP32 (data + offset);
11584
11585   offset += 4;
11586   altitude = QT_SFP32 (data + offset);
11587
11588   /* one invalid means all are invalid */
11589   if (longitude >= -180.0 && longitude <= 180.0 &&
11590       latitude >= -90.0 && latitude <= 90.0) {
11591     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11592         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11593         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11594         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11595   }
11596
11597   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11598
11599   return;
11600
11601   /* ERRORS */
11602 short_read:
11603   {
11604     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11605     return;
11606   }
11607 }
11608
11609
11610 static void
11611 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11612     const char *tag, const char *dummy, GNode * node)
11613 {
11614   guint16 y;
11615   GDate *date;
11616   gint len;
11617
11618   len = QT_UINT32 (node->data);
11619   if (len < 14)
11620     return;
11621
11622   y = QT_UINT16 ((guint8 *) node->data + 12);
11623   if (y == 0) {
11624     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11625     return;
11626   }
11627   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11628
11629   date = g_date_new_dmy (1, 1, y);
11630   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11631   g_date_free (date);
11632 }
11633
11634 static void
11635 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11636     const char *tag, const char *dummy, GNode * node)
11637 {
11638   int offset;
11639   char *tag_str = NULL;
11640   guint8 *entity;
11641   guint16 table;
11642   gint len;
11643
11644   len = QT_UINT32 (node->data);
11645   if (len <= 20)
11646     goto short_read;
11647
11648   offset = 12;
11649   entity = (guint8 *) node->data + offset;
11650   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11651     GST_DEBUG_OBJECT (qtdemux,
11652         "classification info: %c%c%c%c invalid classification entity",
11653         entity[0], entity[1], entity[2], entity[3]);
11654     return;
11655   }
11656
11657   offset += 4;
11658   table = QT_UINT16 ((guint8 *) node->data + offset);
11659
11660   /* Language code skipped */
11661
11662   offset += 4;
11663
11664   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11665    * XXXX: classification entity, fixed length 4 chars.
11666    * Y[YYYY]: classification table, max 5 chars.
11667    */
11668   tag_str = g_strdup_printf ("----://%u/%s",
11669       table, (char *) node->data + offset);
11670
11671   /* memcpy To be sure we're preserving byte order */
11672   memcpy (tag_str, entity, 4);
11673   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11674
11675   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11676
11677   g_free (tag_str);
11678
11679   return;
11680
11681   /* ERRORS */
11682 short_read:
11683   {
11684     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11685     return;
11686   }
11687 }
11688
11689 static gboolean
11690 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11691     const char *tag, const char *dummy, GNode * node)
11692 {
11693   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11694   GNode *data;
11695   char *s;
11696   int len;
11697   guint32 type;
11698   int offset;
11699   gboolean ret = TRUE;
11700   const gchar *charset = NULL;
11701
11702   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11703   if (data) {
11704     len = QT_UINT32 (data->data);
11705     type = QT_UINT32 ((guint8 *) data->data + 8);
11706     if (type == 0x00000001 && len > 16) {
11707       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11708           env_vars);
11709       if (s) {
11710         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11711         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11712         g_free (s);
11713       } else {
11714         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11715       }
11716     }
11717   } else {
11718     len = QT_UINT32 (node->data);
11719     type = QT_UINT32 ((guint8 *) node->data + 4);
11720     if ((type >> 24) == 0xa9) {
11721       gint str_len;
11722       gint lang_code;
11723
11724       /* Type starts with the (C) symbol, so the next data is a list
11725        * of (string size(16), language code(16), string) */
11726
11727       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11728       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11729
11730       /* the string + fourcc + size + 2 16bit fields,
11731        * means that there are more tags in this atom */
11732       if (len > str_len + 8 + 4) {
11733         /* TODO how to represent the same tag in different languages? */
11734         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11735             "text alternatives, reading only first one");
11736       }
11737
11738       offset = 12;
11739       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
11740       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11741
11742       if (lang_code < 0x800) {  /* MAC encoded string */
11743         charset = "mac";
11744       }
11745     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11746             QT_FOURCC ((guint8 *) node->data + 4))) {
11747       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11748
11749       /* we go for 3GP style encoding if major brands claims so,
11750        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11751       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11752           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11753               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11754         offset = 14;
11755         /* 16-bit Language code is ignored here as well */
11756         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11757       } else {
11758         goto normal;
11759       }
11760     } else {
11761     normal:
11762       offset = 8;
11763       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11764       ret = FALSE;              /* may have to fallback */
11765     }
11766     if (charset) {
11767       GError *err = NULL;
11768
11769       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11770           charset, NULL, NULL, &err);
11771       if (err) {
11772         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11773             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11774             err->message);
11775         g_error_free (err);
11776       }
11777     } else {
11778       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11779           len - offset, env_vars);
11780     }
11781     if (s) {
11782       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11783       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11784       g_free (s);
11785       ret = TRUE;
11786     } else {
11787       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11788     }
11789   }
11790   return ret;
11791 }
11792
11793 static void
11794 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11795     const char *tag, const char *dummy, GNode * node)
11796 {
11797   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11798 }
11799
11800 static void
11801 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11802     const char *tag, const char *dummy, GNode * node)
11803 {
11804   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11805   guint8 *data;
11806   char *s, *t, *k = NULL;
11807   int len;
11808   int offset;
11809   int count;
11810
11811   /* first try normal string tag if major brand not 3GP */
11812   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11813     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11814       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11815        * let's try it 3gpp way after minor safety check */
11816       data = node->data;
11817       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11818         return;
11819     } else
11820       return;
11821   }
11822
11823   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11824
11825   data = node->data;
11826
11827   len = QT_UINT32 (data);
11828   if (len < 15)
11829     goto short_read;
11830
11831   count = QT_UINT8 (data + 14);
11832   offset = 15;
11833   for (; count; count--) {
11834     gint slen;
11835
11836     if (offset + 1 > len)
11837       goto short_read;
11838     slen = QT_UINT8 (data + offset);
11839     offset += 1;
11840     if (offset + slen > len)
11841       goto short_read;
11842     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11843         slen, env_vars);
11844     if (s) {
11845       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11846       if (k) {
11847         t = g_strjoin (",", k, s, NULL);
11848         g_free (s);
11849         g_free (k);
11850         k = t;
11851       } else {
11852         k = s;
11853       }
11854     } else {
11855       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11856     }
11857     offset += slen;
11858   }
11859
11860 done:
11861   if (k) {
11862     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11863     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11864   }
11865   g_free (k);
11866
11867   return;
11868
11869   /* ERRORS */
11870 short_read:
11871   {
11872     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11873     goto done;
11874   }
11875 }
11876
11877 static void
11878 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11879     const char *tag1, const char *tag2, GNode * node)
11880 {
11881   GNode *data;
11882   int len;
11883   int type;
11884   int n1, n2;
11885
11886   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11887   if (data) {
11888     len = QT_UINT32 (data->data);
11889     type = QT_UINT32 ((guint8 *) data->data + 8);
11890     if (type == 0x00000000 && len >= 22) {
11891       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11892       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11893       if (n1 > 0) {
11894         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11895         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11896       }
11897       if (n2 > 0) {
11898         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11899         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11900       }
11901     }
11902   }
11903 }
11904
11905 static void
11906 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11907     const char *tag1, const char *dummy, GNode * node)
11908 {
11909   GNode *data;
11910   int len;
11911   int type;
11912   int n1;
11913
11914   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11915   if (data) {
11916     len = QT_UINT32 (data->data);
11917     type = QT_UINT32 ((guint8 *) data->data + 8);
11918     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11919     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11920     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11921       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11922       if (n1) {
11923         /* do not add bpm=0 */
11924         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11925         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11926             NULL);
11927       }
11928     }
11929   }
11930 }
11931
11932 static void
11933 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11934     const char *tag1, const char *dummy, GNode * node)
11935 {
11936   GNode *data;
11937   int len;
11938   int type;
11939   guint32 num;
11940
11941   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11942   if (data) {
11943     len = QT_UINT32 (data->data);
11944     type = QT_UINT32 ((guint8 *) data->data + 8);
11945     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11946     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11947     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11948       num = QT_UINT32 ((guint8 *) data->data + 16);
11949       if (num) {
11950         /* do not add num=0 */
11951         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11952         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11953       }
11954     }
11955   }
11956 }
11957
11958 static void
11959 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11960     const char *tag1, const char *dummy, GNode * node)
11961 {
11962   GNode *data;
11963   int len;
11964   int type;
11965   GstSample *sample;
11966
11967   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11968   if (data) {
11969     len = QT_UINT32 (data->data);
11970     type = QT_UINT32 ((guint8 *) data->data + 8);
11971     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11972     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11973       if ((sample =
11974               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11975                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11976         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11977         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11978         gst_sample_unref (sample);
11979       }
11980     }
11981   }
11982 }
11983
11984 static void
11985 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11986     const char *tag, const char *dummy, GNode * node)
11987 {
11988   GNode *data;
11989   char *s;
11990   int len;
11991   int type;
11992
11993   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11994   if (data) {
11995     len = QT_UINT32 (data->data);
11996     type = QT_UINT32 ((guint8 *) data->data + 8);
11997     if (type == 0x00000001 && len > 16) {
11998       guint y, m = 1, d = 1;
11999       gint ret;
12000
12001       s = g_strndup ((char *) data->data + 16, len - 16);
12002       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12003       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12004       if (ret >= 1 && y > 1500 && y < 3000) {
12005         GDate *date;
12006
12007         date = g_date_new_dmy (d, m, y);
12008         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12009         g_date_free (date);
12010       } else {
12011         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12012       }
12013       g_free (s);
12014     }
12015   }
12016 }
12017
12018 static void
12019 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12020     const char *tag, const char *dummy, GNode * node)
12021 {
12022   GNode *data;
12023
12024   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12025
12026   /* re-route to normal string tag if major brand says so
12027    * or no data atom and compatible brand suggests so */
12028   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12029       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12030     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12031     return;
12032   }
12033
12034   if (data) {
12035     guint len, type, n;
12036
12037     len = QT_UINT32 (data->data);
12038     type = QT_UINT32 ((guint8 *) data->data + 8);
12039     if (type == 0x00000000 && len >= 18) {
12040       n = QT_UINT16 ((guint8 *) data->data + 16);
12041       if (n > 0) {
12042         const gchar *genre;
12043
12044         genre = gst_tag_id3_genre_get (n - 1);
12045         if (genre != NULL) {
12046           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12047           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12048         }
12049       }
12050     }
12051   }
12052 }
12053
12054 static void
12055 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12056     const gchar * tag, guint8 * data, guint32 datasize)
12057 {
12058   gdouble value;
12059   gchar *datacopy;
12060
12061   /* make a copy to have \0 at the end */
12062   datacopy = g_strndup ((gchar *) data, datasize);
12063
12064   /* convert the str to double */
12065   if (sscanf (datacopy, "%lf", &value) == 1) {
12066     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12067     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12068   } else {
12069     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12070         datacopy);
12071   }
12072   g_free (datacopy);
12073 }
12074
12075
12076 static void
12077 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12078     const char *tag, const char *tag_bis, GNode * node)
12079 {
12080   GNode *mean;
12081   GNode *name;
12082   GNode *data;
12083   guint32 meansize;
12084   guint32 namesize;
12085   guint32 datatype;
12086   guint32 datasize;
12087   const gchar *meanstr;
12088   const gchar *namestr;
12089
12090   /* checking the whole ---- atom size for consistency */
12091   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12092     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12093     return;
12094   }
12095
12096   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12097   if (!mean) {
12098     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12099     return;
12100   }
12101
12102   meansize = QT_UINT32 (mean->data);
12103   if (meansize <= 12) {
12104     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12105     return;
12106   }
12107   meanstr = ((gchar *) mean->data) + 12;
12108   meansize -= 12;
12109
12110   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12111   if (!name) {
12112     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12113     return;
12114   }
12115
12116   namesize = QT_UINT32 (name->data);
12117   if (namesize <= 12) {
12118     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12119     return;
12120   }
12121   namestr = ((gchar *) name->data) + 12;
12122   namesize -= 12;
12123
12124   /*
12125    * Data atom is:
12126    * uint32 - size
12127    * uint32 - name
12128    * uint8  - version
12129    * uint24 - data type
12130    * uint32 - all 0
12131    * rest   - the data
12132    */
12133   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12134   if (!data) {
12135     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12136     return;
12137   }
12138   datasize = QT_UINT32 (data->data);
12139   if (datasize <= 16) {
12140     GST_WARNING_OBJECT (demux, "Data atom too small");
12141     return;
12142   }
12143   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12144
12145   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12146       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12147     static const struct
12148     {
12149       const gchar name[28];
12150       const gchar tag[28];
12151     } tags[] = {
12152       {
12153       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12154       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12155       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12156       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12157       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12158       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12159       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12160       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12161     };
12162     int i;
12163
12164     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12165       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12166         switch (gst_tag_get_type (tags[i].tag)) {
12167           case G_TYPE_DOUBLE:
12168             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12169                 ((guint8 *) data->data) + 16, datasize - 16);
12170             break;
12171           case G_TYPE_STRING:
12172             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12173             break;
12174           default:
12175             /* not reached */
12176             break;
12177         }
12178         break;
12179       }
12180     }
12181     if (i == G_N_ELEMENTS (tags))
12182       goto unknown_tag;
12183   } else {
12184     goto unknown_tag;
12185   }
12186
12187   return;
12188
12189 /* errors */
12190 unknown_tag:
12191 #ifndef GST_DISABLE_GST_DEBUG
12192   {
12193     gchar *namestr_dbg;
12194     gchar *meanstr_dbg;
12195
12196     meanstr_dbg = g_strndup (meanstr, meansize);
12197     namestr_dbg = g_strndup (namestr, namesize);
12198
12199     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12200         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12201
12202     g_free (namestr_dbg);
12203     g_free (meanstr_dbg);
12204   }
12205 #endif
12206   return;
12207 }
12208
12209 static void
12210 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12211     const char *tag_bis, GNode * node)
12212 {
12213   guint8 *data;
12214   GstBuffer *buf;
12215   guint len;
12216   GstTagList *id32_taglist = NULL;
12217
12218   GST_LOG_OBJECT (demux, "parsing ID32");
12219
12220   data = node->data;
12221   len = GST_READ_UINT32_BE (data);
12222
12223   /* need at least full box and language tag */
12224   if (len < 12 + 2)
12225     return;
12226
12227   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12228   gst_buffer_fill (buf, 0, data + 14, len - 14);
12229
12230   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12231   if (id32_taglist) {
12232     GST_LOG_OBJECT (demux, "parsing ok");
12233     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12234     gst_tag_list_unref (id32_taglist);
12235   } else {
12236     GST_LOG_OBJECT (demux, "parsing failed");
12237   }
12238
12239   gst_buffer_unref (buf);
12240 }
12241
12242 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12243     const char *tag, const char *tag_bis, GNode * node);
12244
12245 /* unmapped tags
12246 FOURCC_pcst -> if media is a podcast -> bool
12247 FOURCC_cpil -> if media is part of a compilation -> bool
12248 FOURCC_pgap -> if media is part of a gapless context -> bool
12249 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12250 */
12251
12252 static const struct
12253 {
12254   guint32 fourcc;
12255   const gchar *gst_tag;
12256   const gchar *gst_tag_bis;
12257   const GstQTDemuxAddTagFunc func;
12258 } add_funcs[] = {
12259   {
12260   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12261   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12262   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12263   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12264   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12265   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12266   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12267   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12268   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12269   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12270   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12271   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12272   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12273   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12274   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12275   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12276   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12277   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12278   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12279   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12280   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12281   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12282   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12283         qtdemux_tag_add_num}, {
12284   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12285         qtdemux_tag_add_num}, {
12286   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12287   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12288   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12289   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
12290   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12291   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12292   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12293   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12294   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12295   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12296   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12297   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12298   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12299   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12300   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12301   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12302   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12303   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12304         qtdemux_tag_add_classification}, {
12305   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12306   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12307   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12308
12309     /* This is a special case, some tags are stored in this
12310      * 'reverse dns naming', according to:
12311      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12312      * bug #614471
12313      */
12314   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12315     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12316   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12317 };
12318
12319 struct _GstQtDemuxTagList
12320 {
12321   GstQTDemux *demux;
12322   GstTagList *taglist;
12323 };
12324 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12325
12326 static void
12327 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12328 {
12329   gint len;
12330   guint8 *data;
12331   GstBuffer *buf;
12332   gchar *media_type;
12333   const gchar *style;
12334   GstSample *sample;
12335   GstStructure *s;
12336   guint i;
12337   guint8 ndata[4];
12338   GstQTDemux *demux = qtdemuxtaglist->demux;
12339   GstTagList *taglist = qtdemuxtaglist->taglist;
12340
12341   data = node->data;
12342   len = QT_UINT32 (data);
12343   buf = gst_buffer_new_and_alloc (len);
12344   gst_buffer_fill (buf, 0, data, len);
12345
12346   /* heuristic to determine style of tag */
12347   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12348       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12349     style = "itunes";
12350   else if (demux->major_brand == FOURCC_qt__)
12351     style = "quicktime";
12352   /* fall back to assuming iso/3gp tag style */
12353   else
12354     style = "iso";
12355
12356   /* santize the name for the caps. */
12357   for (i = 0; i < 4; i++) {
12358     guint8 d = data[4 + i];
12359     if (g_ascii_isalnum (d))
12360       ndata[i] = g_ascii_tolower (d);
12361     else
12362       ndata[i] = '_';
12363   }
12364
12365   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12366       ndata[0], ndata[1], ndata[2], ndata[3]);
12367   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12368
12369   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12370   sample = gst_sample_new (buf, NULL, NULL, s);
12371   gst_buffer_unref (buf);
12372   g_free (media_type);
12373
12374   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12375       len, s);
12376
12377   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12378       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12379
12380   gst_sample_unref (sample);
12381 }
12382
12383 static void
12384 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12385 {
12386   GNode *meta;
12387   GNode *ilst;
12388   GNode *xmp_;
12389   GNode *node;
12390   gint i;
12391   GstQtDemuxTagList demuxtaglist;
12392
12393   demuxtaglist.demux = qtdemux;
12394   demuxtaglist.taglist = taglist;
12395
12396   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12397   if (meta != NULL) {
12398     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12399     if (ilst == NULL) {
12400       GST_LOG_OBJECT (qtdemux, "no ilst");
12401       return;
12402     }
12403   } else {
12404     ilst = udta;
12405     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12406   }
12407
12408   i = 0;
12409   while (i < G_N_ELEMENTS (add_funcs)) {
12410     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12411     if (node) {
12412       gint len;
12413
12414       len = QT_UINT32 (node->data);
12415       if (len < 12) {
12416         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12417             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12418       } else {
12419         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12420             add_funcs[i].gst_tag_bis, node);
12421       }
12422       g_node_destroy (node);
12423     } else {
12424       i++;
12425     }
12426   }
12427
12428   /* parsed nodes have been removed, pass along remainder as blob */
12429   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12430       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12431
12432   /* parse up XMP_ node if existing */
12433   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12434   if (xmp_ != NULL) {
12435     GstBuffer *buf;
12436     GstTagList *xmptaglist;
12437
12438     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12439         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12440     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12441     gst_buffer_unref (buf);
12442
12443     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12444   } else {
12445     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12446   }
12447 }
12448
12449 typedef struct
12450 {
12451   GstStructure *structure;      /* helper for sort function */
12452   gchar *location;
12453   guint min_req_bitrate;
12454   guint min_req_qt_version;
12455 } GstQtReference;
12456
12457 static gint
12458 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12459 {
12460   GstQtReference *ref_a = (GstQtReference *) a;
12461   GstQtReference *ref_b = (GstQtReference *) b;
12462
12463   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12464     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12465
12466   /* known bitrates go before unknown; higher bitrates go first */
12467   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12468 }
12469
12470 /* sort the redirects and post a message for the application.
12471  */
12472 static void
12473 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12474 {
12475   GstQtReference *best;
12476   GstStructure *s;
12477   GstMessage *msg;
12478   GValue list_val = { 0, };
12479   GList *l;
12480
12481   g_assert (references != NULL);
12482
12483   references = g_list_sort (references, qtdemux_redirects_sort_func);
12484
12485   best = (GstQtReference *) references->data;
12486
12487   g_value_init (&list_val, GST_TYPE_LIST);
12488
12489   for (l = references; l != NULL; l = l->next) {
12490     GstQtReference *ref = (GstQtReference *) l->data;
12491     GValue struct_val = { 0, };
12492
12493     ref->structure = gst_structure_new ("redirect",
12494         "new-location", G_TYPE_STRING, ref->location, NULL);
12495
12496     if (ref->min_req_bitrate > 0) {
12497       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12498           ref->min_req_bitrate, NULL);
12499     }
12500
12501     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12502     g_value_set_boxed (&struct_val, ref->structure);
12503     gst_value_list_append_value (&list_val, &struct_val);
12504     g_value_unset (&struct_val);
12505     /* don't free anything here yet, since we need best->structure below */
12506   }
12507
12508   g_assert (best != NULL);
12509   s = gst_structure_copy (best->structure);
12510
12511   if (g_list_length (references) > 1) {
12512     gst_structure_set_value (s, "locations", &list_val);
12513   }
12514
12515   g_value_unset (&list_val);
12516
12517   for (l = references; l != NULL; l = l->next) {
12518     GstQtReference *ref = (GstQtReference *) l->data;
12519
12520     gst_structure_free (ref->structure);
12521     g_free (ref->location);
12522     g_free (ref);
12523   }
12524   g_list_free (references);
12525
12526   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12527   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12528   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12529   qtdemux->posted_redirect = TRUE;
12530 }
12531
12532 /* look for redirect nodes, collect all redirect information and
12533  * process it.
12534  */
12535 static gboolean
12536 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12537 {
12538   GNode *rmra, *rmda, *rdrf;
12539
12540   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12541   if (rmra) {
12542     GList *redirects = NULL;
12543
12544     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12545     while (rmda) {
12546       GstQtReference ref = { NULL, NULL, 0, 0 };
12547       GNode *rmdr, *rmvc;
12548
12549       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12550         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12551         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12552             ref.min_req_bitrate);
12553       }
12554
12555       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12556         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12557         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12558
12559 #ifndef GST_DISABLE_GST_DEBUG
12560         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12561 #endif
12562         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12563
12564         GST_LOG_OBJECT (qtdemux,
12565             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12566             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12567             bitmask, check_type);
12568         if (package == FOURCC_qtim && check_type == 0) {
12569           ref.min_req_qt_version = version;
12570         }
12571       }
12572
12573       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12574       if (rdrf) {
12575         guint32 ref_type;
12576         guint8 *ref_data;
12577         guint ref_len;
12578
12579         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12580         if (ref_len > 20) {
12581           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12582           ref_data = (guint8 *) rdrf->data + 20;
12583           if (ref_type == FOURCC_alis) {
12584             guint record_len, record_version, fn_len;
12585
12586             if (ref_len > 70) {
12587               /* MacOSX alias record, google for alias-layout.txt */
12588               record_len = QT_UINT16 (ref_data + 4);
12589               record_version = QT_UINT16 (ref_data + 4 + 2);
12590               fn_len = QT_UINT8 (ref_data + 50);
12591               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12592                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12593               }
12594             } else {
12595               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12596                   ref_len);
12597             }
12598           } else if (ref_type == FOURCC_url_) {
12599             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12600           } else {
12601             GST_DEBUG_OBJECT (qtdemux,
12602                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12603                 GST_FOURCC_ARGS (ref_type));
12604           }
12605           if (ref.location != NULL) {
12606             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12607             redirects =
12608                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12609           } else {
12610             GST_WARNING_OBJECT (qtdemux,
12611                 "Failed to extract redirect location from rdrf atom");
12612           }
12613         } else {
12614           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12615         }
12616       }
12617
12618       /* look for others */
12619       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12620     }
12621
12622     if (redirects != NULL) {
12623       qtdemux_process_redirects (qtdemux, redirects);
12624     }
12625   }
12626   return TRUE;
12627 }
12628
12629 static GstTagList *
12630 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12631 {
12632   const gchar *fmt;
12633
12634   if (tags == NULL) {
12635     tags = gst_tag_list_new_empty ();
12636     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12637   }
12638
12639   if (qtdemux->major_brand == FOURCC_mjp2)
12640     fmt = "Motion JPEG 2000";
12641   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12642     fmt = "3GP";
12643   else if (qtdemux->major_brand == FOURCC_qt__)
12644     fmt = "Quicktime";
12645   else if (qtdemux->fragmented)
12646     fmt = "ISO fMP4";
12647   else
12648     fmt = "ISO MP4/M4A";
12649
12650   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12651       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12652
12653   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12654       fmt, NULL);
12655
12656   return tags;
12657 }
12658
12659 /* we have read the complete moov node now.
12660  * This function parses all of the relevant info, creates the traks and
12661  * prepares all data structures for playback
12662  */
12663 static gboolean
12664 qtdemux_parse_tree (GstQTDemux * qtdemux)
12665 {
12666   GNode *mvhd;
12667   GNode *trak;
12668   GNode *udta;
12669   GNode *mvex;
12670   GstClockTime duration;
12671   GNode *pssh;
12672   guint64 creation_time;
12673   GstDateTime *datetime = NULL;
12674   gint version;
12675
12676   /* make sure we have a usable taglist */
12677   if (!qtdemux->tag_list) {
12678     qtdemux->tag_list = gst_tag_list_new_empty ();
12679     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12680   } else {
12681     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12682   }
12683
12684   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12685   if (mvhd == NULL) {
12686     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12687     return qtdemux_parse_redirects (qtdemux);
12688   }
12689
12690   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12691   if (version == 1) {
12692     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12693     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12694     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12695   } else if (version == 0) {
12696     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12697     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12698     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12699   } else {
12700     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12701     return FALSE;
12702   }
12703
12704   /* Moving qt creation time (secs since 1904) to unix time */
12705   if (creation_time != 0) {
12706     /* Try to use epoch first as it should be faster and more commonly found */
12707     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12708       GTimeVal now;
12709
12710       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12711       /* some data cleansing sanity */
12712       g_get_current_time (&now);
12713       if (now.tv_sec + 24 * 3600 < creation_time) {
12714         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12715       } else {
12716         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12717       }
12718     } else {
12719       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12720       GDateTime *dt, *dt_local;
12721
12722       dt = g_date_time_add_seconds (base_dt, creation_time);
12723       dt_local = g_date_time_to_local (dt);
12724       datetime = gst_date_time_new_from_g_date_time (dt_local);
12725
12726       g_date_time_unref (base_dt);
12727       g_date_time_unref (dt);
12728     }
12729   }
12730   if (datetime) {
12731     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12732     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12733         datetime, NULL);
12734     gst_date_time_unref (datetime);
12735   }
12736
12737   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12738   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12739
12740   /* check for fragmented file and get some (default) data */
12741   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12742   if (mvex) {
12743     GNode *mehd;
12744     GstByteReader mehd_data;
12745
12746     /* let track parsing or anyone know weird stuff might happen ... */
12747     qtdemux->fragmented = TRUE;
12748
12749     /* compensate for total duration */
12750     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12751     if (mehd)
12752       qtdemux_parse_mehd (qtdemux, &mehd_data);
12753   }
12754
12755   /* set duration in the segment info */
12756   gst_qtdemux_get_duration (qtdemux, &duration);
12757   if (duration) {
12758     qtdemux->segment.duration = duration;
12759     /* also do not exceed duration; stop is set that way post seek anyway,
12760      * and segment activation falls back to duration,
12761      * whereas loop only checks stop, so let's align this here as well */
12762     qtdemux->segment.stop = duration;
12763   }
12764
12765   /* parse all traks */
12766   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12767   while (trak) {
12768     qtdemux_parse_trak (qtdemux, trak);
12769     /* iterate all siblings */
12770     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12771   }
12772
12773   if (!qtdemux->tag_list) {
12774     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12775     qtdemux->tag_list = gst_tag_list_new_empty ();
12776     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12777   } else {
12778     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12779   }
12780
12781   /* find tags */
12782   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12783   if (udta) {
12784     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12785   } else {
12786     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12787   }
12788
12789   /* maybe also some tags in meta box */
12790   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12791   if (udta) {
12792     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12793     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12794   } else {
12795     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12796   }
12797
12798   /* parse any protection system info */
12799   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12800   while (pssh) {
12801     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12802     qtdemux_parse_pssh (qtdemux, pssh);
12803     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12804   }
12805
12806   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12807
12808   return TRUE;
12809 }
12810
12811 /* taken from ffmpeg */
12812 static int
12813 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12814 {
12815   int count = 4;
12816   int len = 0;
12817
12818   while (count--) {
12819     int c;
12820
12821     if (ptr >= end)
12822       return -1;
12823
12824     c = *ptr++;
12825     len = (len << 7) | (c & 0x7f);
12826     if (!(c & 0x80))
12827       break;
12828   }
12829   *end_out = ptr;
12830   return len;
12831 }
12832
12833 /* this can change the codec originally present in @list */
12834 static void
12835 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12836     GNode * esds, GstTagList * list)
12837 {
12838   int len = QT_UINT32 (esds->data);
12839   guint8 *ptr = esds->data;
12840   guint8 *end = ptr + len;
12841   int tag;
12842   guint8 *data_ptr = NULL;
12843   int data_len = 0;
12844   guint8 object_type_id = 0;
12845   const char *codec_name = NULL;
12846   GstCaps *caps = NULL;
12847
12848   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12849   ptr += 8;
12850   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12851   ptr += 4;
12852   while (ptr + 1 < end) {
12853     tag = QT_UINT8 (ptr);
12854     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12855     ptr++;
12856     len = read_descr_size (ptr, end, &ptr);
12857     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12858
12859     /* Check the stated amount of data is available for reading */
12860     if (len < 0 || ptr + len > end)
12861       break;
12862
12863     switch (tag) {
12864       case ES_DESCRIPTOR_TAG:
12865         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12866         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12867         ptr += 3;
12868         break;
12869       case DECODER_CONFIG_DESC_TAG:{
12870         guint max_bitrate, avg_bitrate;
12871
12872         object_type_id = QT_UINT8 (ptr);
12873         max_bitrate = QT_UINT32 (ptr + 5);
12874         avg_bitrate = QT_UINT32 (ptr + 9);
12875         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12876         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12877         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12878         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12879         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12880         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12881           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12882               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12883         }
12884         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12885           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12886               avg_bitrate, NULL);
12887         }
12888         ptr += 13;
12889         break;
12890       }
12891       case DECODER_SPECIFIC_INFO_TAG:
12892         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12893         if (object_type_id == 0xe0 && len == 0x40) {
12894           guint8 *data;
12895           GstStructure *s;
12896           guint32 clut[16];
12897           gint i;
12898
12899           GST_DEBUG_OBJECT (qtdemux,
12900               "Have VOBSUB palette. Creating palette event");
12901           /* move to decConfigDescr data and read palette */
12902           data = ptr;
12903           for (i = 0; i < 16; i++) {
12904             clut[i] = QT_UINT32 (data);
12905             data += 4;
12906           }
12907
12908           s = gst_structure_new ("application/x-gst-dvd", "event",
12909               G_TYPE_STRING, "dvd-spu-clut-change",
12910               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12911               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12912               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12913               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12914               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12915               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12916               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12917               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12918               NULL);
12919
12920           /* store event and trigger custom processing */
12921           stream->pending_event =
12922               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12923         } else {
12924           /* Generic codec_data handler puts it on the caps */
12925           data_ptr = ptr;
12926           data_len = len;
12927         }
12928
12929         ptr += len;
12930         break;
12931       case SL_CONFIG_DESC_TAG:
12932         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12933         ptr += 1;
12934         break;
12935       default:
12936         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12937             tag);
12938         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12939         ptr += len;
12940         break;
12941     }
12942   }
12943
12944   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12945    * in use, and should also be used to override some other parameters for some
12946    * codecs. */
12947   switch (object_type_id) {
12948     case 0x20:                 /* MPEG-4 */
12949       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12950        * profile_and_level_indication */
12951       if (data_ptr != NULL && data_len >= 5 &&
12952           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12953         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12954             data_ptr + 4, data_len - 4);
12955       }
12956       break;                    /* Nothing special needed here */
12957     case 0x21:                 /* H.264 */
12958       codec_name = "H.264 / AVC";
12959       caps = gst_caps_new_simple ("video/x-h264",
12960           "stream-format", G_TYPE_STRING, "avc",
12961           "alignment", G_TYPE_STRING, "au", NULL);
12962       break;
12963     case 0x40:                 /* AAC (any) */
12964     case 0x66:                 /* AAC Main */
12965     case 0x67:                 /* AAC LC */
12966     case 0x68:                 /* AAC SSR */
12967       /* Override channels and rate based on the codec_data, as it's often
12968        * wrong. */
12969       /* Only do so for basic setup without HE-AAC extension */
12970       if (data_ptr && data_len == 2) {
12971         guint channels, rate;
12972
12973         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
12974         if (channels > 0)
12975           stream->n_channels = channels;
12976
12977         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
12978         if (rate > 0)
12979           stream->rate = rate;
12980       }
12981
12982       /* Set level and profile if possible */
12983       if (data_ptr != NULL && data_len >= 2) {
12984         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12985             data_ptr, data_len);
12986       } else {
12987         const gchar *profile_str = NULL;
12988         GstBuffer *buffer;
12989         GstMapInfo map;
12990         guint8 *codec_data;
12991         gint rate_idx, profile;
12992
12993         /* No codec_data, let's invent something.
12994          * FIXME: This is wrong for SBR! */
12995
12996         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
12997
12998         buffer = gst_buffer_new_and_alloc (2);
12999         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13000         codec_data = map.data;
13001
13002         rate_idx =
13003             gst_codec_utils_aac_get_index_from_sample_rate (stream->rate);
13004
13005         switch (object_type_id) {
13006           case 0x66:
13007             profile_str = "main";
13008             profile = 0;
13009             break;
13010           case 0x67:
13011             profile_str = "lc";
13012             profile = 1;
13013             break;
13014           case 0x68:
13015             profile_str = "ssr";
13016             profile = 2;
13017             break;
13018           default:
13019             profile = 3;
13020             break;
13021         }
13022
13023         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13024         codec_data[1] = ((rate_idx & 0x1) << 7) | (stream->n_channels << 3);
13025
13026         gst_buffer_unmap (buffer, &map);
13027         gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
13028             buffer, NULL);
13029         gst_buffer_unref (buffer);
13030
13031         if (profile_str) {
13032           gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
13033               profile_str, NULL);
13034         }
13035       }
13036       break;
13037     case 0x60:                 /* MPEG-2, various profiles */
13038     case 0x61:
13039     case 0x62:
13040     case 0x63:
13041     case 0x64:
13042     case 0x65:
13043       codec_name = "MPEG-2 video";
13044       caps = gst_caps_new_simple ("video/mpeg",
13045           "mpegversion", G_TYPE_INT, 2,
13046           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13047       break;
13048     case 0x69:                 /* MPEG-2 BC audio */
13049     case 0x6B:                 /* MPEG-1 audio */
13050       caps = gst_caps_new_simple ("audio/mpeg",
13051           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13052       codec_name = "MPEG-1 audio";
13053       break;
13054     case 0x6A:                 /* MPEG-1 */
13055       codec_name = "MPEG-1 video";
13056       caps = gst_caps_new_simple ("video/mpeg",
13057           "mpegversion", G_TYPE_INT, 1,
13058           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13059       break;
13060     case 0x6C:                 /* MJPEG */
13061       caps =
13062           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13063           NULL);
13064       codec_name = "Motion-JPEG";
13065       break;
13066     case 0x6D:                 /* PNG */
13067       caps =
13068           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13069           NULL);
13070       codec_name = "PNG still images";
13071       break;
13072     case 0x6E:                 /* JPEG2000 */
13073       codec_name = "JPEG-2000";
13074       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13075       break;
13076     case 0xA4:                 /* Dirac */
13077       codec_name = "Dirac";
13078       caps = gst_caps_new_empty_simple ("video/x-dirac");
13079       break;
13080     case 0xA5:                 /* AC3 */
13081       codec_name = "AC-3 audio";
13082       caps = gst_caps_new_simple ("audio/x-ac3",
13083           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13084       break;
13085     case 0xA9:                 /* AC3 */
13086       codec_name = "DTS audio";
13087       caps = gst_caps_new_simple ("audio/x-dts",
13088           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13089       break;
13090     case 0xE1:                 /* QCELP */
13091       /* QCELP, the codec_data is a riff tag (little endian) with
13092        * 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). */
13093       caps = gst_caps_new_empty_simple ("audio/qcelp");
13094       codec_name = "QCELP";
13095       break;
13096     default:
13097       break;
13098   }
13099
13100   /* If we have a replacement caps, then change our caps for this stream */
13101   if (caps) {
13102     gst_caps_unref (stream->caps);
13103     stream->caps = caps;
13104   }
13105
13106   if (codec_name && list)
13107     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13108         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13109
13110   /* Add the codec_data attribute to caps, if we have it */
13111   if (data_ptr) {
13112     GstBuffer *buffer;
13113
13114     buffer = gst_buffer_new_and_alloc (data_len);
13115     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13116
13117     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13118     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13119
13120     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
13121         buffer, NULL);
13122     gst_buffer_unref (buffer);
13123   }
13124
13125 }
13126
13127 #define _codec(name) \
13128   do { \
13129     if (codec_name) { \
13130       *codec_name = g_strdup (name); \
13131     } \
13132   } while (0)
13133
13134 static GstCaps *
13135 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13136     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13137 {
13138   GstCaps *caps = NULL;
13139   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13140
13141   switch (fourcc) {
13142     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
13143       _codec ("PNG still images");
13144       caps = gst_caps_new_empty_simple ("image/png");
13145       break;
13146     case FOURCC_jpeg:
13147       _codec ("JPEG still images");
13148       caps =
13149           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13150           NULL);
13151       break;
13152     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13153     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13154     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13155     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13156       _codec ("Motion-JPEG");
13157       caps =
13158           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13159           NULL);
13160       break;
13161     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13162       _codec ("Motion-JPEG format B");
13163       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13164       break;
13165     case FOURCC_mjp2:
13166       _codec ("JPEG-2000");
13167       /* override to what it should be according to spec, avoid palette_data */
13168       stream->bits_per_sample = 24;
13169       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13170       break;
13171     case FOURCC_SVQ3:
13172       _codec ("Sorensen video v.3");
13173       caps = gst_caps_new_simple ("video/x-svq",
13174           "svqversion", G_TYPE_INT, 3, NULL);
13175       break;
13176     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13177     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13178       _codec ("Sorensen video v.1");
13179       caps = gst_caps_new_simple ("video/x-svq",
13180           "svqversion", G_TYPE_INT, 1, NULL);
13181       break;
13182     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13183       caps = gst_caps_new_empty_simple ("video/x-raw");
13184       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13185       _codec ("Windows Raw RGB");
13186       stream->alignment = 32;
13187       break;
13188     case FOURCC_raw_:
13189     {
13190       guint16 bps;
13191
13192       bps = QT_UINT16 (stsd_data + 98);
13193       switch (bps) {
13194         case 15:
13195           format = GST_VIDEO_FORMAT_RGB15;
13196           break;
13197         case 16:
13198           format = GST_VIDEO_FORMAT_RGB16;
13199           break;
13200         case 24:
13201           format = GST_VIDEO_FORMAT_RGB;
13202           break;
13203         case 32:
13204           format = GST_VIDEO_FORMAT_ARGB;
13205           break;
13206         default:
13207           /* unknown */
13208           break;
13209       }
13210       break;
13211     }
13212     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13213       format = GST_VIDEO_FORMAT_I420;
13214       break;
13215     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13216     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13217       format = GST_VIDEO_FORMAT_I420;
13218       break;
13219     case FOURCC_2vuy:
13220     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13221       format = GST_VIDEO_FORMAT_UYVY;
13222       break;
13223     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13224       format = GST_VIDEO_FORMAT_v308;
13225       break;
13226     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13227       format = GST_VIDEO_FORMAT_v216;
13228       break;
13229     case FOURCC_v210:
13230       format = GST_VIDEO_FORMAT_v210;
13231       break;
13232     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13233       format = GST_VIDEO_FORMAT_r210;
13234       break;
13235       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13236          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13237          format = GST_VIDEO_FORMAT_v410;
13238          break;
13239        */
13240       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13241        * but different order than AYUV
13242        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13243        format = GST_VIDEO_FORMAT_v408;
13244        break;
13245        */
13246     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13247     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13248       _codec ("MPEG-1 video");
13249       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13250           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13251       break;
13252     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13253     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13254     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13255     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13256     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13257     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13258     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13259     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13260     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13261     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13262     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13263     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13264     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13265     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13266     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13267     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13268     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13269     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13270     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13271     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13272     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13273     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13274     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13275     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13276     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13277     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13278     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13279     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13280     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13281     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13282     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13283     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13284     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13285     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13286     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13287     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13288     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13289     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13290     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13291     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13292     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13293     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13294     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13295     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13296     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13297     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13298       _codec ("MPEG-2 video");
13299       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13300           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13301       break;
13302     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13303       _codec ("GIF still images");
13304       caps = gst_caps_new_empty_simple ("image/gif");
13305       break;
13306     case FOURCC_h263:
13307     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13308     case FOURCC_s263:
13309     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13310       _codec ("H.263");
13311       /* ffmpeg uses the height/width props, don't know why */
13312       caps = gst_caps_new_simple ("video/x-h263",
13313           "variant", G_TYPE_STRING, "itu", NULL);
13314       break;
13315     case FOURCC_mp4v:
13316     case FOURCC_MP4V:
13317       _codec ("MPEG-4 video");
13318       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13319           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13320       break;
13321     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13322     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13323       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13324       caps = gst_caps_new_simple ("video/x-msmpeg",
13325           "msmpegversion", G_TYPE_INT, 43, NULL);
13326       break;
13327     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13328       _codec ("DivX 3");
13329       caps = gst_caps_new_simple ("video/x-divx",
13330           "divxversion", G_TYPE_INT, 3, NULL);
13331       break;
13332     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13333     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13334       _codec ("DivX 4");
13335       caps = gst_caps_new_simple ("video/x-divx",
13336           "divxversion", G_TYPE_INT, 4, NULL);
13337       break;
13338     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13339       _codec ("DivX 5");
13340       caps = gst_caps_new_simple ("video/x-divx",
13341           "divxversion", G_TYPE_INT, 5, NULL);
13342       break;
13343
13344     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13345       _codec ("FFV1");
13346       caps = gst_caps_new_simple ("video/x-ffv",
13347           "ffvversion", G_TYPE_INT, 1, NULL);
13348       break;
13349
13350     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13351     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13352     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
13353     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
13354     case FOURCC_FMP4:
13355     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13356       caps = gst_caps_new_simple ("video/mpeg",
13357           "mpegversion", G_TYPE_INT, 4, NULL);
13358       _codec ("MPEG-4");
13359       break;
13360
13361     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13362       _codec ("Cinepak");
13363       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13364       break;
13365     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13366       _codec ("Apple QuickDraw");
13367       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13368       break;
13369     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13370       _codec ("Apple video");
13371       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13372       break;
13373     case FOURCC_H264:
13374     case FOURCC_avc1:
13375       _codec ("H.264 / AVC");
13376       caps = gst_caps_new_simple ("video/x-h264",
13377           "stream-format", G_TYPE_STRING, "avc",
13378           "alignment", G_TYPE_STRING, "au", NULL);
13379       break;
13380     case FOURCC_avc3:
13381       _codec ("H.264 / AVC");
13382       caps = gst_caps_new_simple ("video/x-h264",
13383           "stream-format", G_TYPE_STRING, "avc3",
13384           "alignment", G_TYPE_STRING, "au", NULL);
13385       break;
13386     case FOURCC_H265:
13387     case FOURCC_hvc1:
13388       _codec ("H.265 / HEVC");
13389       caps = gst_caps_new_simple ("video/x-h265",
13390           "stream-format", G_TYPE_STRING, "hvc1",
13391           "alignment", G_TYPE_STRING, "au", NULL);
13392       break;
13393     case FOURCC_hev1:
13394       _codec ("H.265 / HEVC");
13395       caps = gst_caps_new_simple ("video/x-h265",
13396           "stream-format", G_TYPE_STRING, "hev1",
13397           "alignment", G_TYPE_STRING, "au", NULL);
13398       break;
13399     case FOURCC_rle_:
13400       _codec ("Run-length encoding");
13401       caps = gst_caps_new_simple ("video/x-rle",
13402           "layout", G_TYPE_STRING, "quicktime", NULL);
13403       break;
13404     case FOURCC_WRLE:
13405       _codec ("Run-length encoding");
13406       caps = gst_caps_new_simple ("video/x-rle",
13407           "layout", G_TYPE_STRING, "microsoft", NULL);
13408       break;
13409     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13410     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13411       _codec ("Indeo Video 3");
13412       caps = gst_caps_new_simple ("video/x-indeo",
13413           "indeoversion", G_TYPE_INT, 3, NULL);
13414       break;
13415     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13416     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13417       _codec ("Intel Video 4");
13418       caps = gst_caps_new_simple ("video/x-indeo",
13419           "indeoversion", G_TYPE_INT, 4, NULL);
13420       break;
13421     case FOURCC_dvcp:
13422     case FOURCC_dvc_:
13423     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13424     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13425     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13426     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13427     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13428     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13429       _codec ("DV Video");
13430       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13431           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13432       break;
13433     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13434     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13435       _codec ("DVCPro50 Video");
13436       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13437           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13438       break;
13439     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13440     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13441       _codec ("DVCProHD Video");
13442       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13443           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13444       break;
13445     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13446       _codec ("Apple Graphics (SMC)");
13447       caps = gst_caps_new_empty_simple ("video/x-smc");
13448       break;
13449     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13450       _codec ("VP3");
13451       caps = gst_caps_new_empty_simple ("video/x-vp3");
13452       break;
13453     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13454       _codec ("VP6 Flash");
13455       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13456       break;
13457     case FOURCC_XiTh:
13458       _codec ("Theora");
13459       caps = gst_caps_new_empty_simple ("video/x-theora");
13460       /* theora uses one byte of padding in the data stream because it does not
13461        * allow 0 sized packets while theora does */
13462       stream->padding = 1;
13463       break;
13464     case FOURCC_drac:
13465       _codec ("Dirac");
13466       caps = gst_caps_new_empty_simple ("video/x-dirac");
13467       break;
13468     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13469       _codec ("TIFF still images");
13470       caps = gst_caps_new_empty_simple ("image/tiff");
13471       break;
13472     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13473       _codec ("Apple Intermediate Codec");
13474       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13475       break;
13476     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13477       _codec ("AVID DNxHD");
13478       caps = gst_caps_from_string ("video/x-dnxhd");
13479       break;
13480     case FOURCC_VP80:
13481       _codec ("On2 VP8");
13482       caps = gst_caps_from_string ("video/x-vp8");
13483       break;
13484     case FOURCC_apcs:
13485       _codec ("Apple ProRes LT");
13486       caps =
13487           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13488           NULL);
13489       break;
13490     case FOURCC_apch:
13491       _codec ("Apple ProRes HQ");
13492       caps =
13493           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13494           NULL);
13495       break;
13496     case FOURCC_apcn:
13497       _codec ("Apple ProRes");
13498       caps =
13499           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13500           "standard", NULL);
13501       break;
13502     case FOURCC_apco:
13503       _codec ("Apple ProRes Proxy");
13504       caps =
13505           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13506           "proxy", NULL);
13507       break;
13508     case FOURCC_ap4h:
13509       _codec ("Apple ProRes 4444");
13510       caps =
13511           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13512           "4444", NULL);
13513       break;
13514     case FOURCC_ap4x:
13515       _codec ("Apple ProRes 4444 XQ");
13516       caps =
13517           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13518           "4444xq", NULL);
13519       break;
13520     case FOURCC_vc_1:
13521     case FOURCC_ovc1:
13522       _codec ("VC-1");
13523       caps = gst_caps_new_simple ("video/x-wmv",
13524           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13525       break;
13526     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13527     default:
13528     {
13529       char *s, fourstr[5];
13530
13531       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13532       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
13533       caps = gst_caps_new_empty_simple (s);
13534       g_free (s);
13535       break;
13536     }
13537   }
13538
13539   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13540     GstVideoInfo info;
13541
13542     gst_video_info_init (&info);
13543     gst_video_info_set_format (&info, format, stream->width, stream->height);
13544
13545     caps = gst_video_info_to_caps (&info);
13546     *codec_name = gst_pb_utils_get_codec_description (caps);
13547
13548     /* enable clipping for raw video streams */
13549     stream->need_clip = TRUE;
13550     stream->alignment = 32;
13551   }
13552
13553   return caps;
13554 }
13555
13556 static guint
13557 round_up_pow2 (guint n)
13558 {
13559   n = n - 1;
13560   n = n | (n >> 1);
13561   n = n | (n >> 2);
13562   n = n | (n >> 4);
13563   n = n | (n >> 8);
13564   n = n | (n >> 16);
13565   return n + 1;
13566 }
13567
13568 static GstCaps *
13569 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13570     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13571 {
13572   GstCaps *caps;
13573   const GstStructure *s;
13574   const gchar *name;
13575   gint endian = 0;
13576   GstAudioFormat format = 0;
13577   gint depth;
13578
13579   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13580
13581   depth = stream->bytes_per_packet * 8;
13582
13583   switch (fourcc) {
13584     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13585     case FOURCC_raw_:
13586       /* 8-bit audio is unsigned */
13587       if (depth == 8)
13588         format = GST_AUDIO_FORMAT_U8;
13589       /* otherwise it's signed and big-endian just like 'twos' */
13590     case FOURCC_twos:
13591       endian = G_BIG_ENDIAN;
13592       /* fall-through */
13593     case FOURCC_sowt:
13594     {
13595       gchar *str;
13596
13597       if (!endian)
13598         endian = G_LITTLE_ENDIAN;
13599
13600       if (!format)
13601         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13602
13603       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13604       _codec (str);
13605       g_free (str);
13606
13607       caps = gst_caps_new_simple ("audio/x-raw",
13608           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13609           "layout", G_TYPE_STRING, "interleaved", NULL);
13610       stream->alignment = GST_ROUND_UP_8 (depth);
13611       stream->alignment = round_up_pow2 (stream->alignment);
13612       break;
13613     }
13614     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13615       _codec ("Raw 64-bit floating-point audio");
13616       caps = gst_caps_new_simple ("audio/x-raw",
13617           "format", G_TYPE_STRING, "F64BE",
13618           "layout", G_TYPE_STRING, "interleaved", NULL);
13619       stream->alignment = 8;
13620       break;
13621     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13622       _codec ("Raw 32-bit floating-point audio");
13623       caps = gst_caps_new_simple ("audio/x-raw",
13624           "format", G_TYPE_STRING, "F32BE",
13625           "layout", G_TYPE_STRING, "interleaved", NULL);
13626       stream->alignment = 4;
13627       break;
13628     case FOURCC_in24:
13629       _codec ("Raw 24-bit PCM audio");
13630       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13631        * endian later */
13632       caps = gst_caps_new_simple ("audio/x-raw",
13633           "format", G_TYPE_STRING, "S24BE",
13634           "layout", G_TYPE_STRING, "interleaved", NULL);
13635       stream->alignment = 4;
13636       break;
13637     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13638       _codec ("Raw 32-bit PCM audio");
13639       caps = gst_caps_new_simple ("audio/x-raw",
13640           "format", G_TYPE_STRING, "S32BE",
13641           "layout", G_TYPE_STRING, "interleaved", NULL);
13642       stream->alignment = 4;
13643       break;
13644     case FOURCC_ulaw:
13645       _codec ("Mu-law audio");
13646       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13647       break;
13648     case FOURCC_alaw:
13649       _codec ("A-law audio");
13650       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13651       break;
13652     case 0x0200736d:
13653     case 0x6d730002:
13654       _codec ("Microsoft ADPCM");
13655       /* Microsoft ADPCM-ACM code 2 */
13656       caps = gst_caps_new_simple ("audio/x-adpcm",
13657           "layout", G_TYPE_STRING, "microsoft", NULL);
13658       break;
13659     case 0x1100736d:
13660     case 0x6d730011:
13661       _codec ("DVI/IMA ADPCM");
13662       caps = gst_caps_new_simple ("audio/x-adpcm",
13663           "layout", G_TYPE_STRING, "dvi", NULL);
13664       break;
13665     case 0x1700736d:
13666     case 0x6d730017:
13667       _codec ("DVI/Intel IMA ADPCM");
13668       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13669       caps = gst_caps_new_simple ("audio/x-adpcm",
13670           "layout", G_TYPE_STRING, "quicktime", NULL);
13671       break;
13672     case 0x5500736d:
13673     case 0x6d730055:
13674       /* MPEG layer 3, CBR only (pre QT4.1) */
13675     case FOURCC__mp3:
13676       _codec ("MPEG-1 layer 3");
13677       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13678       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13679           "mpegversion", G_TYPE_INT, 1, NULL);
13680       break;
13681     case 0x20736d:
13682     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13683       _codec ("EAC-3 audio");
13684       caps = gst_caps_new_simple ("audio/x-eac3",
13685           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13686       stream->sampled = TRUE;
13687       break;
13688     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13689     case FOURCC_ac_3:
13690       _codec ("AC-3 audio");
13691       caps = gst_caps_new_simple ("audio/x-ac3",
13692           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13693       stream->sampled = TRUE;
13694       break;
13695     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13696     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13697       _codec ("DTS audio");
13698       caps = gst_caps_new_simple ("audio/x-dts",
13699           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13700       stream->sampled = TRUE;
13701       break;
13702     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13703     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13704       _codec ("DTS-HD audio");
13705       caps = gst_caps_new_simple ("audio/x-dts",
13706           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13707       stream->sampled = TRUE;
13708       break;
13709     case FOURCC_MAC3:
13710       _codec ("MACE-3");
13711       caps = gst_caps_new_simple ("audio/x-mace",
13712           "maceversion", G_TYPE_INT, 3, NULL);
13713       break;
13714     case FOURCC_MAC6:
13715       _codec ("MACE-6");
13716       caps = gst_caps_new_simple ("audio/x-mace",
13717           "maceversion", G_TYPE_INT, 6, NULL);
13718       break;
13719     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13720       /* ogg/vorbis */
13721       caps = gst_caps_new_empty_simple ("application/ogg");
13722       break;
13723     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13724       _codec ("DV audio");
13725       caps = gst_caps_new_empty_simple ("audio/x-dv");
13726       break;
13727     case FOURCC_mp4a:
13728       _codec ("MPEG-4 AAC audio");
13729       caps = gst_caps_new_simple ("audio/mpeg",
13730           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13731           "stream-format", G_TYPE_STRING, "raw", NULL);
13732       break;
13733     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13734       _codec ("QDesign Music");
13735       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13736       break;
13737     case FOURCC_QDM2:
13738       _codec ("QDesign Music v.2");
13739       /* FIXME: QDesign music version 2 (no constant) */
13740       if (FALSE && data) {
13741         caps = gst_caps_new_simple ("audio/x-qdm2",
13742             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13743             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13744             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13745       } else {
13746         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13747       }
13748       break;
13749     case FOURCC_agsm:
13750       _codec ("GSM audio");
13751       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13752       break;
13753     case FOURCC_samr:
13754       _codec ("AMR audio");
13755       caps = gst_caps_new_empty_simple ("audio/AMR");
13756       break;
13757     case FOURCC_sawb:
13758       _codec ("AMR-WB audio");
13759       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13760       break;
13761     case FOURCC_ima4:
13762       _codec ("Quicktime IMA ADPCM");
13763       caps = gst_caps_new_simple ("audio/x-adpcm",
13764           "layout", G_TYPE_STRING, "quicktime", NULL);
13765       break;
13766     case FOURCC_alac:
13767       _codec ("Apple lossless audio");
13768       caps = gst_caps_new_empty_simple ("audio/x-alac");
13769       break;
13770     case FOURCC_fLaC:
13771       _codec ("Free Lossless Audio Codec");
13772       caps = gst_caps_new_simple ("audio/x-flac",
13773           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13774       break;
13775     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13776       _codec ("QualComm PureVoice");
13777       caps = gst_caps_from_string ("audio/qcelp");
13778       break;
13779     case FOURCC_wma_:
13780     case FOURCC_owma:
13781       _codec ("WMA");
13782       caps = gst_caps_new_empty_simple ("audio/x-wma");
13783       break;
13784     case FOURCC_opus:
13785       _codec ("Opus");
13786       caps = gst_caps_new_empty_simple ("audio/x-opus");
13787       break;
13788     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13789     {
13790       guint32 flags = 0;
13791       guint32 depth = 0;
13792       guint32 width = 0;
13793       GstAudioFormat format;
13794       enum
13795       {
13796         FLAG_IS_FLOAT = 0x1,
13797         FLAG_IS_BIG_ENDIAN = 0x2,
13798         FLAG_IS_SIGNED = 0x4,
13799         FLAG_IS_PACKED = 0x8,
13800         FLAG_IS_ALIGNED_HIGH = 0x10,
13801         FLAG_IS_NON_INTERLEAVED = 0x20
13802       };
13803       _codec ("Raw LPCM audio");
13804
13805       if (data && len >= 56) {
13806         depth = QT_UINT32 (data + 40);
13807         flags = QT_UINT32 (data + 44);
13808         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13809       }
13810       if ((flags & FLAG_IS_FLOAT) == 0) {
13811         if (depth == 0)
13812           depth = 16;
13813         if (width == 0)
13814           width = 16;
13815         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13816             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13817             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13818         caps = gst_caps_new_simple ("audio/x-raw",
13819             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13820             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13821             "non-interleaved" : "interleaved", NULL);
13822         stream->alignment = GST_ROUND_UP_8 (depth);
13823         stream->alignment = round_up_pow2 (stream->alignment);
13824       } else {
13825         if (width == 0)
13826           width = 32;
13827         if (width == 64) {
13828           if (flags & FLAG_IS_BIG_ENDIAN)
13829             format = GST_AUDIO_FORMAT_F64BE;
13830           else
13831             format = GST_AUDIO_FORMAT_F64LE;
13832         } else {
13833           if (flags & FLAG_IS_BIG_ENDIAN)
13834             format = GST_AUDIO_FORMAT_F32BE;
13835           else
13836             format = GST_AUDIO_FORMAT_F32LE;
13837         }
13838         caps = gst_caps_new_simple ("audio/x-raw",
13839             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13840             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13841             "non-interleaved" : "interleaved", NULL);
13842         stream->alignment = width / 8;
13843       }
13844       break;
13845     }
13846     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
13847       /* ? */
13848     default:
13849     {
13850       char *s, fourstr[5];
13851
13852       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13853       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
13854       caps = gst_caps_new_empty_simple (s);
13855       g_free (s);
13856       break;
13857     }
13858   }
13859
13860   if (caps) {
13861     GstCaps *templ_caps =
13862         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
13863     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
13864     gst_caps_unref (caps);
13865     gst_caps_unref (templ_caps);
13866     caps = intersection;
13867   }
13868
13869   /* enable clipping for raw audio streams */
13870   s = gst_caps_get_structure (caps, 0);
13871   name = gst_structure_get_name (s);
13872   if (g_str_has_prefix (name, "audio/x-raw")) {
13873     stream->need_clip = TRUE;
13874     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
13875     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
13876   }
13877   return caps;
13878 }
13879
13880 static GstCaps *
13881 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13882     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13883 {
13884   GstCaps *caps;
13885
13886   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13887
13888   switch (fourcc) {
13889     case FOURCC_mp4s:
13890       _codec ("DVD subtitle");
13891       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
13892       stream->need_process = TRUE;
13893       break;
13894     case FOURCC_text:
13895       _codec ("Quicktime timed text");
13896       goto text;
13897     case FOURCC_tx3g:
13898       _codec ("3GPP timed text");
13899     text:
13900       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
13901           "utf8", NULL);
13902       /* actual text piece needs to be extracted */
13903       stream->need_process = TRUE;
13904       break;
13905     case FOURCC_stpp:
13906       _codec ("XML subtitles");
13907       caps = gst_caps_new_empty_simple ("application/ttml+xml");
13908       break;
13909     default:
13910     {
13911       char *s, fourstr[5];
13912
13913       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13914       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
13915       caps = gst_caps_new_empty_simple (s);
13916       g_free (s);
13917       break;
13918     }
13919   }
13920   return caps;
13921 }
13922
13923 static GstCaps *
13924 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13925     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13926 {
13927   GstCaps *caps;
13928
13929   switch (fourcc) {
13930     case FOURCC_m1v:
13931       _codec ("MPEG 1 video");
13932       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13933           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13934       break;
13935     default:
13936       caps = NULL;
13937       break;
13938   }
13939   return caps;
13940 }
13941
13942 static void
13943 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
13944     const gchar * system_id)
13945 {
13946   gint i;
13947
13948   if (!qtdemux->protection_system_ids)
13949     qtdemux->protection_system_ids =
13950         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13951   /* Check whether we already have an entry for this system ID. */
13952   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13953     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13954     if (g_ascii_strcasecmp (system_id, id) == 0) {
13955       return;
13956     }
13957   }
13958   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13959   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13960           -1));
13961 }