qtdemux: Add out-of-bound check
[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 QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 GST_DEBUG_CATEGORY (qtdemux_debug);
104
105 typedef struct _QtDemuxSegment QtDemuxSegment;
106 typedef struct _QtDemuxSample QtDemuxSample;
107
108 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
109
110 struct _QtDemuxSample
111 {
112   guint32 size;
113   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
114   guint64 offset;
115   guint64 timestamp;            /* DTS In mov time */
116   guint32 duration;             /* In mov time */
117   gboolean keyframe;            /* TRUE when this packet is a keyframe */
118 };
119
120 /* Macros for converting to/from timescale */
121 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
122 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
123
124 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
125 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
126
127 /* timestamp is the DTS */
128 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
129 /* timestamp + offset + cslg_shift is the outgoing PTS */
130 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
131 /* timestamp + offset is the PTS used for internal seek calcuations */
132 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
133 /* timestamp + duration - dts is the duration */
134 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
135
136 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
137
138 /*
139  * Quicktime has tracks and segments. A track is a continuous piece of
140  * multimedia content. The track is not always played from start to finish but
141  * instead, pieces of the track are 'cut out' and played in sequence. This is
142  * what the segments do.
143  *
144  * Inside the track we have keyframes (K) and delta frames. The track has its
145  * own timing, which starts from 0 and extends to end. The position in the track
146  * is called the media_time.
147  *
148  * The segments now describe the pieces that should be played from this track
149  * and are basically tuples of media_time/duration/rate entries. We can have
150  * multiple segments and they are all played after one another. An example:
151  *
152  * segment 1: media_time: 1 second, duration: 1 second, rate 1
153  * segment 2: media_time: 3 second, duration: 2 second, rate 2
154  *
155  * To correctly play back this track, one must play: 1 second of media starting
156  * from media_time 1 followed by 2 seconds of media starting from media_time 3
157  * at a rate of 2.
158  *
159  * Each of the segments will be played at a specific time, the first segment at
160  * time 0, the second one after the duration of the first one, etc.. Note that
161  * the time in resulting playback is not identical to the media_time of the
162  * track anymore.
163  *
164  * Visually, assuming the track has 4 second of media_time:
165  *
166  *                (a)                   (b)          (c)              (d)
167  *         .-----------------------------------------------------------.
168  * track:  | K.....K.........K........K.......K.......K...........K... |
169  *         '-----------------------------------------------------------'
170  *         0              1              2              3              4
171  *           .------------^              ^   .----------^              ^
172  *          /              .-------------'  /       .------------------'
173  *         /              /          .-----'       /
174  *         .--------------.         .--------------.
175  *         | segment 1    |         | segment 2    |
176  *         '--------------'         '--------------'
177  *
178  * The challenge here is to cut out the right pieces of the track for each of
179  * the playback segments. This fortunately can easily be done with the SEGMENT
180  * events of GStreamer.
181  *
182  * For playback of segment 1, we need to provide the decoder with the keyframe
183  * (a), in the above figure, but we must instruct it only to output the decoded
184  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
185  * position set to the time of the segment: 0.
186  *
187  * We then proceed to push data from keyframe (a) to frame (b). The decoder
188  * decodes but clips all before media_time 1.
189  *
190  * After finishing a segment, we push out a new SEGMENT event with the clipping
191  * boundaries of the new data.
192  *
193  * This is a good usecase for the GStreamer accumulated SEGMENT events.
194  */
195
196 struct _QtDemuxSegment
197 {
198   /* global time and duration, all gst time */
199   GstClockTime time;
200   GstClockTime stop_time;
201   GstClockTime duration;
202   /* media time of trak, all gst time */
203   GstClockTime media_start;
204   GstClockTime media_stop;
205   gdouble rate;
206   /* Media start time in trak timescale units */
207   guint32 trak_media_start;
208 };
209
210 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
211
212 /* Used with fragmented MP4 files (mfra atom) */
213 typedef struct
214 {
215   GstClockTime ts;
216   guint64 moof_offset;
217 } QtDemuxRandomAccessEntry;
218
219 typedef struct _QtDemuxStreamStsdEntry
220 {
221   GstCaps *caps;
222   guint32 fourcc;
223   gboolean sparse;
224
225   /* video info */
226   gint width;
227   gint height;
228   gint par_w;
229   gint par_h;
230   /* Numerator/denominator framerate */
231   gint fps_n;
232   gint fps_d;
233   GstVideoColorimetry colorimetry;
234   guint16 bits_per_sample;
235   guint16 color_table_id;
236   GstMemory *rgb8_palette;
237   guint interlace_mode;
238   guint field_order;
239
240   /* audio info */
241   gdouble rate;
242   gint n_channels;
243   guint samples_per_packet;
244   guint samples_per_frame;
245   guint bytes_per_packet;
246   guint bytes_per_sample;
247   guint bytes_per_frame;
248   guint compression;
249
250   /* if we use chunks or samples */
251   gboolean sampled;
252   guint padding;
253
254 } QtDemuxStreamStsdEntry;
255
256 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
257
258 struct _QtDemuxStream
259 {
260   GstPad *pad;
261
262   QtDemuxStreamStsdEntry *stsd_entries;
263   guint stsd_entries_length;
264   guint cur_stsd_entry_index;
265
266   /* stream type */
267   guint32 subtype;
268
269   gboolean new_caps;            /* If TRUE, caps need to be generated (by
270                                  * calling _configure_stream()) This happens
271                                  * for MSS and fragmented streams */
272
273   gboolean new_stream;          /* signals that a stream_start is required */
274   gboolean on_keyframe;         /* if this stream last pushed buffer was a
275                                  * keyframe. This is important to identify
276                                  * where to stop pushing buffers after a
277                                  * segment stop time */
278
279   /* if the stream has a redirect URI in its headers, we store it here */
280   gchar *redirect_uri;
281
282   /* track id */
283   guint track_id;
284
285   /* duration/scale */
286   guint64 duration;             /* in timescale units */
287   guint32 timescale;
288
289   /* language */
290   gchar lang_id[4];             /* ISO 639-2T language code */
291
292   /* our samples */
293   guint32 n_samples;
294   QtDemuxSample *samples;
295   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
296   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
297                                    the framerate */
298   guint32 n_samples_moof;       /* sample count in a moof */
299   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
300                                  * the framerate of fragmented format stream */
301   guint64 duration_last_moof;
302
303   guint32 offset_in_sample;     /* Offset in the current sample, used for
304                                  * streams which have got exceedingly big
305                                  * sample size (such as 24s of raw audio).
306                                  * Only used when max_buffer_size is non-NULL */
307   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
308                                  * Currently only set for raw audio streams*/
309
310   /* video info */
311   /* aspect ratio */
312   gint display_width;
313   gint display_height;
314
315   /* allocation */
316   gboolean use_allocator;
317   GstAllocator *allocator;
318   GstAllocationParams params;
319
320   gsize alignment;
321
322   /* when a discontinuity is pending */
323   gboolean discont;
324
325   /* list of buffers to push first */
326   GSList *buffers;
327
328   /* if we need to clip this buffer. This is only needed for uncompressed
329    * data */
330   gboolean need_clip;
331
332   /* buffer needs some custom processing, e.g. subtitles */
333   gboolean need_process;
334
335   /* current position */
336   guint32 segment_index;
337   guint32 sample_index;
338   GstClockTime time_position;   /* in gst time */
339   guint64 accumulated_base;
340
341   /* the Gst segment we are processing out, used for clipping */
342   GstSegment segment;
343
344   /* quicktime segments */
345   guint32 n_segments;
346   QtDemuxSegment *segments;
347   gboolean dummy_segment;
348   guint32 from_sample;
349   guint32 to_sample;
350
351   gboolean sent_eos;
352   GstTagList *stream_tags;
353   gboolean send_global_tags;
354
355   GstEvent *pending_event;
356
357   GstByteReader stco;
358   GstByteReader stsz;
359   GstByteReader stsc;
360   GstByteReader stts;
361   GstByteReader stss;
362   GstByteReader stps;
363   GstByteReader ctts;
364
365   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
366   gint64 stbl_index;
367   /* stco */
368   guint co_size;
369   GstByteReader co_chunk;
370   guint32 first_chunk;
371   guint32 current_chunk;
372   guint32 last_chunk;
373   guint32 samples_per_chunk;
374   guint32 stsd_sample_description_id;
375   guint32 stco_sample_index;
376   /* stsz */
377   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
378   /* stsc */
379   guint32 stsc_index;
380   guint32 n_samples_per_chunk;
381   guint32 stsc_chunk_index;
382   guint32 stsc_sample_index;
383   guint64 chunk_offset;
384   /* stts */
385   guint32 stts_index;
386   guint32 stts_samples;
387   guint32 n_sample_times;
388   guint32 stts_sample_index;
389   guint64 stts_time;
390   guint32 stts_duration;
391   /* stss */
392   gboolean stss_present;
393   guint32 n_sample_syncs;
394   guint32 stss_index;
395   /* stps */
396   gboolean stps_present;
397   guint32 n_sample_partial_syncs;
398   guint32 stps_index;
399   QtDemuxRandomAccessEntry *ra_entries;
400   guint n_ra_entries;
401
402   const QtDemuxRandomAccessEntry *pending_seek;
403
404   /* ctts */
405   gboolean ctts_present;
406   guint32 n_composition_times;
407   guint32 ctts_index;
408   guint32 ctts_sample_index;
409   guint32 ctts_count;
410   gint32 ctts_soffset;
411
412   /* cslg */
413   guint32 cslg_shift;
414
415   /* fragmented */
416   gboolean parsed_trex;
417   guint32 def_sample_duration;
418   guint32 def_sample_size;
419   guint32 def_sample_flags;
420
421   gboolean disabled;
422
423   /* stereoscopic video streams */
424   GstVideoMultiviewMode multiview_mode;
425   GstVideoMultiviewFlags multiview_flags;
426
427   /* protected streams */
428   gboolean protected;
429   guint32 protection_scheme_type;
430   guint32 protection_scheme_version;
431   gpointer protection_scheme_info;      /* specific to the protection scheme */
432   GQueue protection_scheme_event_queue;
433 };
434
435 /* Contains properties and cryptographic info for a set of samples from a
436  * track protected using Common Encryption (cenc) */
437 struct _QtDemuxCencSampleSetInfo
438 {
439   GstStructure *default_properties;
440
441   /* @crypto_info holds one GstStructure per sample */
442   GPtrArray *crypto_info;
443 };
444
445 static const gchar *
446 qt_demux_state_string (enum QtDemuxState state)
447 {
448   switch (state) {
449     case QTDEMUX_STATE_INITIAL:
450       return "<INITIAL>";
451     case QTDEMUX_STATE_HEADER:
452       return "<HEADER>";
453     case QTDEMUX_STATE_MOVIE:
454       return "<MOVIE>";
455     case QTDEMUX_STATE_BUFFER_MDAT:
456       return "<BUFFER_MDAT>";
457     default:
458       return "<UNKNOWN>";
459   }
460 }
461
462 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
463 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
464     guint32 fourcc, GstByteReader * parser);
465 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
466 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
467     guint32 fourcc, GstByteReader * parser);
468
469 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
470
471 static GstStaticPadTemplate gst_qtdemux_sink_template =
472     GST_STATIC_PAD_TEMPLATE ("sink",
473     GST_PAD_SINK,
474     GST_PAD_ALWAYS,
475     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
476         "application/x-3gp")
477     );
478
479 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
480 GST_STATIC_PAD_TEMPLATE ("video_%u",
481     GST_PAD_SRC,
482     GST_PAD_SOMETIMES,
483     GST_STATIC_CAPS_ANY);
484
485 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
486 GST_STATIC_PAD_TEMPLATE ("audio_%u",
487     GST_PAD_SRC,
488     GST_PAD_SOMETIMES,
489     GST_STATIC_CAPS_ANY);
490
491 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
492 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
493     GST_PAD_SRC,
494     GST_PAD_SOMETIMES,
495     GST_STATIC_CAPS_ANY);
496
497 #define gst_qtdemux_parent_class parent_class
498 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
499
500 static void gst_qtdemux_dispose (GObject * object);
501
502 static guint32
503 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
504     GstClockTime media_time);
505 static guint32
506 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
507     QtDemuxStream * str, gint64 media_offset);
508
509 #if 0
510 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
511 static GstIndex *gst_qtdemux_get_index (GstElement * element);
512 #endif
513 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
514     GstStateChange transition);
515 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
516 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
517     GstObject * parent, GstPadMode mode, gboolean active);
518
519 static void gst_qtdemux_loop (GstPad * pad);
520 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
521     GstBuffer * inbuf);
522 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
523     GstEvent * event);
524 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
525 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
526     QtDemuxStream * stream);
527 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
528     QtDemuxStream * stream);
529 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
530     gboolean force);
531
532 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
533     const guint8 * buffer, guint length);
534 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
535     const guint8 * buffer, guint length);
536 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
537 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
538     GNode * udta);
539
540 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
541     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
542     GstTagList * list);
543 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
544     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
545     const guint8 * stsd_entry_data, gchar ** codec_name);
546 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
547     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
548     const guint8 * data, int len, gchar ** codec_name);
549 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
550     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
551     gchar ** codec_name);
552 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
553     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
554     const guint8 * stsd_entry_data, gchar ** codec_name);
555
556 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
557     QtDemuxStream * stream, guint32 n);
558 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
559 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
560     QtDemuxStream * stream);
561 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
562     QtDemuxStream * stream);
563 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
564 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
565 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
566     QtDemuxStream * stream);
567 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
568     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
569 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
570     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
571     GstClockTime * _start, GstClockTime * _stop);
572 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
573     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
574
575 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
576 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
577
578 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
579
580 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
581     QtDemuxStream * stream, guint sample_index);
582 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
583     const gchar * id);
584 static void qtdemux_gst_structure_free (GstStructure * gststructure);
585
586 static void
587 gst_qtdemux_class_init (GstQTDemuxClass * klass)
588 {
589   GObjectClass *gobject_class;
590   GstElementClass *gstelement_class;
591
592   gobject_class = (GObjectClass *) klass;
593   gstelement_class = (GstElementClass *) klass;
594
595   parent_class = g_type_class_peek_parent (klass);
596
597   gobject_class->dispose = gst_qtdemux_dispose;
598
599   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
600 #if 0
601   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
602   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
603 #endif
604
605   gst_tag_register_musicbrainz_tags ();
606
607   gst_element_class_add_static_pad_template (gstelement_class,
608       &gst_qtdemux_sink_template);
609   gst_element_class_add_static_pad_template (gstelement_class,
610       &gst_qtdemux_videosrc_template);
611   gst_element_class_add_static_pad_template (gstelement_class,
612       &gst_qtdemux_audiosrc_template);
613   gst_element_class_add_static_pad_template (gstelement_class,
614       &gst_qtdemux_subsrc_template);
615   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
616       "Codec/Demuxer",
617       "Demultiplex a QuickTime file into audio and video streams",
618       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
619
620   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
621
622 }
623
624 static void
625 gst_qtdemux_init (GstQTDemux * qtdemux)
626 {
627   qtdemux->sinkpad =
628       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
629   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
630   gst_pad_set_activatemode_function (qtdemux->sinkpad,
631       qtdemux_sink_activate_mode);
632   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
633   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
634   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
635
636   qtdemux->state = QTDEMUX_STATE_INITIAL;
637   qtdemux->pullbased = FALSE;
638   qtdemux->posted_redirect = FALSE;
639   qtdemux->neededbytes = 16;
640   qtdemux->todrop = 0;
641   qtdemux->adapter = gst_adapter_new ();
642   qtdemux->offset = 0;
643   qtdemux->first_mdat = -1;
644   qtdemux->got_moov = FALSE;
645   qtdemux->mdatoffset = -1;
646   qtdemux->mdatbuffer = NULL;
647   qtdemux->restoredata_buffer = NULL;
648   qtdemux->restoredata_offset = -1;
649   qtdemux->fragment_start = -1;
650   qtdemux->fragment_start_offset = -1;
651   qtdemux->media_caps = NULL;
652   qtdemux->exposed = FALSE;
653   qtdemux->mss_mode = FALSE;
654   qtdemux->pending_newsegment = NULL;
655   qtdemux->upstream_format_is_time = FALSE;
656   qtdemux->have_group_id = FALSE;
657   qtdemux->group_id = G_MAXUINT;
658   qtdemux->cenc_aux_info_offset = 0;
659   qtdemux->cenc_aux_info_sizes = NULL;
660   qtdemux->cenc_aux_sample_count = 0;
661   qtdemux->protection_system_ids = NULL;
662   g_queue_init (&qtdemux->protection_event_queue);
663   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
664   qtdemux->tag_list = gst_tag_list_new_empty ();
665   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
666   qtdemux->flowcombiner = gst_flow_combiner_new ();
667
668   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
669 }
670
671 static void
672 gst_qtdemux_dispose (GObject * object)
673 {
674   GstQTDemux *qtdemux = GST_QTDEMUX (object);
675
676   if (qtdemux->adapter) {
677     g_object_unref (G_OBJECT (qtdemux->adapter));
678     qtdemux->adapter = NULL;
679   }
680   gst_tag_list_unref (qtdemux->tag_list);
681   gst_flow_combiner_free (qtdemux->flowcombiner);
682   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
683       NULL);
684   g_queue_clear (&qtdemux->protection_event_queue);
685
686   g_free (qtdemux->cenc_aux_info_sizes);
687   qtdemux->cenc_aux_info_sizes = NULL;
688
689   G_OBJECT_CLASS (parent_class)->dispose (object);
690 }
691
692 static void
693 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
694 {
695   if (qtdemux->posted_redirect) {
696     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
697         (_("This file contains no playable streams.")),
698         ("no known streams found, a redirect message has been posted"));
699   } else {
700     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
701         (_("This file contains no playable streams.")),
702         ("no known streams found"));
703   }
704 }
705
706 static GstBuffer *
707 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
708 {
709   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
710       mem, size, 0, size, mem, free_func);
711 }
712
713 static GstFlowReturn
714 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
715     GstBuffer ** buf)
716 {
717   GstFlowReturn flow;
718   GstMapInfo map;
719   gsize bsize;
720
721   if (G_UNLIKELY (size == 0)) {
722     GstFlowReturn ret;
723     GstBuffer *tmp = NULL;
724
725     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
726     if (ret != GST_FLOW_OK)
727       return ret;
728
729     gst_buffer_map (tmp, &map, GST_MAP_READ);
730     size = QT_UINT32 (map.data);
731     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
732
733     gst_buffer_unmap (tmp, &map);
734     gst_buffer_unref (tmp);
735   }
736
737   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
738   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
739     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
740       /* we're pulling header but already got most interesting bits,
741        * so never mind the rest (e.g. tags) (that much) */
742       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
743           size);
744       return GST_FLOW_EOS;
745     } else {
746       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
747           (_("This file is invalid and cannot be played.")),
748           ("atom has bogus size %" G_GUINT64_FORMAT, size));
749       return GST_FLOW_ERROR;
750     }
751   }
752
753   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
754
755   if (G_UNLIKELY (flow != GST_FLOW_OK))
756     return flow;
757
758   bsize = gst_buffer_get_size (*buf);
759   /* Catch short reads - we don't want any partial atoms */
760   if (G_UNLIKELY (bsize < size)) {
761     GST_WARNING_OBJECT (qtdemux,
762         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
763     gst_buffer_unref (*buf);
764     *buf = NULL;
765     return GST_FLOW_EOS;
766   }
767
768   return flow;
769 }
770
771 #if 1
772 static gboolean
773 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
774     GstFormat src_format, gint64 src_value, GstFormat dest_format,
775     gint64 * dest_value)
776 {
777   gboolean res = TRUE;
778   QtDemuxStream *stream = gst_pad_get_element_private (pad);
779   gint32 index;
780
781   if (stream->subtype != FOURCC_vide) {
782     res = FALSE;
783     goto done;
784   }
785
786   switch (src_format) {
787     case GST_FORMAT_TIME:
788       switch (dest_format) {
789         case GST_FORMAT_BYTES:{
790           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
791           if (-1 == index) {
792             res = FALSE;
793             goto done;
794           }
795
796           *dest_value = stream->samples[index].offset;
797
798           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
799               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
800               GST_TIME_ARGS (src_value), *dest_value);
801           break;
802         }
803         default:
804           res = FALSE;
805           break;
806       }
807       break;
808     case GST_FORMAT_BYTES:
809       switch (dest_format) {
810         case GST_FORMAT_TIME:{
811           index =
812               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
813               stream, src_value);
814
815           if (-1 == index) {
816             res = FALSE;
817             goto done;
818           }
819
820           *dest_value =
821               QTSTREAMTIME_TO_GSTTIME (stream,
822               stream->samples[index].timestamp);
823           GST_DEBUG_OBJECT (qtdemux,
824               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
825               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
826           break;
827         }
828         default:
829           res = FALSE;
830           break;
831       }
832       break;
833     default:
834       res = FALSE;
835       break;
836   }
837
838 done:
839   return res;
840 }
841 #endif
842
843 static gboolean
844 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
845 {
846   gboolean res = FALSE;
847
848   *duration = GST_CLOCK_TIME_NONE;
849
850   if (qtdemux->duration != 0 &&
851       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
852     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
853     res = TRUE;
854   } else {
855     *duration = GST_CLOCK_TIME_NONE;
856   }
857
858   return res;
859 }
860
861 static gboolean
862 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
863     GstQuery * query)
864 {
865   gboolean res = FALSE;
866   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
867
868   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
869
870   switch (GST_QUERY_TYPE (query)) {
871     case GST_QUERY_POSITION:{
872       GstFormat fmt;
873
874       gst_query_parse_position (query, &fmt, NULL);
875       if (fmt == GST_FORMAT_TIME
876           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
877         gst_query_set_position (query, GST_FORMAT_TIME,
878             qtdemux->segment.position);
879         res = TRUE;
880       }
881     }
882       break;
883     case GST_QUERY_DURATION:{
884       GstFormat fmt;
885
886       gst_query_parse_duration (query, &fmt, NULL);
887       if (fmt == GST_FORMAT_TIME) {
888         /* First try to query upstream */
889         res = gst_pad_query_default (pad, parent, query);
890         if (!res) {
891           GstClockTime duration;
892           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
893             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
894             res = TRUE;
895           }
896         }
897       }
898       break;
899     }
900     case GST_QUERY_CONVERT:{
901       GstFormat src_fmt, dest_fmt;
902       gint64 src_value, dest_value = 0;
903
904       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
905
906       res = gst_qtdemux_src_convert (qtdemux, pad,
907           src_fmt, src_value, dest_fmt, &dest_value);
908       if (res) {
909         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
910         res = TRUE;
911       }
912       break;
913     }
914     case GST_QUERY_FORMATS:
915       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
916       res = TRUE;
917       break;
918     case GST_QUERY_SEEKING:{
919       GstFormat fmt;
920       gboolean seekable;
921
922       /* try upstream first */
923       res = gst_pad_query_default (pad, parent, query);
924
925       if (!res) {
926         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
927         if (fmt == GST_FORMAT_TIME) {
928           GstClockTime duration;
929
930           gst_qtdemux_get_duration (qtdemux, &duration);
931           seekable = TRUE;
932           if (!qtdemux->pullbased) {
933             GstQuery *q;
934
935             /* we might be able with help from upstream */
936             seekable = FALSE;
937             q = gst_query_new_seeking (GST_FORMAT_BYTES);
938             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
939               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
940               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
941             }
942             gst_query_unref (q);
943           }
944           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
945           res = TRUE;
946         }
947       }
948       break;
949     }
950     case GST_QUERY_SEGMENT:
951     {
952       GstFormat format;
953       gint64 start, stop;
954
955       format = qtdemux->segment.format;
956
957       start =
958           gst_segment_to_stream_time (&qtdemux->segment, format,
959           qtdemux->segment.start);
960       if ((stop = qtdemux->segment.stop) == -1)
961         stop = qtdemux->segment.duration;
962       else
963         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
964
965       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
966       res = TRUE;
967       break;
968     }
969     default:
970       res = gst_pad_query_default (pad, parent, query);
971       break;
972   }
973
974   return res;
975 }
976
977 static void
978 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
979 {
980   if (G_LIKELY (stream->pad)) {
981     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
982         GST_DEBUG_PAD_NAME (stream->pad));
983
984     if (!gst_tag_list_is_empty (stream->stream_tags)) {
985       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
986           stream->stream_tags);
987       gst_pad_push_event (stream->pad,
988           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
989     }
990
991     if (G_UNLIKELY (stream->send_global_tags)) {
992       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
993           qtdemux->tag_list);
994       gst_pad_push_event (stream->pad,
995           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
996       stream->send_global_tags = FALSE;
997     }
998   }
999 }
1000
1001 /* push event on all source pads; takes ownership of the event */
1002 static void
1003 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1004 {
1005   guint n;
1006   gboolean has_valid_stream = FALSE;
1007   GstEventType etype = GST_EVENT_TYPE (event);
1008
1009   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1010       GST_EVENT_TYPE_NAME (event));
1011
1012   for (n = 0; n < qtdemux->n_streams; n++) {
1013     GstPad *pad;
1014     QtDemuxStream *stream = qtdemux->streams[n];
1015     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
1016
1017     if ((pad = stream->pad)) {
1018       has_valid_stream = TRUE;
1019
1020       if (etype == GST_EVENT_EOS) {
1021         /* let's not send twice */
1022         if (stream->sent_eos)
1023           continue;
1024         stream->sent_eos = TRUE;
1025       }
1026
1027       gst_pad_push_event (pad, gst_event_ref (event));
1028     }
1029   }
1030
1031   gst_event_unref (event);
1032
1033   /* if it is EOS and there are no pads, post an error */
1034   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1035     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1036   }
1037 }
1038
1039 /* push a pending newsegment event, if any from the streaming thread */
1040 static void
1041 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1042 {
1043   if (qtdemux->pending_newsegment) {
1044     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1045     qtdemux->pending_newsegment = NULL;
1046   }
1047 }
1048
1049 typedef struct
1050 {
1051   guint64 media_time;
1052 } FindData;
1053
1054 static gint
1055 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1056 {
1057   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1058     return 1;
1059   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1060     return 0;
1061
1062   return -1;
1063 }
1064
1065 /* find the index of the sample that includes the data for @media_time using a
1066  * binary search.  Only to be called in optimized cases of linear search below.
1067  *
1068  * Returns the index of the sample.
1069  */
1070 static guint32
1071 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1072     guint64 media_time)
1073 {
1074   QtDemuxSample *result;
1075   guint32 index;
1076
1077   /* convert media_time to mov format */
1078   media_time =
1079       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1080
1081   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1082       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1083       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1084
1085   if (G_LIKELY (result))
1086     index = result - str->samples;
1087   else
1088     index = 0;
1089
1090   return index;
1091 }
1092
1093
1094
1095 /* find the index of the sample that includes the data for @media_offset using a
1096  * linear search
1097  *
1098  * Returns the index of the sample.
1099  */
1100 static guint32
1101 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1102     QtDemuxStream * str, gint64 media_offset)
1103 {
1104   QtDemuxSample *result = str->samples;
1105   guint32 index = 0;
1106
1107   if (result == NULL || str->n_samples == 0)
1108     return -1;
1109
1110   if (media_offset == result->offset)
1111     return index;
1112
1113   result++;
1114   while (index < str->n_samples - 1) {
1115     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1116       goto parse_failed;
1117
1118     if (media_offset < result->offset)
1119       break;
1120
1121     index++;
1122     result++;
1123   }
1124   return index;
1125
1126   /* ERRORS */
1127 parse_failed:
1128   {
1129     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1130     return -1;
1131   }
1132 }
1133
1134 /* find the index of the sample that includes the data for @media_time using a
1135  * linear search, and keeping in mind that not all samples may have been parsed
1136  * yet.  If possible, it will delegate to binary search.
1137  *
1138  * Returns the index of the sample.
1139  */
1140 static guint32
1141 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1142     GstClockTime media_time)
1143 {
1144   guint32 index = 0;
1145   guint64 mov_time;
1146   QtDemuxSample *sample;
1147
1148   /* convert media_time to mov format */
1149   mov_time =
1150       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1151
1152   sample = str->samples;
1153   if (mov_time == sample->timestamp + sample->pts_offset)
1154     return index;
1155
1156   /* use faster search if requested time in already parsed range */
1157   sample = str->samples + str->stbl_index;
1158   if (str->stbl_index >= 0 &&
1159       mov_time <= (sample->timestamp + sample->pts_offset))
1160     return gst_qtdemux_find_index (qtdemux, str, media_time);
1161
1162   while (index < str->n_samples - 1) {
1163     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1164       goto parse_failed;
1165
1166     sample = str->samples + index + 1;
1167     if (mov_time < (sample->timestamp + sample->pts_offset))
1168       break;
1169
1170     index++;
1171   }
1172   return index;
1173
1174   /* ERRORS */
1175 parse_failed:
1176   {
1177     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1178     return -1;
1179   }
1180 }
1181
1182 /* find the index of the keyframe needed to decode the sample at @index
1183  * of stream @str, or of a subsequent keyframe (depending on @next)
1184  *
1185  * Returns the index of the keyframe.
1186  */
1187 static guint32
1188 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1189     guint32 index, gboolean next)
1190 {
1191   guint32 new_index = index;
1192
1193   if (index >= str->n_samples) {
1194     new_index = str->n_samples;
1195     goto beach;
1196   }
1197
1198   /* all keyframes, return index */
1199   if (str->all_keyframe) {
1200     new_index = index;
1201     goto beach;
1202   }
1203
1204   /* else search until we have a keyframe */
1205   while (new_index < str->n_samples) {
1206     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1207       goto parse_failed;
1208
1209     if (str->samples[new_index].keyframe)
1210       break;
1211
1212     if (new_index == 0)
1213       break;
1214
1215     if (next)
1216       new_index++;
1217     else
1218       new_index--;
1219   }
1220
1221   if (new_index == str->n_samples) {
1222     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1223     new_index = -1;
1224   }
1225
1226 beach:
1227   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1228       "gave %u", next ? "after" : "before", index, new_index);
1229
1230   return new_index;
1231
1232   /* ERRORS */
1233 parse_failed:
1234   {
1235     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1236     return -1;
1237   }
1238 }
1239
1240 /* find the segment for @time_position for @stream
1241  *
1242  * Returns the index of the segment containing @time_position.
1243  * Returns the last segment and sets the @eos variable to TRUE
1244  * if the time is beyond the end. @eos may be NULL
1245  */
1246 static guint32
1247 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1248     GstClockTime time_position)
1249 {
1250   gint i;
1251   guint32 seg_idx;
1252
1253   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1254       GST_TIME_ARGS (time_position));
1255
1256   seg_idx = -1;
1257   for (i = 0; i < stream->n_segments; i++) {
1258     QtDemuxSegment *segment = &stream->segments[i];
1259
1260     GST_LOG_OBJECT (stream->pad,
1261         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1262         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1263
1264     /* For the last segment we include stop_time in the last segment */
1265     if (i < stream->n_segments - 1) {
1266       if (segment->time <= time_position && time_position < segment->stop_time) {
1267         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1268         seg_idx = i;
1269         break;
1270       }
1271     } else {
1272       /* Last segment always matches */
1273       seg_idx = i;
1274       break;
1275     }
1276   }
1277   return seg_idx;
1278 }
1279
1280 /* move the stream @str to the sample position @index.
1281  *
1282  * Updates @str->sample_index and marks discontinuity if needed.
1283  */
1284 static void
1285 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1286     guint32 index)
1287 {
1288   /* no change needed */
1289   if (index == str->sample_index)
1290     return;
1291
1292   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1293       str->n_samples);
1294
1295   /* position changed, we have a discont */
1296   str->sample_index = index;
1297   str->offset_in_sample = 0;
1298   /* Each time we move in the stream we store the position where we are
1299    * starting from */
1300   str->from_sample = index;
1301   str->discont = TRUE;
1302 }
1303
1304 static void
1305 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1306     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1307 {
1308   guint64 min_offset;
1309   gint64 min_byte_offset = -1;
1310   gint n;
1311
1312   min_offset = desired_time;
1313
1314   /* for each stream, find the index of the sample in the segment
1315    * and move back to the previous keyframe. */
1316   for (n = 0; n < qtdemux->n_streams; n++) {
1317     QtDemuxStream *str;
1318     guint32 index, kindex;
1319     guint32 seg_idx;
1320     GstClockTime media_start;
1321     GstClockTime media_time;
1322     GstClockTime seg_time;
1323     QtDemuxSegment *seg;
1324     gboolean empty_segment = FALSE;
1325
1326     str = qtdemux->streams[n];
1327
1328     if (CUR_STREAM (str)->sparse && !use_sparse)
1329       continue;
1330
1331     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1332     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1333
1334     /* get segment and time in the segment */
1335     seg = &str->segments[seg_idx];
1336     seg_time = (desired_time - seg->time) * seg->rate;
1337
1338     while (QTSEGMENT_IS_EMPTY (seg)) {
1339       seg_time = 0;
1340       empty_segment = TRUE;
1341       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1342           seg_idx);
1343       seg_idx++;
1344       if (seg_idx == str->n_segments)
1345         break;
1346       seg = &str->segments[seg_idx];
1347     }
1348
1349     if (seg_idx == str->n_segments) {
1350       /* FIXME track shouldn't have the last segment as empty, but if it
1351        * happens we better handle it */
1352       continue;
1353     }
1354
1355     /* get the media time in the segment */
1356     media_start = seg->media_start + seg_time;
1357
1358     /* get the index of the sample with media time */
1359     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1360     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1361         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1362         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1363         empty_segment);
1364
1365     /* shift to next frame if we are looking for next keyframe */
1366     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1367         && index < str->stbl_index)
1368       index++;
1369
1370     if (!empty_segment) {
1371       /* find previous keyframe */
1372       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1373
1374       /* we will settle for one before if none found after */
1375       if (next && kindex == -1)
1376         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1377
1378       /* if the keyframe is at a different position, we need to update the
1379        * requested seek time */
1380       if (index != kindex) {
1381         index = kindex;
1382
1383         /* get timestamp of keyframe */
1384         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1385         GST_DEBUG_OBJECT (qtdemux,
1386             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1387             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1388             str->samples[kindex].offset);
1389
1390         /* keyframes in the segment get a chance to change the
1391          * desired_offset. keyframes out of the segment are
1392          * ignored. */
1393         if (media_time >= seg->media_start) {
1394           GstClockTime seg_time;
1395
1396           /* this keyframe is inside the segment, convert back to
1397            * segment time */
1398           seg_time = (media_time - seg->media_start) + seg->time;
1399           if ((!next && (seg_time < min_offset)) ||
1400               (next && (seg_time > min_offset)))
1401             min_offset = seg_time;
1402         }
1403       }
1404     }
1405
1406     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1407       min_byte_offset = str->samples[index].offset;
1408   }
1409
1410   if (key_time)
1411     *key_time = min_offset;
1412   if (key_offset)
1413     *key_offset = min_byte_offset;
1414 }
1415
1416 static gboolean
1417 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1418     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1419 {
1420   gboolean res;
1421
1422   g_return_val_if_fail (format != NULL, FALSE);
1423   g_return_val_if_fail (cur != NULL, FALSE);
1424   g_return_val_if_fail (stop != NULL, FALSE);
1425
1426   if (*format == GST_FORMAT_TIME)
1427     return TRUE;
1428
1429   res = TRUE;
1430   if (cur_type != GST_SEEK_TYPE_NONE)
1431     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1432   if (res && stop_type != GST_SEEK_TYPE_NONE)
1433     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1434
1435   if (res)
1436     *format = GST_FORMAT_TIME;
1437
1438   return res;
1439 }
1440
1441 /* perform seek in push based mode:
1442    find BYTE position to move to based on time and delegate to upstream
1443 */
1444 static gboolean
1445 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1446 {
1447   gdouble rate;
1448   GstFormat format;
1449   GstSeekFlags flags;
1450   GstSeekType cur_type, stop_type;
1451   gint64 cur, stop, key_cur;
1452   gboolean res;
1453   gint64 byte_cur;
1454   gint64 original_stop;
1455   guint32 seqnum;
1456
1457   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1458
1459   gst_event_parse_seek (event, &rate, &format, &flags,
1460       &cur_type, &cur, &stop_type, &stop);
1461   seqnum = gst_event_get_seqnum (event);
1462
1463   /* only forward streaming and seeking is possible */
1464   if (rate <= 0)
1465     goto unsupported_seek;
1466
1467   /* convert to TIME if needed and possible */
1468   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1469           stop_type, &stop))
1470     goto no_format;
1471
1472   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1473    * the original stop position to use when upstream pushes the new segment
1474    * for this seek */
1475   original_stop = stop;
1476   stop = -1;
1477
1478   /* find reasonable corresponding BYTE position,
1479    * also try to mind about keyframes, since we can not go back a bit for them
1480    * later on */
1481   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1482    * mostly just work, but let's not yet boldly go there  ... */
1483   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1484
1485   if (byte_cur == -1)
1486     goto abort_seek;
1487
1488   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1489       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1490       stop);
1491
1492   GST_OBJECT_LOCK (qtdemux);
1493   qtdemux->seek_offset = byte_cur;
1494   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1495     qtdemux->push_seek_start = cur;
1496   } else {
1497     qtdemux->push_seek_start = key_cur;
1498   }
1499
1500   if (stop_type == GST_SEEK_TYPE_NONE) {
1501     qtdemux->push_seek_stop = qtdemux->segment.stop;
1502   } else {
1503     qtdemux->push_seek_stop = original_stop;
1504   }
1505   GST_OBJECT_UNLOCK (qtdemux);
1506
1507   /* BYTE seek event */
1508   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1509       stop_type, stop);
1510   gst_event_set_seqnum (event, seqnum);
1511   res = gst_pad_push_event (qtdemux->sinkpad, event);
1512
1513   return res;
1514
1515   /* ERRORS */
1516 abort_seek:
1517   {
1518     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1519         "seek aborted.");
1520     return FALSE;
1521   }
1522 unsupported_seek:
1523   {
1524     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1525     return FALSE;
1526   }
1527 no_format:
1528   {
1529     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1530     return FALSE;
1531   }
1532 }
1533
1534 /* perform the seek.
1535  *
1536  * We set all segment_indexes in the streams to unknown and
1537  * adjust the time_position to the desired position. this is enough
1538  * to trigger a segment switch in the streaming thread to start
1539  * streaming from the desired position.
1540  *
1541  * Keyframe seeking is a little more complicated when dealing with
1542  * segments. Ideally we want to move to the previous keyframe in
1543  * the segment but there might not be a keyframe in the segment. In
1544  * fact, none of the segments could contain a keyframe. We take a
1545  * practical approach: seek to the previous keyframe in the segment,
1546  * if there is none, seek to the beginning of the segment.
1547  *
1548  * Called with STREAM_LOCK
1549  */
1550 static gboolean
1551 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1552     guint32 seqnum, GstSeekFlags flags)
1553 {
1554   gint64 desired_offset;
1555   gint n;
1556
1557   desired_offset = segment->position;
1558
1559   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1560       GST_TIME_ARGS (desired_offset));
1561
1562   /* may not have enough fragmented info to do this adjustment,
1563    * and we can't scan (and probably should not) at this time with
1564    * possibly flushing upstream */
1565   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1566     gint64 min_offset;
1567     gboolean next, before, after;
1568
1569     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1570     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1571     next = after && !before;
1572     if (segment->rate < 0)
1573       next = !next;
1574
1575     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1576         NULL);
1577     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1578         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1579     desired_offset = min_offset;
1580   }
1581
1582   /* and set all streams to the final position */
1583   gst_flow_combiner_reset (qtdemux->flowcombiner);
1584   qtdemux->segment_seqnum = seqnum;
1585   for (n = 0; n < qtdemux->n_streams; n++) {
1586     QtDemuxStream *stream = qtdemux->streams[n];
1587
1588     stream->time_position = desired_offset;
1589     stream->accumulated_base = 0;
1590     stream->sample_index = -1;
1591     stream->offset_in_sample = 0;
1592     stream->segment_index = -1;
1593     stream->sent_eos = FALSE;
1594
1595     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1596       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1597   }
1598   segment->position = desired_offset;
1599   segment->time = desired_offset;
1600   if (segment->rate >= 0) {
1601     segment->start = desired_offset;
1602
1603     /* we stop at the end */
1604     if (segment->stop == -1)
1605       segment->stop = segment->duration;
1606   } else {
1607     segment->stop = desired_offset;
1608   }
1609
1610   if (qtdemux->fragmented)
1611     qtdemux->fragmented_seek_pending = TRUE;
1612
1613   return TRUE;
1614 }
1615
1616 /* do a seek in pull based mode */
1617 static gboolean
1618 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1619 {
1620   gdouble rate;
1621   GstFormat format;
1622   GstSeekFlags flags;
1623   GstSeekType cur_type, stop_type;
1624   gint64 cur, stop;
1625   gboolean flush;
1626   gboolean update;
1627   GstSegment seeksegment;
1628   guint32 seqnum = 0;
1629   GstEvent *flush_event;
1630
1631   if (event) {
1632     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1633
1634     gst_event_parse_seek (event, &rate, &format, &flags,
1635         &cur_type, &cur, &stop_type, &stop);
1636     seqnum = gst_event_get_seqnum (event);
1637
1638     /* we have to have a format as the segment format. Try to convert
1639      * if not. */
1640     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1641             stop_type, &stop))
1642       goto no_format;
1643
1644     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1645   } else {
1646     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1647     flags = 0;
1648   }
1649
1650   flush = flags & GST_SEEK_FLAG_FLUSH;
1651
1652   /* stop streaming, either by flushing or by pausing the task */
1653   if (flush) {
1654     flush_event = gst_event_new_flush_start ();
1655     if (seqnum)
1656       gst_event_set_seqnum (flush_event, seqnum);
1657     /* unlock upstream pull_range */
1658     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1659     /* make sure out loop function exits */
1660     gst_qtdemux_push_event (qtdemux, flush_event);
1661   } else {
1662     /* non flushing seek, pause the task */
1663     gst_pad_pause_task (qtdemux->sinkpad);
1664   }
1665
1666   /* wait for streaming to finish */
1667   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1668
1669   /* copy segment, we need this because we still need the old
1670    * segment when we close the current segment. */
1671   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1672
1673   if (event) {
1674     /* configure the segment with the seek variables */
1675     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1676     gst_segment_do_seek (&seeksegment, rate, format, flags,
1677         cur_type, cur, stop_type, stop, &update);
1678   }
1679
1680   /* now do the seek, this actually never returns FALSE */
1681   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1682
1683   /* prepare for streaming again */
1684   if (flush) {
1685     flush_event = gst_event_new_flush_stop (TRUE);
1686     if (seqnum)
1687       gst_event_set_seqnum (flush_event, seqnum);
1688
1689     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1690     gst_qtdemux_push_event (qtdemux, flush_event);
1691   }
1692
1693   /* commit the new segment */
1694   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1695
1696   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1697     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1698         qtdemux->segment.format, qtdemux->segment.position);
1699     if (seqnum)
1700       gst_message_set_seqnum (msg, seqnum);
1701     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1702   }
1703
1704   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1705   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1706       qtdemux->sinkpad, NULL);
1707
1708   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1709
1710   return TRUE;
1711
1712   /* ERRORS */
1713 no_format:
1714   {
1715     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1716     return FALSE;
1717   }
1718 }
1719
1720 static gboolean
1721 qtdemux_ensure_index (GstQTDemux * qtdemux)
1722 {
1723   guint i;
1724
1725   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1726
1727   /* Build complete index */
1728   for (i = 0; i < qtdemux->n_streams; i++) {
1729     QtDemuxStream *stream = qtdemux->streams[i];
1730
1731     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1732       goto parse_error;
1733   }
1734   return TRUE;
1735
1736   /* ERRORS */
1737 parse_error:
1738   {
1739     GST_LOG_OBJECT (qtdemux,
1740         "Building complete index of stream %u for seeking failed!", i);
1741     return FALSE;
1742   }
1743 }
1744
1745 static gboolean
1746 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1747     GstEvent * event)
1748 {
1749   gboolean res = TRUE;
1750   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1751
1752   switch (GST_EVENT_TYPE (event)) {
1753     case GST_EVENT_SEEK:
1754     {
1755 #ifndef GST_DISABLE_GST_DEBUG
1756       GstClockTime ts = gst_util_get_timestamp ();
1757 #endif
1758       guint32 seqnum = gst_event_get_seqnum (event);
1759
1760       if (seqnum == qtdemux->segment_seqnum) {
1761         GST_LOG_OBJECT (pad,
1762             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1763         gst_event_unref (event);
1764         return TRUE;
1765       }
1766
1767       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1768         /* seek should be handled by upstream, we might need to re-download fragments */
1769         GST_DEBUG_OBJECT (qtdemux,
1770             "let upstream handle seek for fragmented playback");
1771         goto upstream;
1772       }
1773
1774       /* Build complete index for seeking;
1775        * if not a fragmented file at least */
1776       if (!qtdemux->fragmented)
1777         if (!qtdemux_ensure_index (qtdemux))
1778           goto index_failed;
1779 #ifndef GST_DISABLE_GST_DEBUG
1780       ts = gst_util_get_timestamp () - ts;
1781       GST_INFO_OBJECT (qtdemux,
1782           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1783 #endif
1784     }
1785       if (qtdemux->pullbased) {
1786         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1787       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1788         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1789         res = TRUE;
1790       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1791           && !qtdemux->fragmented) {
1792         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1793       } else {
1794         GST_DEBUG_OBJECT (qtdemux,
1795             "ignoring seek in push mode in current state");
1796         res = FALSE;
1797       }
1798       gst_event_unref (event);
1799       break;
1800     default:
1801     upstream:
1802       res = gst_pad_event_default (pad, parent, event);
1803       break;
1804   }
1805
1806 done:
1807   return res;
1808
1809   /* ERRORS */
1810 index_failed:
1811   {
1812     GST_ERROR_OBJECT (qtdemux, "Index failed");
1813     gst_event_unref (event);
1814     res = FALSE;
1815     goto done;
1816   }
1817 }
1818
1819 /* stream/index return sample that is min/max w.r.t. byte position,
1820  * time is min/max w.r.t. time of samples,
1821  * the latter need not be time of the former sample */
1822 static void
1823 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1824     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1825 {
1826   gint i, n, index;
1827   gint64 time, min_time;
1828   QtDemuxStream *stream;
1829
1830   min_time = -1;
1831   stream = NULL;
1832   index = -1;
1833
1834   for (n = 0; n < qtdemux->n_streams; ++n) {
1835     QtDemuxStream *str;
1836     gint inc;
1837     gboolean set_sample;
1838
1839     str = qtdemux->streams[n];
1840     set_sample = !set;
1841
1842     if (fw) {
1843       i = 0;
1844       inc = 1;
1845     } else {
1846       i = str->n_samples - 1;
1847       inc = -1;
1848     }
1849
1850     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1851       if (str->samples[i].size == 0)
1852         continue;
1853
1854       if (fw && (str->samples[i].offset < byte_pos))
1855         continue;
1856
1857       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1858         continue;
1859
1860       /* move stream to first available sample */
1861       if (set) {
1862         gst_qtdemux_move_stream (qtdemux, str, i);
1863         set_sample = TRUE;
1864       }
1865
1866       /* avoid index from sparse streams since they might be far away */
1867       if (!CUR_STREAM (str)->sparse) {
1868         /* determine min/max time */
1869         time = QTSAMPLE_PTS (str, &str->samples[i]);
1870         if (min_time == -1 || (!fw && time > min_time) ||
1871             (fw && time < min_time)) {
1872           min_time = time;
1873         }
1874
1875         /* determine stream with leading sample, to get its position */
1876         if (!stream ||
1877             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1878             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1879           stream = str;
1880           index = i;
1881         }
1882       }
1883       break;
1884     }
1885
1886     /* no sample for this stream, mark eos */
1887     if (!set_sample)
1888       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1889   }
1890
1891   if (_time)
1892     *_time = min_time;
1893   if (_stream)
1894     *_stream = stream;
1895   if (_index)
1896     *_index = index;
1897 }
1898
1899 static QtDemuxStream *
1900 _create_stream (void)
1901 {
1902   QtDemuxStream *stream;
1903
1904   stream = g_new0 (QtDemuxStream, 1);
1905   /* new streams always need a discont */
1906   stream->discont = TRUE;
1907   /* we enable clipping for raw audio/video streams */
1908   stream->need_clip = FALSE;
1909   stream->need_process = FALSE;
1910   stream->segment_index = -1;
1911   stream->time_position = 0;
1912   stream->sample_index = -1;
1913   stream->offset_in_sample = 0;
1914   stream->new_stream = TRUE;
1915   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1916   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1917   stream->protected = FALSE;
1918   stream->protection_scheme_type = 0;
1919   stream->protection_scheme_version = 0;
1920   stream->protection_scheme_info = NULL;
1921   stream->n_samples_moof = 0;
1922   stream->duration_moof = 0;
1923   stream->duration_last_moof = 0;
1924   stream->alignment = 1;
1925   stream->stream_tags = gst_tag_list_new_empty ();
1926   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1927   g_queue_init (&stream->protection_scheme_event_queue);
1928   return stream;
1929 }
1930
1931 static gboolean
1932 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1933 {
1934   GstStructure *structure;
1935   const gchar *variant;
1936   const GstCaps *mediacaps = NULL;
1937
1938   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1939
1940   structure = gst_caps_get_structure (caps, 0);
1941   variant = gst_structure_get_string (structure, "variant");
1942
1943   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1944     QtDemuxStream *stream;
1945     const GValue *value;
1946
1947     demux->fragmented = TRUE;
1948     demux->mss_mode = TRUE;
1949
1950     if (demux->n_streams > 1) {
1951       /* can't do this, we can only renegotiate for another mss format */
1952       return FALSE;
1953     }
1954
1955     value = gst_structure_get_value (structure, "media-caps");
1956     /* create stream */
1957     if (value) {
1958       const GValue *timescale_v;
1959
1960       /* TODO update when stream changes during playback */
1961
1962       if (demux->n_streams == 0) {
1963         stream = _create_stream ();
1964         demux->streams[demux->n_streams] = stream;
1965         demux->n_streams = 1;
1966       } else {
1967         stream = demux->streams[0];
1968       }
1969
1970       timescale_v = gst_structure_get_value (structure, "timescale");
1971       if (timescale_v) {
1972         stream->timescale = g_value_get_uint64 (timescale_v);
1973       } else {
1974         /* default mss timescale */
1975         stream->timescale = 10000000;
1976       }
1977       demux->timescale = stream->timescale;
1978
1979       mediacaps = gst_value_get_caps (value);
1980       if (!CUR_STREAM (stream)->caps
1981           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1982         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1983             mediacaps);
1984         stream->new_caps = TRUE;
1985       }
1986       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1987       structure = gst_caps_get_structure (mediacaps, 0);
1988       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1989         stream->subtype = FOURCC_vide;
1990
1991         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1992         gst_structure_get_int (structure, "height",
1993             &CUR_STREAM (stream)->height);
1994         gst_structure_get_fraction (structure, "framerate",
1995             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1996       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1997         gint rate = 0;
1998         stream->subtype = FOURCC_soun;
1999         gst_structure_get_int (structure, "channels",
2000             &CUR_STREAM (stream)->n_channels);
2001         gst_structure_get_int (structure, "rate", &rate);
2002         CUR_STREAM (stream)->rate = rate;
2003       }
2004     }
2005     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2006   } else {
2007     demux->mss_mode = FALSE;
2008   }
2009
2010   return TRUE;
2011 }
2012
2013 static void
2014 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2015 {
2016   gint n;
2017
2018   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2019   gst_pad_stop_task (qtdemux->sinkpad);
2020
2021   if (hard || qtdemux->upstream_format_is_time) {
2022     qtdemux->state = QTDEMUX_STATE_INITIAL;
2023     qtdemux->neededbytes = 16;
2024     qtdemux->todrop = 0;
2025     qtdemux->pullbased = FALSE;
2026     qtdemux->posted_redirect = FALSE;
2027     qtdemux->first_mdat = -1;
2028     qtdemux->header_size = 0;
2029     qtdemux->mdatoffset = -1;
2030     qtdemux->restoredata_offset = -1;
2031     if (qtdemux->mdatbuffer)
2032       gst_buffer_unref (qtdemux->mdatbuffer);
2033     if (qtdemux->restoredata_buffer)
2034       gst_buffer_unref (qtdemux->restoredata_buffer);
2035     qtdemux->mdatbuffer = NULL;
2036     qtdemux->restoredata_buffer = NULL;
2037     qtdemux->mdatleft = 0;
2038     qtdemux->mdatsize = 0;
2039     if (qtdemux->comp_brands)
2040       gst_buffer_unref (qtdemux->comp_brands);
2041     qtdemux->comp_brands = NULL;
2042     qtdemux->last_moov_offset = -1;
2043     if (qtdemux->moov_node_compressed) {
2044       g_node_destroy (qtdemux->moov_node_compressed);
2045       if (qtdemux->moov_node)
2046         g_free (qtdemux->moov_node->data);
2047     }
2048     qtdemux->moov_node_compressed = NULL;
2049     if (qtdemux->moov_node)
2050       g_node_destroy (qtdemux->moov_node);
2051     qtdemux->moov_node = NULL;
2052     if (qtdemux->tag_list)
2053       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2054     qtdemux->tag_list = gst_tag_list_new_empty ();
2055     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2056 #if 0
2057     if (qtdemux->element_index)
2058       gst_object_unref (qtdemux->element_index);
2059     qtdemux->element_index = NULL;
2060 #endif
2061     qtdemux->major_brand = 0;
2062     if (qtdemux->pending_newsegment)
2063       gst_event_unref (qtdemux->pending_newsegment);
2064     qtdemux->pending_newsegment = NULL;
2065     qtdemux->upstream_format_is_time = FALSE;
2066     qtdemux->upstream_seekable = FALSE;
2067     qtdemux->upstream_size = 0;
2068
2069     qtdemux->fragment_start = -1;
2070     qtdemux->fragment_start_offset = -1;
2071     qtdemux->duration = 0;
2072     qtdemux->moof_offset = 0;
2073     qtdemux->chapters_track_id = 0;
2074     qtdemux->have_group_id = FALSE;
2075     qtdemux->group_id = G_MAXUINT;
2076
2077     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2078         NULL);
2079     g_queue_clear (&qtdemux->protection_event_queue);
2080   }
2081   qtdemux->offset = 0;
2082   gst_adapter_clear (qtdemux->adapter);
2083   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2084   qtdemux->segment_seqnum = 0;
2085
2086   if (hard) {
2087     for (n = 0; n < qtdemux->n_streams; n++) {
2088       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2089       qtdemux->streams[n] = NULL;
2090     }
2091     qtdemux->n_streams = 0;
2092     qtdemux->n_video_streams = 0;
2093     qtdemux->n_audio_streams = 0;
2094     qtdemux->n_sub_streams = 0;
2095     qtdemux->exposed = FALSE;
2096     qtdemux->fragmented = FALSE;
2097     qtdemux->mss_mode = FALSE;
2098     gst_caps_replace (&qtdemux->media_caps, NULL);
2099     qtdemux->timescale = 0;
2100     qtdemux->got_moov = FALSE;
2101     if (qtdemux->protection_system_ids) {
2102       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2103       qtdemux->protection_system_ids = NULL;
2104     }
2105   } else if (qtdemux->mss_mode) {
2106     gst_flow_combiner_reset (qtdemux->flowcombiner);
2107     for (n = 0; n < qtdemux->n_streams; n++)
2108       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2109   } else {
2110     gst_flow_combiner_reset (qtdemux->flowcombiner);
2111     for (n = 0; n < qtdemux->n_streams; n++) {
2112       qtdemux->streams[n]->sent_eos = FALSE;
2113       qtdemux->streams[n]->time_position = 0;
2114       qtdemux->streams[n]->accumulated_base = 0;
2115     }
2116     if (!qtdemux->pending_newsegment) {
2117       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2118       if (qtdemux->segment_seqnum)
2119         gst_event_set_seqnum (qtdemux->pending_newsegment,
2120             qtdemux->segment_seqnum);
2121     }
2122   }
2123 }
2124
2125
2126 /* Maps the @segment to the qt edts internal segments and pushes
2127  * the correspnding segment event.
2128  *
2129  * If it ends up being at a empty segment, a gap will be pushed and the next
2130  * edts segment will be activated in sequence.
2131  *
2132  * To be used in push-mode only */
2133 static void
2134 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2135 {
2136   gint n, i;
2137
2138   for (n = 0; n < qtdemux->n_streams; n++) {
2139     QtDemuxStream *stream = qtdemux->streams[n];
2140
2141     stream->time_position = segment->start;
2142
2143     /* in push mode we should be guaranteed that we will have empty segments
2144      * at the beginning and then one segment after, other scenarios are not
2145      * supported and are discarded when parsing the edts */
2146     for (i = 0; i < stream->n_segments; i++) {
2147       if (stream->segments[i].stop_time > segment->start) {
2148         gst_qtdemux_activate_segment (qtdemux, stream, i,
2149             stream->time_position);
2150         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2151           /* push the empty segment and move to the next one */
2152           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2153               stream->time_position);
2154           continue;
2155         }
2156
2157         g_assert (i == stream->n_segments - 1);
2158       }
2159     }
2160   }
2161 }
2162
2163 static gboolean
2164 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2165     GstEvent * event)
2166 {
2167   GstQTDemux *demux = GST_QTDEMUX (parent);
2168   gboolean res = TRUE;
2169
2170   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2171
2172   switch (GST_EVENT_TYPE (event)) {
2173     case GST_EVENT_SEGMENT:
2174     {
2175       gint64 offset = 0;
2176       QtDemuxStream *stream;
2177       gint idx;
2178       GstSegment segment;
2179
2180       /* some debug output */
2181       gst_event_copy_segment (event, &segment);
2182       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2183           &segment);
2184
2185       /* erase any previously set segment */
2186       gst_event_replace (&demux->pending_newsegment, NULL);
2187
2188       if (segment.format == GST_FORMAT_TIME) {
2189         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2190         gst_event_replace (&demux->pending_newsegment, event);
2191         demux->upstream_format_is_time = TRUE;
2192       } else {
2193         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2194             "not in time format");
2195
2196         /* chain will send initial newsegment after pads have been added */
2197         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2198           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2199           goto exit;
2200         }
2201       }
2202
2203       /* check if this matches a time seek we received previously
2204        * FIXME for backwards compatibility reasons we use the
2205        * seek_offset here to compare. In the future we might want to
2206        * change this to use the seqnum as it uniquely should identify
2207        * the segment that corresponds to the seek. */
2208       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2209           ", received segment offset %" G_GINT64_FORMAT,
2210           demux->seek_offset, segment.start);
2211       if (segment.format == GST_FORMAT_BYTES
2212           && demux->seek_offset == segment.start) {
2213         GST_OBJECT_LOCK (demux);
2214         offset = segment.start;
2215
2216         segment.format = GST_FORMAT_TIME;
2217         segment.start = demux->push_seek_start;
2218         segment.stop = demux->push_seek_stop;
2219         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2220             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2221             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2222         GST_OBJECT_UNLOCK (demux);
2223       }
2224
2225       /* we only expect a BYTE segment, e.g. following a seek */
2226       if (segment.format == GST_FORMAT_BYTES) {
2227         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2228           offset = segment.start;
2229
2230           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2231               NULL, (gint64 *) & segment.start);
2232           if ((gint64) segment.start < 0)
2233             segment.start = 0;
2234         }
2235         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2236           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2237               NULL, (gint64 *) & segment.stop);
2238           /* keyframe seeking should already arrange for start >= stop,
2239            * but make sure in other rare cases */
2240           segment.stop = MAX (segment.stop, segment.start);
2241         }
2242       } else if (segment.format == GST_FORMAT_TIME) {
2243         /* push all data on the adapter before starting this
2244          * new segment */
2245         gst_qtdemux_process_adapter (demux, TRUE);
2246       } else {
2247         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2248         goto exit;
2249       }
2250
2251       /* We shouldn't modify upstream driven TIME FORMAT segment */
2252       if (!demux->upstream_format_is_time) {
2253         /* accept upstream's notion of segment and distribute along */
2254         segment.format = GST_FORMAT_TIME;
2255         segment.position = segment.time = segment.start;
2256         segment.duration = demux->segment.duration;
2257         segment.base = gst_segment_to_running_time (&demux->segment,
2258             GST_FORMAT_TIME, demux->segment.position);
2259       }
2260
2261       gst_segment_copy_into (&segment, &demux->segment);
2262       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2263
2264       /* map segment to internal qt segments and push on each stream */
2265       if (demux->n_streams) {
2266         if (demux->fragmented) {
2267           GstEvent *segment_event = gst_event_new_segment (&segment);
2268
2269           gst_event_replace (&demux->pending_newsegment, NULL);
2270           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2271           gst_qtdemux_push_event (demux, segment_event);
2272         } else {
2273           gst_event_replace (&demux->pending_newsegment, NULL);
2274           gst_qtdemux_map_and_push_segments (demux, &segment);
2275         }
2276       }
2277
2278       /* clear leftover in current segment, if any */
2279       gst_adapter_clear (demux->adapter);
2280
2281       /* set up streaming thread */
2282       demux->offset = offset;
2283       if (demux->upstream_format_is_time) {
2284         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2285             "set values to restart reading from a new atom");
2286         demux->neededbytes = 16;
2287         demux->todrop = 0;
2288       } else {
2289         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2290             NULL);
2291         if (stream) {
2292           demux->todrop = stream->samples[idx].offset - offset;
2293           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2294         } else {
2295           /* set up for EOS */
2296           demux->neededbytes = -1;
2297           demux->todrop = 0;
2298         }
2299       }
2300     exit:
2301       gst_event_unref (event);
2302       res = TRUE;
2303       goto drop;
2304     }
2305     case GST_EVENT_FLUSH_START:
2306     {
2307       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2308         gst_event_unref (event);
2309         goto drop;
2310       }
2311       break;
2312     }
2313     case GST_EVENT_FLUSH_STOP:
2314     {
2315       guint64 dur;
2316
2317       dur = demux->segment.duration;
2318       gst_qtdemux_reset (demux, FALSE);
2319       demux->segment.duration = dur;
2320
2321       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2322         gst_event_unref (event);
2323         goto drop;
2324       }
2325       break;
2326     }
2327     case GST_EVENT_EOS:
2328       /* If we are in push mode, and get an EOS before we've seen any streams,
2329        * then error out - we have nowhere to send the EOS */
2330       if (!demux->pullbased) {
2331         gint i;
2332         gboolean has_valid_stream = FALSE;
2333         for (i = 0; i < demux->n_streams; i++) {
2334           if (demux->streams[i]->pad != NULL) {
2335             has_valid_stream = TRUE;
2336             break;
2337           }
2338         }
2339         if (!has_valid_stream)
2340           gst_qtdemux_post_no_playable_stream_error (demux);
2341         else {
2342           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2343               (guint) gst_adapter_available (demux->adapter));
2344           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2345             res = FALSE;
2346           }
2347         }
2348       }
2349       break;
2350     case GST_EVENT_CAPS:{
2351       GstCaps *caps = NULL;
2352
2353       gst_event_parse_caps (event, &caps);
2354       gst_qtdemux_setcaps (demux, caps);
2355       res = TRUE;
2356       gst_event_unref (event);
2357       goto drop;
2358     }
2359     case GST_EVENT_PROTECTION:
2360     {
2361       const gchar *system_id = NULL;
2362
2363       gst_event_parse_protection (event, &system_id, NULL, NULL);
2364       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2365           system_id);
2366       gst_qtdemux_append_protection_system_id (demux, system_id);
2367       /* save the event for later, for source pads that have not been created */
2368       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2369       /* send it to all pads that already exist */
2370       gst_qtdemux_push_event (demux, event);
2371       res = TRUE;
2372       goto drop;
2373     }
2374     default:
2375       break;
2376   }
2377
2378   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2379
2380 drop:
2381   return res;
2382 }
2383
2384 #if 0
2385 static void
2386 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2387 {
2388   GstQTDemux *demux = GST_QTDEMUX (element);
2389
2390   GST_OBJECT_LOCK (demux);
2391   if (demux->element_index)
2392     gst_object_unref (demux->element_index);
2393   if (index) {
2394     demux->element_index = gst_object_ref (index);
2395   } else {
2396     demux->element_index = NULL;
2397   }
2398   GST_OBJECT_UNLOCK (demux);
2399   /* object lock might be taken again */
2400   if (index)
2401     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2402   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2403       demux->element_index, demux->index_id);
2404 }
2405
2406 static GstIndex *
2407 gst_qtdemux_get_index (GstElement * element)
2408 {
2409   GstIndex *result = NULL;
2410   GstQTDemux *demux = GST_QTDEMUX (element);
2411
2412   GST_OBJECT_LOCK (demux);
2413   if (demux->element_index)
2414     result = gst_object_ref (demux->element_index);
2415   GST_OBJECT_UNLOCK (demux);
2416
2417   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2418
2419   return result;
2420 }
2421 #endif
2422
2423 static void
2424 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2425 {
2426   g_free ((gpointer) stream->stco.data);
2427   stream->stco.data = NULL;
2428   g_free ((gpointer) stream->stsz.data);
2429   stream->stsz.data = NULL;
2430   g_free ((gpointer) stream->stsc.data);
2431   stream->stsc.data = NULL;
2432   g_free ((gpointer) stream->stts.data);
2433   stream->stts.data = NULL;
2434   g_free ((gpointer) stream->stss.data);
2435   stream->stss.data = NULL;
2436   g_free ((gpointer) stream->stps.data);
2437   stream->stps.data = NULL;
2438   g_free ((gpointer) stream->ctts.data);
2439   stream->ctts.data = NULL;
2440 }
2441
2442 static void
2443 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2444     QtDemuxStream * stream)
2445 {
2446   g_free (stream->segments);
2447   stream->segments = NULL;
2448   stream->segment_index = -1;
2449   stream->accumulated_base = 0;
2450 }
2451
2452 static void
2453 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2454     QtDemuxStream * stream)
2455 {
2456   g_free (stream->samples);
2457   stream->samples = NULL;
2458   gst_qtdemux_stbl_free (stream);
2459
2460   /* fragments */
2461   g_free (stream->ra_entries);
2462   stream->ra_entries = NULL;
2463   stream->n_ra_entries = 0;
2464
2465   stream->sample_index = -1;
2466   stream->stbl_index = -1;
2467   stream->n_samples = 0;
2468   stream->time_position = 0;
2469
2470   stream->n_samples_moof = 0;
2471   stream->duration_moof = 0;
2472   stream->duration_last_moof = 0;
2473 }
2474
2475 static void
2476 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2477 {
2478   gint i;
2479   if (stream->allocator)
2480     gst_object_unref (stream->allocator);
2481   while (stream->buffers) {
2482     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2483     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2484   }
2485   for (i = 0; i < stream->stsd_entries_length; i++) {
2486     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2487     if (entry->rgb8_palette) {
2488       gst_memory_unref (entry->rgb8_palette);
2489       entry->rgb8_palette = NULL;
2490     }
2491     entry->sparse = FALSE;
2492   }
2493
2494   gst_tag_list_unref (stream->stream_tags);
2495   stream->stream_tags = gst_tag_list_new_empty ();
2496   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2497   g_free (stream->redirect_uri);
2498   stream->redirect_uri = NULL;
2499   stream->sent_eos = FALSE;
2500   stream->protected = FALSE;
2501   if (stream->protection_scheme_info) {
2502     if (stream->protection_scheme_type == FOURCC_cenc) {
2503       QtDemuxCencSampleSetInfo *info =
2504           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2505       if (info->default_properties)
2506         gst_structure_free (info->default_properties);
2507       if (info->crypto_info)
2508         g_ptr_array_free (info->crypto_info, TRUE);
2509     }
2510     g_free (stream->protection_scheme_info);
2511     stream->protection_scheme_info = NULL;
2512   }
2513   stream->protection_scheme_type = 0;
2514   stream->protection_scheme_version = 0;
2515   g_queue_foreach (&stream->protection_scheme_event_queue,
2516       (GFunc) gst_event_unref, NULL);
2517   g_queue_clear (&stream->protection_scheme_event_queue);
2518   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2519   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2520 }
2521
2522 static void
2523 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2524 {
2525   gint i;
2526   gst_qtdemux_stream_clear (qtdemux, stream);
2527   for (i = 0; i < stream->stsd_entries_length; i++) {
2528     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2529     if (entry->caps) {
2530       gst_caps_unref (entry->caps);
2531       entry->caps = NULL;
2532     }
2533   }
2534   gst_tag_list_unref (stream->stream_tags);
2535   if (stream->pad) {
2536     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2537     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2538   }
2539   g_free (stream);
2540 }
2541
2542 static void
2543 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2544 {
2545   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2546
2547   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2548   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2549   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2550   qtdemux->n_streams--;
2551 }
2552
2553 static GstStateChangeReturn
2554 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2555 {
2556   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2557   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2558
2559   switch (transition) {
2560     case GST_STATE_CHANGE_PAUSED_TO_READY:
2561       break;
2562     default:
2563       break;
2564   }
2565
2566   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2567
2568   switch (transition) {
2569     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2570       gst_qtdemux_reset (qtdemux, TRUE);
2571       break;
2572     }
2573     default:
2574       break;
2575   }
2576
2577   return result;
2578 }
2579
2580 static void
2581 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2582 {
2583   /* counts as header data */
2584   qtdemux->header_size += length;
2585
2586   /* only consider at least a sufficiently complete ftyp atom */
2587   if (length >= 20) {
2588     GstBuffer *buf;
2589
2590     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2591     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2592         GST_FOURCC_ARGS (qtdemux->major_brand));
2593     if (qtdemux->comp_brands)
2594       gst_buffer_unref (qtdemux->comp_brands);
2595     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2596     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2597   }
2598 }
2599
2600 static void
2601 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2602     GstTagList * xmptaglist)
2603 {
2604   /* Strip out bogus fields */
2605   if (xmptaglist) {
2606     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2607       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2608       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2609     } else {
2610       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2611     }
2612
2613     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2614
2615     /* prioritize native tags using _KEEP mode */
2616     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2617     gst_tag_list_unref (xmptaglist);
2618   }
2619 }
2620
2621 static void
2622 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2623     guint offset)
2624 {
2625   GstByteReader br;
2626   guint8 version;
2627   guint32 flags = 0;
2628   guint i;
2629   guint8 iv_size = 8;
2630   QtDemuxStream *stream;
2631   GstStructure *structure;
2632   QtDemuxCencSampleSetInfo *ss_info = NULL;
2633   const gchar *system_id;
2634   gboolean uses_sub_sample_encryption = FALSE;
2635
2636   if (qtdemux->n_streams == 0)
2637     return;
2638
2639   stream = qtdemux->streams[0];
2640
2641   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2642   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2643     GST_WARNING_OBJECT (qtdemux,
2644         "Attempting PIFF box parsing on an unencrypted stream.");
2645     return;
2646   }
2647
2648   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2649       G_TYPE_STRING, &system_id, NULL);
2650   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2651
2652   stream->protected = TRUE;
2653   stream->protection_scheme_type = FOURCC_cenc;
2654
2655   if (!stream->protection_scheme_info)
2656     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2657
2658   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2659
2660   if (ss_info->default_properties)
2661     gst_structure_free (ss_info->default_properties);
2662
2663   ss_info->default_properties =
2664       gst_structure_new ("application/x-cenc",
2665       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2666
2667   if (ss_info->crypto_info) {
2668     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2669     g_ptr_array_free (ss_info->crypto_info, TRUE);
2670     ss_info->crypto_info = NULL;
2671   }
2672
2673   /* skip UUID */
2674   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2675
2676   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2677     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2678     return;
2679   }
2680
2681   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2682     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2683     return;
2684   }
2685
2686   if ((flags & 0x000001)) {
2687     guint32 algorithm_id = 0;
2688     const guint8 *kid;
2689     GstBuffer *kid_buf;
2690     gboolean is_encrypted = TRUE;
2691
2692     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2693       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2694       return;
2695     }
2696
2697     algorithm_id >>= 8;
2698     if (algorithm_id == 0) {
2699       is_encrypted = FALSE;
2700     } else if (algorithm_id == 1) {
2701       /* FIXME: maybe store this in properties? */
2702       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2703     } else if (algorithm_id == 2) {
2704       /* FIXME: maybe store this in properties? */
2705       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2706     }
2707
2708     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2709       return;
2710
2711     if (!gst_byte_reader_get_data (&br, 16, &kid))
2712       return;
2713
2714     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2715     gst_buffer_fill (kid_buf, 0, kid, 16);
2716     if (ss_info->default_properties)
2717       gst_structure_free (ss_info->default_properties);
2718     ss_info->default_properties =
2719         gst_structure_new ("application/x-cenc",
2720         "iv_size", G_TYPE_UINT, iv_size,
2721         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2722         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2723     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2724         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2725     gst_buffer_unref (kid_buf);
2726   } else if ((flags & 0x000002)) {
2727     uses_sub_sample_encryption = TRUE;
2728   }
2729
2730   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2731     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2732     return;
2733   }
2734
2735   ss_info->crypto_info =
2736       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2737       (GDestroyNotify) qtdemux_gst_structure_free);
2738
2739   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2740     GstStructure *properties;
2741     guint8 *data;
2742     GstBuffer *buf;
2743
2744     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2745     if (properties == NULL) {
2746       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2747       return;
2748     }
2749
2750     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2751       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2752       gst_structure_free (properties);
2753       return;
2754     }
2755     buf = gst_buffer_new_wrapped (data, iv_size);
2756     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2757     gst_buffer_unref (buf);
2758
2759     if (uses_sub_sample_encryption) {
2760       guint16 n_subsamples;
2761
2762       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2763           || n_subsamples == 0) {
2764         GST_ERROR_OBJECT (qtdemux,
2765             "failed to get subsample count for sample %u", i);
2766         gst_structure_free (properties);
2767         return;
2768       }
2769       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2770       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2771         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2772             i);
2773         gst_structure_free (properties);
2774         return;
2775       }
2776       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2777       gst_structure_set (properties,
2778           "subsample_count", G_TYPE_UINT, n_subsamples,
2779           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2780       gst_buffer_unref (buf);
2781     } else {
2782       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2783     }
2784
2785     g_ptr_array_add (ss_info->crypto_info, properties);
2786   }
2787 }
2788
2789 static void
2790 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2791 {
2792   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2793     0x97, 0xA9, 0x42, 0xE8,
2794     0x9C, 0x71, 0x99, 0x94,
2795     0x91, 0xE3, 0xAF, 0xAC
2796   };
2797   static const guint8 playready_uuid[] = {
2798     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2799     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2800   };
2801
2802   static const guint8 piff_sample_encryption_uuid[] = {
2803     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2804     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2805   };
2806
2807   guint offset;
2808
2809   /* counts as header data */
2810   qtdemux->header_size += length;
2811
2812   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2813
2814   if (length <= offset + 16) {
2815     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2816     return;
2817   }
2818
2819   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2820     GstBuffer *buf;
2821     GstTagList *taglist;
2822
2823     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2824         length - offset - 16, NULL);
2825     taglist = gst_tag_list_from_xmp_buffer (buf);
2826     gst_buffer_unref (buf);
2827
2828     /* make sure we have a usable taglist */
2829     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2830
2831     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2832
2833   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2834     int len;
2835     const gunichar2 *s_utf16;
2836     char *contents;
2837
2838     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2839     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2840     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2841     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2842
2843     g_free (contents);
2844
2845     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2846         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2847         (NULL));
2848   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2849     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2850   } else {
2851     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2852         GST_READ_UINT32_LE (buffer + offset),
2853         GST_READ_UINT32_LE (buffer + offset + 4),
2854         GST_READ_UINT32_LE (buffer + offset + 8),
2855         GST_READ_UINT32_LE (buffer + offset + 12));
2856   }
2857 }
2858
2859 static void
2860 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2861 {
2862   GstSidxParser sidx_parser;
2863   GstIsoffParserResult res;
2864   guint consumed;
2865
2866   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2867
2868   res =
2869       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2870       &consumed);
2871   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2872   if (res == GST_ISOFF_QT_PARSER_DONE) {
2873     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2874   }
2875   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2876 }
2877
2878 /* caller verifies at least 8 bytes in buf */
2879 static void
2880 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2881     guint64 * plength, guint32 * pfourcc)
2882 {
2883   guint64 length;
2884   guint32 fourcc;
2885
2886   length = QT_UINT32 (data);
2887   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2888   fourcc = QT_FOURCC (data + 4);
2889   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2890
2891   if (length == 0) {
2892     length = G_MAXUINT64;
2893   } else if (length == 1 && size >= 16) {
2894     /* this means we have an extended size, which is the 64 bit value of
2895      * the next 8 bytes */
2896     length = QT_UINT64 (data + 8);
2897     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2898   }
2899
2900   if (plength)
2901     *plength = length;
2902   if (pfourcc)
2903     *pfourcc = fourcc;
2904 }
2905
2906 static gboolean
2907 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2908 {
2909   guint32 version = 0;
2910   GstClockTime duration = 0;
2911
2912   if (!gst_byte_reader_get_uint32_be (br, &version))
2913     goto failed;
2914
2915   version >>= 24;
2916   if (version == 1) {
2917     if (!gst_byte_reader_get_uint64_be (br, &duration))
2918       goto failed;
2919   } else {
2920     guint32 dur = 0;
2921
2922     if (!gst_byte_reader_get_uint32_be (br, &dur))
2923       goto failed;
2924     duration = dur;
2925   }
2926
2927   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2928   qtdemux->duration = duration;
2929
2930   return TRUE;
2931
2932 failed:
2933   {
2934     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2935     return FALSE;
2936   }
2937 }
2938
2939 static gboolean
2940 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2941     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2942 {
2943   if (!stream->parsed_trex && qtdemux->moov_node) {
2944     GNode *mvex, *trex;
2945     GstByteReader trex_data;
2946
2947     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2948     if (mvex) {
2949       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2950           &trex_data);
2951       while (trex) {
2952         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2953
2954         /* skip version/flags */
2955         if (!gst_byte_reader_skip (&trex_data, 4))
2956           goto next;
2957         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2958           goto next;
2959         if (id != stream->track_id)
2960           goto next;
2961         /* sample description index; ignore */
2962         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2963           goto next;
2964         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2965           goto next;
2966         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2967           goto next;
2968         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2969           goto next;
2970
2971         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2972             "duration %d,  size %d, flags 0x%x", stream->track_id,
2973             dur, size, flags);
2974
2975         stream->parsed_trex = TRUE;
2976         stream->def_sample_duration = dur;
2977         stream->def_sample_size = size;
2978         stream->def_sample_flags = flags;
2979
2980       next:
2981         /* iterate all siblings */
2982         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2983             &trex_data);
2984       }
2985     }
2986   }
2987
2988   *ds_duration = stream->def_sample_duration;
2989   *ds_size = stream->def_sample_size;
2990   *ds_flags = stream->def_sample_flags;
2991
2992   /* even then, above values are better than random ... */
2993   if (G_UNLIKELY (!stream->parsed_trex)) {
2994     GST_WARNING_OBJECT (qtdemux,
2995         "failed to find fragment defaults for stream %d", stream->track_id);
2996     return FALSE;
2997   }
2998
2999   return TRUE;
3000 }
3001
3002 /* This method should be called whenever a more accurate duration might
3003  * have been found. It will update all relevant variables if/where needed
3004  */
3005 static void
3006 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3007 {
3008   guint i;
3009   guint64 movdur;
3010   GstClockTime prevdur;
3011
3012   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3013
3014   if (movdur > qtdemux->duration) {
3015     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3016     GST_DEBUG_OBJECT (qtdemux,
3017         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3018         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3019     qtdemux->duration = movdur;
3020     GST_DEBUG_OBJECT (qtdemux,
3021         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3022         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3023         GST_TIME_ARGS (qtdemux->segment.stop));
3024     if (qtdemux->segment.duration == prevdur) {
3025       /* If the current segment has duration/stop identical to previous duration
3026        * update them also (because they were set at that point in time with
3027        * the wrong duration */
3028       /* We convert the value *from* the timescale version to avoid rounding errors */
3029       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3030       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3031       qtdemux->segment.duration = fixeddur;
3032       qtdemux->segment.stop = fixeddur;
3033     }
3034   }
3035   for (i = 0; i < qtdemux->n_streams; i++) {
3036     QtDemuxStream *stream = qtdemux->streams[i];
3037     if (stream) {
3038       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3039       if (movdur > stream->duration) {
3040         GST_DEBUG_OBJECT (qtdemux,
3041             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3042             GST_TIME_ARGS (duration));
3043         stream->duration = movdur;
3044         if (stream->dummy_segment) {
3045           /* Update all dummy values to new duration */
3046           stream->segments[0].stop_time = duration;
3047           stream->segments[0].duration = duration;
3048           stream->segments[0].media_stop = duration;
3049
3050           /* let downstream know we possibly have a new stop time */
3051           if (stream->segment_index != -1) {
3052             GstClockTime pos;
3053
3054             if (qtdemux->segment.rate >= 0) {
3055               pos = stream->segment.start;
3056             } else {
3057               pos = stream->segment.stop;
3058             }
3059
3060             gst_qtdemux_stream_update_segment (qtdemux, stream,
3061                 stream->segment_index, pos, NULL, NULL);
3062           }
3063         }
3064       }
3065     }
3066   }
3067 }
3068
3069 static gboolean
3070 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3071     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3072     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3073     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3074     gboolean has_tfdt)
3075 {
3076   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3077   guint64 timestamp;
3078   gint32 data_offset = 0;
3079   guint32 flags = 0, first_flags = 0, samples_count = 0;
3080   gint i;
3081   guint8 *data;
3082   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3083   QtDemuxSample *sample;
3084   gboolean ismv = FALSE;
3085   gint64 initial_offset;
3086
3087   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3088       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3089       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3090       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3091
3092   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3093     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3094     return TRUE;
3095   }
3096
3097   /* presence of stss or not can't really tell us much,
3098    * and flags and so on tend to be marginally reliable in these files */
3099   if (stream->subtype == FOURCC_soun) {
3100     GST_DEBUG_OBJECT (qtdemux,
3101         "sound track in fragmented file; marking all keyframes");
3102     stream->all_keyframe = TRUE;
3103   }
3104
3105   if (!gst_byte_reader_skip (trun, 1) ||
3106       !gst_byte_reader_get_uint24_be (trun, &flags))
3107     goto fail;
3108
3109   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3110     goto fail;
3111
3112   if (flags & TR_DATA_OFFSET) {
3113     /* note this is really signed */
3114     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3115       goto fail;
3116     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3117     /* default base offset = first byte of moof */
3118     if (*base_offset == -1) {
3119       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3120       *base_offset = moof_offset;
3121     }
3122     *running_offset = *base_offset + data_offset;
3123   } else {
3124     /* if no offset at all, that would mean data starts at moof start,
3125      * which is a bit wrong and is ismv crappy way, so compensate
3126      * assuming data is in mdat following moof */
3127     if (*base_offset == -1) {
3128       *base_offset = moof_offset + moof_length + 8;
3129       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3130       ismv = TRUE;
3131     }
3132     if (*running_offset == -1)
3133       *running_offset = *base_offset;
3134   }
3135
3136   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3137       *running_offset);
3138   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3139       data_offset, flags, samples_count);
3140
3141   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3142     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3143       GST_DEBUG_OBJECT (qtdemux,
3144           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3145       flags ^= TR_FIRST_SAMPLE_FLAGS;
3146     } else {
3147       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3148         goto fail;
3149       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3150     }
3151   }
3152
3153   /* FIXME ? spec says other bits should also be checked to determine
3154    * entry size (and prefix size for that matter) */
3155   entry_size = 0;
3156   dur_offset = size_offset = 0;
3157   if (flags & TR_SAMPLE_DURATION) {
3158     GST_LOG_OBJECT (qtdemux, "entry duration present");
3159     dur_offset = entry_size;
3160     entry_size += 4;
3161   }
3162   if (flags & TR_SAMPLE_SIZE) {
3163     GST_LOG_OBJECT (qtdemux, "entry size present");
3164     size_offset = entry_size;
3165     entry_size += 4;
3166   }
3167   if (flags & TR_SAMPLE_FLAGS) {
3168     GST_LOG_OBJECT (qtdemux, "entry flags present");
3169     flags_offset = entry_size;
3170     entry_size += 4;
3171   }
3172   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3173     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3174     ct_offset = entry_size;
3175     entry_size += 4;
3176   }
3177
3178   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3179     goto fail;
3180   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3181
3182   if (stream->n_samples + samples_count >=
3183       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3184     goto index_too_big;
3185
3186   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3187       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3188       (stream->n_samples + samples_count) *
3189       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3190
3191   /* create a new array of samples if it's the first sample parsed */
3192   if (stream->n_samples == 0) {
3193     g_assert (stream->samples == NULL);
3194     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3195     /* or try to reallocate it with space enough to insert the new samples */
3196   } else
3197     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3198         stream->n_samples + samples_count);
3199   if (stream->samples == NULL)
3200     goto out_of_memory;
3201
3202   if (qtdemux->fragment_start != -1) {
3203     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3204     qtdemux->fragment_start = -1;
3205   } else {
3206     if (stream->n_samples == 0) {
3207       if (decode_ts > 0) {
3208         timestamp = decode_ts;
3209       } else if (stream->pending_seek != NULL) {
3210         /* if we don't have a timestamp from a tfdt box, we'll use the one
3211          * from the mfra seek table */
3212         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3213             GST_TIME_ARGS (stream->pending_seek->ts));
3214
3215         /* FIXME: this is not fully correct, the timestamp refers to the random
3216          * access sample refered to in the tfra entry, which may not necessarily
3217          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3218         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3219       } else {
3220         timestamp = 0;
3221       }
3222
3223       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3224       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3225           GST_TIME_ARGS (gst_ts));
3226     } else {
3227       /* subsequent fragments extend stream */
3228       timestamp =
3229           stream->samples[stream->n_samples - 1].timestamp +
3230           stream->samples[stream->n_samples - 1].duration;
3231
3232       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3233        * difference (1 sec.) between decode_ts and timestamp, prefer the
3234        * former */
3235       if (has_tfdt && !qtdemux->upstream_format_is_time
3236           && ABSDIFF (decode_ts, timestamp) >
3237           MAX (stream->duration_last_moof / 2,
3238               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3239         GST_INFO_OBJECT (qtdemux,
3240             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3241             ") are significantly different (more than %" GST_TIME_FORMAT
3242             "), using decode_ts",
3243             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3244             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3245             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3246                     MAX (stream->duration_last_moof / 2,
3247                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3248         timestamp = decode_ts;
3249       }
3250
3251       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3252       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3253           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3254     }
3255   }
3256
3257   initial_offset = *running_offset;
3258
3259   sample = stream->samples + stream->n_samples;
3260   for (i = 0; i < samples_count; i++) {
3261     guint32 dur, size, sflags, ct;
3262
3263     /* first read sample data */
3264     if (flags & TR_SAMPLE_DURATION) {
3265       dur = QT_UINT32 (data + dur_offset);
3266     } else {
3267       dur = d_sample_duration;
3268     }
3269     if (flags & TR_SAMPLE_SIZE) {
3270       size = QT_UINT32 (data + size_offset);
3271     } else {
3272       size = d_sample_size;
3273     }
3274     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3275       if (i == 0) {
3276         sflags = first_flags;
3277       } else {
3278         sflags = d_sample_flags;
3279       }
3280     } else if (flags & TR_SAMPLE_FLAGS) {
3281       sflags = QT_UINT32 (data + flags_offset);
3282     } else {
3283       sflags = d_sample_flags;
3284     }
3285     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3286       ct = QT_UINT32 (data + ct_offset);
3287     } else {
3288       ct = 0;
3289     }
3290     data += entry_size;
3291
3292     /* fill the sample information */
3293     sample->offset = *running_offset;
3294     sample->pts_offset = ct;
3295     sample->size = size;
3296     sample->timestamp = timestamp;
3297     sample->duration = dur;
3298     /* sample-is-difference-sample */
3299     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3300      * now idea how it relates to bitfield other than massive LE/BE confusion */
3301     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3302     *running_offset += size;
3303     timestamp += dur;
3304     stream->duration_moof += dur;
3305     sample++;
3306   }
3307
3308   /* Update total duration if needed */
3309   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3310
3311   /* Pre-emptively figure out size of mdat based on trun information.
3312    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3313    * size, else we will still be able to use this when dealing with gap'ed
3314    * input */
3315   qtdemux->mdatleft = *running_offset - initial_offset;
3316   qtdemux->mdatoffset = initial_offset;
3317   qtdemux->mdatsize = qtdemux->mdatleft;
3318
3319   stream->n_samples += samples_count;
3320   stream->n_samples_moof += samples_count;
3321
3322   if (stream->pending_seek != NULL)
3323     stream->pending_seek = NULL;
3324
3325   return TRUE;
3326
3327 fail:
3328   {
3329     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3330     return FALSE;
3331   }
3332 out_of_memory:
3333   {
3334     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3335         stream->n_samples);
3336     return FALSE;
3337   }
3338 index_too_big:
3339   {
3340     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3341         "be larger than %uMB (broken file?)", stream->n_samples,
3342         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3343     return FALSE;
3344   }
3345 }
3346
3347 /* find stream with @id */
3348 static inline QtDemuxStream *
3349 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3350 {
3351   QtDemuxStream *stream;
3352   gint i;
3353
3354   /* check */
3355   if (G_UNLIKELY (!id)) {
3356     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3357     return NULL;
3358   }
3359
3360   /* try to get it fast and simple */
3361   if (G_LIKELY (id <= qtdemux->n_streams)) {
3362     stream = qtdemux->streams[id - 1];
3363     if (G_LIKELY (stream->track_id == id))
3364       return stream;
3365   }
3366
3367   /* linear search otherwise */
3368   for (i = 0; i < qtdemux->n_streams; i++) {
3369     stream = qtdemux->streams[i];
3370     if (stream->track_id == id)
3371       return stream;
3372   }
3373   if (qtdemux->mss_mode) {
3374     /* mss should have only 1 stream anyway */
3375     return qtdemux->streams[0];
3376   }
3377
3378   return NULL;
3379 }
3380
3381 static gboolean
3382 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3383     guint32 * fragment_number)
3384 {
3385   if (!gst_byte_reader_skip (mfhd, 4))
3386     goto fail;
3387   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3388     goto fail;
3389   return TRUE;
3390 fail:
3391   {
3392     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3393     return FALSE;
3394   }
3395 }
3396
3397 static gboolean
3398 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3399     QtDemuxStream ** stream, guint32 * default_sample_duration,
3400     guint32 * default_sample_size, guint32 * default_sample_flags,
3401     gint64 * base_offset)
3402 {
3403   guint32 flags = 0;
3404   guint32 track_id = 0;
3405
3406   if (!gst_byte_reader_skip (tfhd, 1) ||
3407       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3408     goto invalid_track;
3409
3410   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3411     goto invalid_track;
3412
3413   *stream = qtdemux_find_stream (qtdemux, track_id);
3414   if (G_UNLIKELY (!*stream))
3415     goto unknown_stream;
3416
3417   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3418     *base_offset = qtdemux->moof_offset;
3419
3420   if (flags & TF_BASE_DATA_OFFSET)
3421     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3422       goto invalid_track;
3423
3424   /* obtain stream defaults */
3425   qtdemux_parse_trex (qtdemux, *stream,
3426       default_sample_duration, default_sample_size, default_sample_flags);
3427
3428   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3429   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3430     if (!gst_byte_reader_skip (tfhd, 4))
3431       goto invalid_track;
3432
3433   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3434     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3435       goto invalid_track;
3436
3437   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3438     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3439       goto invalid_track;
3440
3441   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3442     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3443       goto invalid_track;
3444
3445   return TRUE;
3446
3447 invalid_track:
3448   {
3449     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3450     return FALSE;
3451   }
3452 unknown_stream:
3453   {
3454     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3455     return TRUE;
3456   }
3457 }
3458
3459 static gboolean
3460 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3461     guint64 * decode_time)
3462 {
3463   guint32 version = 0;
3464
3465   if (!gst_byte_reader_get_uint32_be (br, &version))
3466     return FALSE;
3467
3468   version >>= 24;
3469   if (version == 1) {
3470     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3471       goto failed;
3472   } else {
3473     guint32 dec_time = 0;
3474     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3475       goto failed;
3476     *decode_time = dec_time;
3477   }
3478
3479   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3480       *decode_time);
3481
3482   return TRUE;
3483
3484 failed:
3485   {
3486     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3487     return FALSE;
3488   }
3489 }
3490
3491 /* Returns a pointer to a GstStructure containing the properties of
3492  * the stream sample identified by @sample_index. The caller must unref
3493  * the returned object after use. Returns NULL if unsuccessful. */
3494 static GstStructure *
3495 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3496     QtDemuxStream * stream, guint sample_index)
3497 {
3498   QtDemuxCencSampleSetInfo *info = NULL;
3499
3500   g_return_val_if_fail (stream != NULL, NULL);
3501   g_return_val_if_fail (stream->protected, NULL);
3502   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3503
3504   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3505
3506   /* Currently, cenc properties for groups of samples are not supported, so
3507    * simply return a copy of the default sample properties */
3508   return gst_structure_copy (info->default_properties);
3509 }
3510
3511 /* Parses the sizes of sample auxiliary information contained within a stream,
3512  * as given in a saiz box. Returns array of sample_count guint8 size values,
3513  * or NULL on failure */
3514 static guint8 *
3515 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3516     GstByteReader * br, guint32 * sample_count)
3517 {
3518   guint32 flags = 0;
3519   guint8 *info_sizes;
3520   guint8 default_info_size;
3521
3522   g_return_val_if_fail (qtdemux != NULL, NULL);
3523   g_return_val_if_fail (stream != NULL, NULL);
3524   g_return_val_if_fail (br != NULL, NULL);
3525   g_return_val_if_fail (sample_count != NULL, NULL);
3526
3527   if (!gst_byte_reader_get_uint32_be (br, &flags))
3528     return NULL;
3529
3530   if (flags & 0x1) {
3531     /* aux_info_type and aux_info_type_parameter are ignored */
3532     if (!gst_byte_reader_skip (br, 8))
3533       return NULL;
3534   }
3535
3536   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3537     return NULL;
3538   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3539
3540   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3541     return NULL;
3542   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3543
3544
3545   if (default_info_size == 0) {
3546     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3547       return NULL;
3548     }
3549   } else {
3550     info_sizes = g_new (guint8, *sample_count);
3551     memset (info_sizes, default_info_size, *sample_count);
3552   }
3553
3554   return info_sizes;
3555 }
3556
3557 /* Parses the offset of sample auxiliary information contained within a stream,
3558  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3559 static gboolean
3560 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3561     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3562     guint64 * offset)
3563 {
3564   guint8 version = 0;
3565   guint32 flags = 0;
3566   guint32 aux_info_type = 0;
3567   guint32 aux_info_type_parameter = 0;
3568   guint32 entry_count;
3569   guint32 off_32;
3570   guint64 off_64;
3571   const guint8 *aux_info_type_data = NULL;
3572
3573   g_return_val_if_fail (qtdemux != NULL, FALSE);
3574   g_return_val_if_fail (stream != NULL, FALSE);
3575   g_return_val_if_fail (br != NULL, FALSE);
3576   g_return_val_if_fail (offset != NULL, FALSE);
3577
3578   if (!gst_byte_reader_get_uint8 (br, &version))
3579     return FALSE;
3580
3581   if (!gst_byte_reader_get_uint24_be (br, &flags))
3582     return FALSE;
3583
3584   if (flags & 0x1) {
3585
3586     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3587       return FALSE;
3588     aux_info_type = QT_FOURCC (aux_info_type_data);
3589
3590     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3591       return FALSE;
3592   } else if (stream->protected) {
3593     aux_info_type = stream->protection_scheme_type;
3594   } else {
3595     aux_info_type = CUR_STREAM (stream)->fourcc;
3596   }
3597
3598   if (info_type)
3599     *info_type = aux_info_type;
3600   if (info_type_parameter)
3601     *info_type_parameter = aux_info_type_parameter;
3602
3603   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3604       "aux_info_type_parameter:  %#06x",
3605       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3606
3607   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3608     return FALSE;
3609
3610   if (entry_count != 1) {
3611     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3612     return FALSE;
3613   }
3614
3615   if (version == 0) {
3616     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3617       return FALSE;
3618     *offset = (guint64) off_32;
3619   } else {
3620     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3621       return FALSE;
3622     *offset = off_64;
3623   }
3624
3625   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3626   return TRUE;
3627 }
3628
3629 static void
3630 qtdemux_gst_structure_free (GstStructure * gststructure)
3631 {
3632   if (gststructure) {
3633     gst_structure_free (gststructure);
3634   }
3635 }
3636
3637 /* Parses auxiliary information relating to samples protected using Common
3638  * Encryption (cenc); the format of this information is defined in
3639  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3640 static gboolean
3641 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3642     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3643 {
3644   QtDemuxCencSampleSetInfo *ss_info = NULL;
3645   guint8 size;
3646   gint i;
3647   GPtrArray *old_crypto_info = NULL;
3648   guint old_entries = 0;
3649
3650   g_return_val_if_fail (qtdemux != NULL, FALSE);
3651   g_return_val_if_fail (stream != NULL, FALSE);
3652   g_return_val_if_fail (br != NULL, FALSE);
3653   g_return_val_if_fail (stream->protected, FALSE);
3654   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3655
3656   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3657
3658   if (ss_info->crypto_info) {
3659     old_crypto_info = ss_info->crypto_info;
3660     /* Count number of non-null entries remaining at the tail end */
3661     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3662       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3663         break;
3664       old_entries++;
3665     }
3666   }
3667
3668   ss_info->crypto_info =
3669       g_ptr_array_new_full (sample_count + old_entries,
3670       (GDestroyNotify) qtdemux_gst_structure_free);
3671
3672   /* We preserve old entries because we parse the next moof in advance
3673    * of consuming all samples from the previous moof, and otherwise
3674    * we'd discard the corresponding crypto info for the samples
3675    * from the previous fragment. */
3676   if (old_entries) {
3677     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3678         old_entries);
3679     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3680       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3681               i));
3682       g_ptr_array_index (old_crypto_info, i) = NULL;
3683     }
3684   }
3685
3686   if (old_crypto_info) {
3687     /* Everything now belongs to the new array */
3688     g_ptr_array_free (old_crypto_info, TRUE);
3689   }
3690
3691   for (i = 0; i < sample_count; ++i) {
3692     GstStructure *properties;
3693     guint16 n_subsamples = 0;
3694     guint8 *data;
3695     guint iv_size;
3696     GstBuffer *buf;
3697
3698     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3699     if (properties == NULL) {
3700       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3701       return FALSE;
3702     }
3703     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3704       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3705       gst_structure_free (properties);
3706       return FALSE;
3707     }
3708     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3709       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3710       gst_structure_free (properties);
3711       return FALSE;
3712     }
3713     buf = gst_buffer_new_wrapped (data, iv_size);
3714     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3715     gst_buffer_unref (buf);
3716     size = info_sizes[i];
3717     if (size > iv_size) {
3718       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3719           || !(n_subsamples > 0)) {
3720         gst_structure_free (properties);
3721         GST_ERROR_OBJECT (qtdemux,
3722             "failed to get subsample count for sample %u", i);
3723         return FALSE;
3724       }
3725       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3726       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3727         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3728             i);
3729         gst_structure_free (properties);
3730         return FALSE;
3731       }
3732       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3733       if (!buf) {
3734         gst_structure_free (properties);
3735         return FALSE;
3736       }
3737       gst_structure_set (properties,
3738           "subsample_count", G_TYPE_UINT, n_subsamples,
3739           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3740       gst_buffer_unref (buf);
3741     } else {
3742       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3743     }
3744     g_ptr_array_add (ss_info->crypto_info, properties);
3745   }
3746   return TRUE;
3747 }
3748
3749 /* Converts a UUID in raw byte form to a string representation, as defined in
3750  * RFC 4122. The caller takes ownership of the returned string and is
3751  * responsible for freeing it after use. */
3752 static gchar *
3753 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3754 {
3755   const guint8 *uuid = (const guint8 *) uuid_bytes;
3756
3757   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3758       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3759       uuid[0], uuid[1], uuid[2], uuid[3],
3760       uuid[4], uuid[5], uuid[6], uuid[7],
3761       uuid[8], uuid[9], uuid[10], uuid[11],
3762       uuid[12], uuid[13], uuid[14], uuid[15]);
3763 }
3764
3765 /* Parses a Protection System Specific Header box (pssh), as defined in the
3766  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3767  * information needed by a specific content protection system in order to
3768  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3769  * otherwise. */
3770 static gboolean
3771 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3772 {
3773   gchar *sysid_string;
3774   guint32 pssh_size = QT_UINT32 (node->data);
3775   GstBuffer *pssh = NULL;
3776   GstEvent *event = NULL;
3777   guint32 parent_box_type;
3778   gint i;
3779
3780   if (G_UNLIKELY (pssh_size < 32U)) {
3781     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3782     return FALSE;
3783   }
3784
3785   sysid_string =
3786       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3787
3788   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3789
3790   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3791   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3792       gst_buffer_get_size (pssh));
3793
3794   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3795
3796   /* Push an event containing the pssh box onto the queues of all streams. */
3797   event = gst_event_new_protection (sysid_string, pssh,
3798       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3799   for (i = 0; i < qtdemux->n_streams; ++i) {
3800     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3801         gst_event_ref (event));
3802   }
3803   g_free (sysid_string);
3804   gst_event_unref (event);
3805   gst_buffer_unref (pssh);
3806   return TRUE;
3807 }
3808
3809 static gboolean
3810 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3811     guint64 moof_offset, QtDemuxStream * stream)
3812 {
3813   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3814   GNode *uuid_node;
3815   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3816   GNode *saiz_node, *saio_node, *pssh_node;
3817   GstByteReader saiz_data, saio_data;
3818   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3819   gint64 base_offset, running_offset;
3820   guint32 frag_num;
3821
3822   /* NOTE @stream ignored */
3823
3824   moof_node = g_node_new ((guint8 *) buffer);
3825   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3826   qtdemux_node_dump (qtdemux, moof_node);
3827
3828   /* Get fragment number from mfhd and check it's valid */
3829   mfhd_node =
3830       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3831   if (mfhd_node == NULL)
3832     goto missing_mfhd;
3833   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3834     goto fail;
3835   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3836
3837   /* unknown base_offset to start with */
3838   base_offset = running_offset = -1;
3839   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3840   while (traf_node) {
3841     guint64 decode_time = 0;
3842
3843     /* Fragment Header node */
3844     tfhd_node =
3845         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3846         &tfhd_data);
3847     if (!tfhd_node)
3848       goto missing_tfhd;
3849     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3850             &ds_size, &ds_flags, &base_offset))
3851       goto missing_tfhd;
3852
3853     /* The following code assumes at most a single set of sample auxiliary
3854      * data in the fragment (consisting of a saiz box and a corresponding saio
3855      * box); in theory, however, there could be multiple sets of sample
3856      * auxiliary data in a fragment. */
3857     saiz_node =
3858         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3859         &saiz_data);
3860     if (saiz_node) {
3861       guint32 info_type = 0;
3862       guint64 offset = 0;
3863       guint32 info_type_parameter = 0;
3864
3865       g_free (qtdemux->cenc_aux_info_sizes);
3866
3867       qtdemux->cenc_aux_info_sizes =
3868           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3869           &qtdemux->cenc_aux_sample_count);
3870       if (qtdemux->cenc_aux_info_sizes == NULL) {
3871         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3872         goto fail;
3873       }
3874       saio_node =
3875           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3876           &saio_data);
3877       if (!saio_node) {
3878         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3879         g_free (qtdemux->cenc_aux_info_sizes);
3880         qtdemux->cenc_aux_info_sizes = NULL;
3881         goto fail;
3882       }
3883
3884       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3885                   &info_type, &info_type_parameter, &offset))) {
3886         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3887         g_free (qtdemux->cenc_aux_info_sizes);
3888         qtdemux->cenc_aux_info_sizes = NULL;
3889         goto fail;
3890       }
3891       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3892         offset += (guint64) (base_offset - qtdemux->moof_offset);
3893       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3894         GstByteReader br;
3895         if (offset > length) {
3896           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3897           qtdemux->cenc_aux_info_offset = offset;
3898         } else {
3899           gst_byte_reader_init (&br, buffer + offset, length - offset);
3900           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3901                   qtdemux->cenc_aux_info_sizes,
3902                   qtdemux->cenc_aux_sample_count)) {
3903             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3904             g_free (qtdemux->cenc_aux_info_sizes);
3905             qtdemux->cenc_aux_info_sizes = NULL;
3906             goto fail;
3907           }
3908         }
3909       }
3910     }
3911
3912     tfdt_node =
3913         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3914         &tfdt_data);
3915     if (tfdt_node) {
3916       /* We'll use decode_time to interpolate timestamps
3917        * in case the input timestamps are missing */
3918       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3919
3920       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3921           " (%" GST_TIME_FORMAT ")", decode_time,
3922           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3923
3924       /* Discard the fragment buffer timestamp info to avoid using it.
3925        * Rely on tfdt instead as it is more accurate than the timestamp
3926        * that is fetched from a manifest/playlist and is usually
3927        * less accurate. */
3928       qtdemux->fragment_start = -1;
3929     }
3930
3931     if (G_UNLIKELY (!stream)) {
3932       /* we lost track of offset, we'll need to regain it,
3933        * but can delay complaining until later or avoid doing so altogether */
3934       base_offset = -2;
3935       goto next;
3936     }
3937     if (G_UNLIKELY (base_offset < -1))
3938       goto lost_offset;
3939
3940     if (qtdemux->upstream_format_is_time)
3941       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3942
3943     /* initialise moof sample data */
3944     stream->n_samples_moof = 0;
3945     stream->duration_last_moof = stream->duration_moof;
3946     stream->duration_moof = 0;
3947
3948     /* Track Run node */
3949     trun_node =
3950         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3951         &trun_data);
3952     while (trun_node) {
3953       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3954           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3955           &running_offset, decode_time, (tfdt_node != NULL));
3956       /* iterate all siblings */
3957       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3958           &trun_data);
3959     }
3960
3961     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3962     if (uuid_node) {
3963       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3964       guint32 box_length = QT_UINT32 (uuid_buffer);
3965
3966       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3967     }
3968
3969     /* if no new base_offset provided for next traf,
3970      * base is end of current traf */
3971     base_offset = running_offset;
3972     running_offset = -1;
3973
3974     if (stream->n_samples_moof && stream->duration_moof)
3975       stream->new_caps = TRUE;
3976
3977   next:
3978     /* iterate all siblings */
3979     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3980   }
3981
3982   /* parse any protection system info */
3983   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3984   while (pssh_node) {
3985     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3986     qtdemux_parse_pssh (qtdemux, pssh_node);
3987     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3988   }
3989
3990   g_node_destroy (moof_node);
3991   return TRUE;
3992
3993 missing_tfhd:
3994   {
3995     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3996     goto fail;
3997   }
3998 missing_mfhd:
3999   {
4000     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4001     goto fail;
4002   }
4003 lost_offset:
4004   {
4005     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4006     goto fail;
4007   }
4008 fail:
4009   {
4010     g_node_destroy (moof_node);
4011     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4012         (_("This file is corrupt and cannot be played.")), (NULL));
4013     return FALSE;
4014   }
4015 }
4016
4017 #if 0
4018 /* might be used if some day we actually use mfra & co
4019  * for random access to fragments,
4020  * but that will require quite some modifications and much less relying
4021  * on a sample array */
4022 #endif
4023
4024 static gboolean
4025 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4026 {
4027   QtDemuxStream *stream;
4028   guint32 ver_flags, track_id, len, num_entries, i;
4029   guint value_size, traf_size, trun_size, sample_size;
4030   guint64 time = 0, moof_offset = 0;
4031 #if 0
4032   GstBuffer *buf = NULL;
4033   GstFlowReturn ret;
4034 #endif
4035   GstByteReader tfra;
4036
4037   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4038
4039   if (!gst_byte_reader_skip (&tfra, 8))
4040     return FALSE;
4041
4042   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4043     return FALSE;
4044
4045   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4046       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4047       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4048     return FALSE;
4049
4050   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4051
4052   stream = qtdemux_find_stream (qtdemux, track_id);
4053   if (stream == NULL)
4054     goto unknown_trackid;
4055
4056   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4057   sample_size = (len & 3) + 1;
4058   trun_size = ((len & 12) >> 2) + 1;
4059   traf_size = ((len & 48) >> 4) + 1;
4060
4061   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4062       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4063
4064   if (num_entries == 0)
4065     goto no_samples;
4066
4067   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4068           value_size + value_size + traf_size + trun_size + sample_size))
4069     goto corrupt_file;
4070
4071   g_free (stream->ra_entries);
4072   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4073   stream->n_ra_entries = num_entries;
4074
4075   for (i = 0; i < num_entries; i++) {
4076     qt_atom_parser_get_offset (&tfra, value_size, &time);
4077     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4078     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4079     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4080     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4081
4082     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4083
4084     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4085         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4086
4087     stream->ra_entries[i].ts = time;
4088     stream->ra_entries[i].moof_offset = moof_offset;
4089
4090     /* don't want to go through the entire file and read all moofs at startup */
4091 #if 0
4092     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4093     if (ret != GST_FLOW_OK)
4094       goto corrupt_file;
4095     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4096         moof_offset, stream);
4097     gst_buffer_unref (buf);
4098 #endif
4099   }
4100
4101   check_update_duration (qtdemux, time);
4102
4103   return TRUE;
4104
4105 /* ERRORS */
4106 unknown_trackid:
4107   {
4108     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4109     return FALSE;
4110   }
4111 corrupt_file:
4112   {
4113     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4114     return FALSE;
4115   }
4116 no_samples:
4117   {
4118     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4119     return FALSE;
4120   }
4121 }
4122
4123 static gboolean
4124 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4125 {
4126   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4127   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4128   GstBuffer *mfro = NULL, *mfra = NULL;
4129   GstFlowReturn flow;
4130   gboolean ret = FALSE;
4131   GNode *mfra_node, *tfra_node;
4132   guint64 mfra_offset = 0;
4133   guint32 fourcc, mfra_size;
4134   gint64 len;
4135
4136   /* query upstream size in bytes */
4137   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4138     goto size_query_failed;
4139
4140   /* mfro box should be at the very end of the file */
4141   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4142   if (flow != GST_FLOW_OK)
4143     goto exit;
4144
4145   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4146
4147   fourcc = QT_FOURCC (mfro_map.data + 4);
4148   if (fourcc != FOURCC_mfro)
4149     goto exit;
4150
4151   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4152   if (mfro_map.size < 16)
4153     goto invalid_mfro_size;
4154
4155   mfra_size = QT_UINT32 (mfro_map.data + 12);
4156   if (mfra_size >= len)
4157     goto invalid_mfra_size;
4158
4159   mfra_offset = len - mfra_size;
4160
4161   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4162       mfra_offset, mfra_size);
4163
4164   /* now get and parse mfra box */
4165   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4166   if (flow != GST_FLOW_OK)
4167     goto broken_file;
4168
4169   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4170
4171   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4172   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4173
4174   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4175
4176   while (tfra_node) {
4177     qtdemux_parse_tfra (qtdemux, tfra_node);
4178     /* iterate all siblings */
4179     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4180   }
4181   g_node_destroy (mfra_node);
4182
4183   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4184   ret = TRUE;
4185
4186 exit:
4187
4188   if (mfro) {
4189     if (mfro_map.memory != NULL)
4190       gst_buffer_unmap (mfro, &mfro_map);
4191     gst_buffer_unref (mfro);
4192   }
4193   if (mfra) {
4194     if (mfra_map.memory != NULL)
4195       gst_buffer_unmap (mfra, &mfra_map);
4196     gst_buffer_unref (mfra);
4197   }
4198   return ret;
4199
4200 /* ERRORS */
4201 size_query_failed:
4202   {
4203     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4204     goto exit;
4205   }
4206 invalid_mfro_size:
4207   {
4208     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4209     goto exit;
4210   }
4211 invalid_mfra_size:
4212   {
4213     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4214     goto exit;
4215   }
4216 broken_file:
4217   {
4218     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4219     goto exit;
4220   }
4221 }
4222
4223 static guint64
4224 add_offset (guint64 offset, guint64 advance)
4225 {
4226   /* Avoid 64-bit overflow by clamping */
4227   if (offset > G_MAXUINT64 - advance)
4228     return G_MAXUINT64;
4229   return offset + advance;
4230 }
4231
4232 static GstFlowReturn
4233 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4234 {
4235   guint64 length = 0;
4236   guint32 fourcc = 0;
4237   GstBuffer *buf = NULL;
4238   GstFlowReturn ret = GST_FLOW_OK;
4239   guint64 cur_offset = qtdemux->offset;
4240   GstMapInfo map;
4241
4242   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4243   if (G_UNLIKELY (ret != GST_FLOW_OK))
4244     goto beach;
4245   gst_buffer_map (buf, &map, GST_MAP_READ);
4246   if (G_LIKELY (map.size >= 8))
4247     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4248   gst_buffer_unmap (buf, &map);
4249   gst_buffer_unref (buf);
4250
4251   /* maybe we already got most we needed, so only consider this eof */
4252   if (G_UNLIKELY (length == 0)) {
4253     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4254         (_("Invalid atom size.")),
4255         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4256             GST_FOURCC_ARGS (fourcc)));
4257     ret = GST_FLOW_EOS;
4258     goto beach;
4259   }
4260
4261   switch (fourcc) {
4262     case FOURCC_moof:
4263       /* record for later parsing when needed */
4264       if (!qtdemux->moof_offset) {
4265         qtdemux->moof_offset = qtdemux->offset;
4266       }
4267       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4268         /* FIXME */
4269       } else {
4270         qtdemux->offset += length;      /* skip moof and keep going */
4271       }
4272       if (qtdemux->got_moov) {
4273         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4274         ret = GST_FLOW_EOS;
4275         goto beach;
4276       }
4277       break;
4278     case FOURCC_mdat:
4279     case FOURCC_free:
4280     case FOURCC_wide:
4281     case FOURCC_PICT:
4282     case FOURCC_pnot:
4283     {
4284       GST_LOG_OBJECT (qtdemux,
4285           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4286           GST_FOURCC_ARGS (fourcc), cur_offset);
4287       qtdemux->offset = add_offset (qtdemux->offset, length);
4288       break;
4289     }
4290     case FOURCC_moov:
4291     {
4292       GstBuffer *moov = NULL;
4293
4294       if (qtdemux->got_moov) {
4295         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4296         qtdemux->offset = add_offset (qtdemux->offset, length);
4297         goto beach;
4298       }
4299
4300       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4301       if (ret != GST_FLOW_OK)
4302         goto beach;
4303       gst_buffer_map (moov, &map, GST_MAP_READ);
4304
4305       if (length != map.size) {
4306         /* Some files have a 'moov' atom at the end of the file which contains
4307          * a terminal 'free' atom where the body of the atom is missing.
4308          * Check for, and permit, this special case.
4309          */
4310         if (map.size >= 8) {
4311           guint8 *final_data = map.data + (map.size - 8);
4312           guint32 final_length = QT_UINT32 (final_data);
4313           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4314
4315           if (final_fourcc == FOURCC_free
4316               && map.size + final_length - 8 == length) {
4317             /* Ok, we've found that special case. Allocate a new buffer with
4318              * that free atom actually present. */
4319             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4320             gst_buffer_fill (newmoov, 0, map.data, map.size);
4321             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4322             gst_buffer_unmap (moov, &map);
4323             gst_buffer_unref (moov);
4324             moov = newmoov;
4325             gst_buffer_map (moov, &map, GST_MAP_READ);
4326           }
4327         }
4328       }
4329
4330       if (length != map.size) {
4331         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4332             (_("This file is incomplete and cannot be played.")),
4333             ("We got less than expected (received %" G_GSIZE_FORMAT
4334                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4335                 (guint) length, cur_offset));
4336         gst_buffer_unmap (moov, &map);
4337         gst_buffer_unref (moov);
4338         ret = GST_FLOW_ERROR;
4339         goto beach;
4340       }
4341       qtdemux->offset += length;
4342
4343       qtdemux_parse_moov (qtdemux, map.data, length);
4344       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4345
4346       qtdemux_parse_tree (qtdemux);
4347       if (qtdemux->moov_node_compressed) {
4348         g_node_destroy (qtdemux->moov_node_compressed);
4349         g_free (qtdemux->moov_node->data);
4350       }
4351       qtdemux->moov_node_compressed = NULL;
4352       g_node_destroy (qtdemux->moov_node);
4353       qtdemux->moov_node = NULL;
4354       gst_buffer_unmap (moov, &map);
4355       gst_buffer_unref (moov);
4356       qtdemux->got_moov = TRUE;
4357
4358       break;
4359     }
4360     case FOURCC_ftyp:
4361     {
4362       GstBuffer *ftyp = NULL;
4363
4364       /* extract major brand; might come in handy for ISO vs QT issues */
4365       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4366       if (ret != GST_FLOW_OK)
4367         goto beach;
4368       qtdemux->offset += length;
4369       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4370       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4371       gst_buffer_unmap (ftyp, &map);
4372       gst_buffer_unref (ftyp);
4373       break;
4374     }
4375     case FOURCC_uuid:
4376     {
4377       GstBuffer *uuid = NULL;
4378
4379       /* uuid are extension atoms */
4380       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4381       if (ret != GST_FLOW_OK)
4382         goto beach;
4383       qtdemux->offset += length;
4384       gst_buffer_map (uuid, &map, GST_MAP_READ);
4385       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4386       gst_buffer_unmap (uuid, &map);
4387       gst_buffer_unref (uuid);
4388       break;
4389     }
4390     case FOURCC_sidx:
4391     {
4392       GstBuffer *sidx = NULL;
4393       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4394       if (ret != GST_FLOW_OK)
4395         goto beach;
4396       qtdemux->offset += length;
4397       gst_buffer_map (sidx, &map, GST_MAP_READ);
4398       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4399       gst_buffer_unmap (sidx, &map);
4400       gst_buffer_unref (sidx);
4401       break;
4402     }
4403     default:
4404     {
4405       GstBuffer *unknown = NULL;
4406
4407       GST_LOG_OBJECT (qtdemux,
4408           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4409           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4410           cur_offset);
4411       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4412       if (ret != GST_FLOW_OK)
4413         goto beach;
4414       gst_buffer_map (unknown, &map, GST_MAP_READ);
4415       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4416       gst_buffer_unmap (unknown, &map);
4417       gst_buffer_unref (unknown);
4418       qtdemux->offset += length;
4419       break;
4420     }
4421   }
4422
4423 beach:
4424   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4425     /* digested all data, show what we have */
4426     qtdemux_prepare_streams (qtdemux);
4427     ret = qtdemux_expose_streams (qtdemux);
4428
4429     qtdemux->state = QTDEMUX_STATE_MOVIE;
4430     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4431         qtdemux->state);
4432     return ret;
4433   }
4434   return ret;
4435 }
4436
4437 /* Seeks to the previous keyframe of the indexed stream and
4438  * aligns other streams with respect to the keyframe timestamp
4439  * of indexed stream. Only called in case of Reverse Playback
4440  */
4441 static GstFlowReturn
4442 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4443 {
4444   guint8 n = 0;
4445   guint32 seg_idx = 0, k_index = 0;
4446   guint32 ref_seg_idx, ref_k_index;
4447   GstClockTime k_pos = 0, last_stop = 0;
4448   QtDemuxSegment *seg = NULL;
4449   QtDemuxStream *ref_str = NULL;
4450   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4451   guint64 target_ts;
4452
4453   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4454    * and finally align all the other streams on that timestamp with their
4455    * respective keyframes */
4456   for (n = 0; n < qtdemux->n_streams; n++) {
4457     QtDemuxStream *str = qtdemux->streams[n];
4458
4459     /* No candidate yet, take the first stream */
4460     if (!ref_str) {
4461       ref_str = str;
4462       continue;
4463     }
4464
4465     /* So that stream has a segment, we prefer video streams */
4466     if (str->subtype == FOURCC_vide) {
4467       ref_str = str;
4468       break;
4469     }
4470   }
4471
4472   if (G_UNLIKELY (!ref_str)) {
4473     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4474     goto eos;
4475   }
4476
4477   if (G_UNLIKELY (!ref_str->from_sample)) {
4478     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4479     goto eos;
4480   }
4481
4482   /* So that stream has been playing from from_sample to to_sample. We will
4483    * get the timestamp of the previous sample and search for a keyframe before
4484    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4485   if (ref_str->subtype == FOURCC_vide) {
4486     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4487         ref_str->from_sample - 1, FALSE);
4488   } else {
4489     if (ref_str->from_sample >= 10)
4490       k_index = ref_str->from_sample - 10;
4491     else
4492       k_index = 0;
4493   }
4494
4495   target_ts =
4496       ref_str->samples[k_index].timestamp +
4497       ref_str->samples[k_index].pts_offset;
4498
4499   /* get current segment for that stream */
4500   seg = &ref_str->segments[ref_str->segment_index];
4501   /* Use segment start in original timescale for comparisons */
4502   seg_media_start_mov = seg->trak_media_start;
4503
4504   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4505       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4506       k_index, target_ts, seg_media_start_mov,
4507       GST_TIME_ARGS (seg->media_start));
4508
4509   /* Crawl back through segments to find the one containing this I frame */
4510   while (target_ts < seg_media_start_mov) {
4511     GST_DEBUG_OBJECT (qtdemux,
4512         "keyframe position (sample %u) is out of segment %u " " target %"
4513         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4514         ref_str->segment_index, target_ts, seg_media_start_mov);
4515
4516     if (G_UNLIKELY (!ref_str->segment_index)) {
4517       /* Reached first segment, let's consider it's EOS */
4518       goto eos;
4519     }
4520     ref_str->segment_index--;
4521     seg = &ref_str->segments[ref_str->segment_index];
4522     /* Use segment start in original timescale for comparisons */
4523     seg_media_start_mov = seg->trak_media_start;
4524   }
4525   /* Calculate time position of the keyframe and where we should stop */
4526   k_pos =
4527       QTSTREAMTIME_TO_GSTTIME (ref_str,
4528       target_ts - seg->trak_media_start) + seg->time;
4529   last_stop =
4530       QTSTREAMTIME_TO_GSTTIME (ref_str,
4531       ref_str->samples[ref_str->from_sample].timestamp -
4532       seg->trak_media_start) + seg->time;
4533
4534   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4535       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4536       k_index, GST_TIME_ARGS (k_pos));
4537
4538   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4539   qtdemux->segment.position = last_stop;
4540   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4541       GST_TIME_ARGS (last_stop));
4542
4543   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4544     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4545     goto eos;
4546   }
4547
4548   ref_seg_idx = ref_str->segment_index;
4549   ref_k_index = k_index;
4550
4551   /* Align them all on this */
4552   for (n = 0; n < qtdemux->n_streams; n++) {
4553     guint32 index = 0;
4554     GstClockTime seg_time = 0;
4555     QtDemuxStream *str = qtdemux->streams[n];
4556
4557     /* aligning reference stream again might lead to backing up to yet another
4558      * keyframe (due to timestamp rounding issues),
4559      * potentially putting more load on downstream; so let's try to avoid */
4560     if (str == ref_str) {
4561       seg_idx = ref_seg_idx;
4562       seg = &str->segments[seg_idx];
4563       k_index = ref_k_index;
4564       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4565           "sample at index %d", n, ref_str->segment_index, k_index);
4566     } else {
4567       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4568       GST_DEBUG_OBJECT (qtdemux,
4569           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4570           seg_idx, GST_TIME_ARGS (k_pos));
4571
4572       /* get segment and time in the segment */
4573       seg = &str->segments[seg_idx];
4574       seg_time = k_pos - seg->time;
4575
4576       /* get the media time in the segment.
4577        * No adjustment for empty "filler" segments */
4578       if (seg->media_start != GST_CLOCK_TIME_NONE)
4579         seg_time += seg->media_start;
4580
4581       /* get the index of the sample with media time */
4582       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4583       GST_DEBUG_OBJECT (qtdemux,
4584           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4585           GST_TIME_ARGS (seg_time), index);
4586
4587       /* find previous keyframe */
4588       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4589     }
4590
4591     /* Remember until where we want to go */
4592     str->to_sample = str->from_sample - 1;
4593     /* Define our time position */
4594     target_ts =
4595         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4596     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4597     if (seg->media_start != GST_CLOCK_TIME_NONE)
4598       str->time_position -= seg->media_start;
4599
4600     /* Now seek back in time */
4601     gst_qtdemux_move_stream (qtdemux, str, k_index);
4602     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4603         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4604         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4605   }
4606
4607   return GST_FLOW_OK;
4608
4609 eos:
4610   return GST_FLOW_EOS;
4611 }
4612
4613 /*
4614  * Gets the current qt segment start, stop and position for the
4615  * given time offset. This is used in update_segment()
4616  */
4617 static void
4618 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4619     QtDemuxStream * stream, GstClockTime offset,
4620     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4621 {
4622   GstClockTime seg_time;
4623   GstClockTime start, stop, time;
4624   QtDemuxSegment *segment;
4625
4626   segment = &stream->segments[stream->segment_index];
4627
4628   /* get time in this segment */
4629   seg_time = (offset - segment->time) * segment->rate;
4630
4631   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4632       GST_TIME_ARGS (seg_time));
4633
4634   if (G_UNLIKELY (seg_time > segment->duration)) {
4635     GST_LOG_OBJECT (stream->pad,
4636         "seg_time > segment->duration %" GST_TIME_FORMAT,
4637         GST_TIME_ARGS (segment->duration));
4638     seg_time = segment->duration;
4639   }
4640
4641   /* qtdemux->segment.stop is in outside-time-realm, whereas
4642    * segment->media_stop is in track-time-realm.
4643    *
4644    * In order to compare the two, we need to bring segment.stop
4645    * into the track-time-realm
4646    *
4647    * FIXME - does this comment still hold? Don't see any conversion here */
4648
4649   stop = qtdemux->segment.stop;
4650   if (stop == GST_CLOCK_TIME_NONE)
4651     stop = qtdemux->segment.duration;
4652   if (stop == GST_CLOCK_TIME_NONE)
4653     stop = segment->media_stop;
4654   else
4655     stop =
4656         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4657
4658   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4659     start = segment->time + seg_time;
4660     time = offset;
4661     stop = start - seg_time + segment->duration;
4662   } else if (qtdemux->segment.rate >= 0) {
4663     start = MIN (segment->media_start + seg_time, stop);
4664     time = offset;
4665   } else {
4666     if (segment->media_start >= qtdemux->segment.start) {
4667       time = segment->time;
4668     } else {
4669       time = segment->time + (qtdemux->segment.start - segment->media_start);
4670     }
4671
4672     start = MAX (segment->media_start, qtdemux->segment.start);
4673     stop = MIN (segment->media_start + seg_time, stop);
4674   }
4675
4676   *_start = start;
4677   *_stop = stop;
4678   *_time = time;
4679 }
4680
4681 /*
4682  * Updates the qt segment used for the stream and pushes a new segment event
4683  * downstream on this stream's pad.
4684  */
4685 static gboolean
4686 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4687     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4688     GstClockTime * _stop)
4689 {
4690   QtDemuxSegment *segment;
4691   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4692   gdouble rate;
4693   GstEvent *event;
4694
4695   /* update the current segment */
4696   stream->segment_index = seg_idx;
4697
4698   /* get the segment */
4699   segment = &stream->segments[seg_idx];
4700
4701   if (G_UNLIKELY (offset < segment->time)) {
4702     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4703         GST_TIME_ARGS (segment->time));
4704     return FALSE;
4705   }
4706
4707   /* segment lies beyond total indicated duration */
4708   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4709           segment->time > qtdemux->segment.duration)) {
4710     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4711         " < segment->time %" GST_TIME_FORMAT,
4712         GST_TIME_ARGS (qtdemux->segment.duration),
4713         GST_TIME_ARGS (segment->time));
4714     return FALSE;
4715   }
4716
4717   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4718       &start, &stop, &time);
4719
4720   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4721       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4722       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4723
4724   /* combine global rate with that of the segment */
4725   rate = segment->rate * qtdemux->segment.rate;
4726
4727   /* Copy flags from main segment */
4728   stream->segment.flags = qtdemux->segment.flags;
4729
4730   /* update the segment values used for clipping */
4731   stream->segment.offset = qtdemux->segment.offset;
4732   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4733   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4734   stream->segment.rate = rate;
4735   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4736       stream->cslg_shift);
4737   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4738       stream->cslg_shift);
4739   stream->segment.time = time;
4740   stream->segment.position = stream->segment.start;
4741
4742   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4743       &stream->segment);
4744
4745   /* now prepare and send the segment */
4746   if (stream->pad) {
4747     event = gst_event_new_segment (&stream->segment);
4748     if (qtdemux->segment_seqnum) {
4749       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4750     }
4751     gst_pad_push_event (stream->pad, event);
4752     /* assume we can send more data now */
4753     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4754     /* clear to send tags on this pad now */
4755     gst_qtdemux_push_tags (qtdemux, stream);
4756   }
4757
4758   if (_start)
4759     *_start = start;
4760   if (_stop)
4761     *_stop = stop;
4762
4763   return TRUE;
4764 }
4765
4766 /* activate the given segment number @seg_idx of @stream at time @offset.
4767  * @offset is an absolute global position over all the segments.
4768  *
4769  * This will push out a NEWSEGMENT event with the right values and
4770  * position the stream index to the first decodable sample before
4771  * @offset.
4772  */
4773 static gboolean
4774 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4775     guint32 seg_idx, GstClockTime offset)
4776 {
4777   QtDemuxSegment *segment;
4778   guint32 index, kf_index;
4779   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4780
4781   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4782       seg_idx, GST_TIME_ARGS (offset));
4783
4784   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4785           &start, &stop))
4786     return FALSE;
4787
4788   segment = &stream->segments[stream->segment_index];
4789
4790   /* in the fragmented case, we pick a fragment that starts before our
4791    * desired position and rely on downstream to wait for a keyframe
4792    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4793    * tfra entries tells us which trun/sample the key unit is in, but we don't
4794    * make use of this additional information at the moment) */
4795   if (qtdemux->fragmented) {
4796     stream->to_sample = G_MAXUINT32;
4797     return TRUE;
4798   }
4799
4800   /* We don't need to look for a sample in push-based */
4801   if (!qtdemux->pullbased)
4802     return TRUE;
4803
4804   /* and move to the keyframe before the indicated media time of the
4805    * segment */
4806   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4807     if (qtdemux->segment.rate >= 0) {
4808       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4809       stream->to_sample = G_MAXUINT32;
4810       GST_DEBUG_OBJECT (stream->pad,
4811           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4812           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4813           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4814     } else {
4815       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4816       stream->to_sample = index;
4817       GST_DEBUG_OBJECT (stream->pad,
4818           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4819           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4820           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4821     }
4822   } else {
4823     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4824         "this is an empty segment");
4825     return TRUE;
4826   }
4827
4828   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4829    * encountered an error and printed a message so we return appropriately */
4830   if (index == -1)
4831     return FALSE;
4832
4833   /* we're at the right spot */
4834   if (index == stream->sample_index) {
4835     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4836     return TRUE;
4837   }
4838
4839   /* find keyframe of the target index */
4840   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4841
4842 /* *INDENT-OFF* */
4843 /* indent does stupid stuff with stream->samples[].timestamp */
4844
4845   /* if we move forwards, we don't have to go back to the previous
4846    * keyframe since we already sent that. We can also just jump to
4847    * the keyframe right before the target index if there is one. */
4848   if (index > stream->sample_index) {
4849     /* moving forwards check if we move past a keyframe */
4850     if (kf_index > stream->sample_index) {
4851       GST_DEBUG_OBJECT (stream->pad,
4852            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4853            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4854            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4855       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4856     } else {
4857       GST_DEBUG_OBJECT (stream->pad,
4858           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4859           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4860           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4861     }
4862   } else {
4863     GST_DEBUG_OBJECT (stream->pad,
4864         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4865         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4866         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4867     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4868   }
4869
4870 /* *INDENT-ON* */
4871
4872   return TRUE;
4873 }
4874
4875 /* prepare to get the current sample of @stream, getting essential values.
4876  *
4877  * This function will also prepare and send the segment when needed.
4878  *
4879  * Return FALSE if the stream is EOS.
4880  *
4881  * PULL-BASED
4882  */
4883 static gboolean
4884 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4885     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4886     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4887     gboolean * keyframe)
4888 {
4889   QtDemuxSample *sample;
4890   GstClockTime time_position;
4891   guint32 seg_idx;
4892
4893   g_return_val_if_fail (stream != NULL, FALSE);
4894
4895   time_position = stream->time_position;
4896   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4897     goto eos;
4898
4899   seg_idx = stream->segment_index;
4900   if (G_UNLIKELY (seg_idx == -1)) {
4901     /* find segment corresponding to time_position if we are looking
4902      * for a segment. */
4903     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4904   }
4905
4906   /* different segment, activate it, sample_index will be set. */
4907   if (G_UNLIKELY (stream->segment_index != seg_idx))
4908     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4909
4910   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4911                   segment_index]))) {
4912     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4913
4914     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4915         " prepare empty sample");
4916
4917     *empty = TRUE;
4918     *pts = *dts = time_position;
4919     *duration = seg->duration - (time_position - seg->time);
4920
4921     return TRUE;
4922   }
4923
4924   *empty = FALSE;
4925
4926   if (stream->sample_index == -1)
4927     stream->sample_index = 0;
4928
4929   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4930       stream->sample_index, stream->n_samples);
4931
4932   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4933     if (!qtdemux->fragmented)
4934       goto eos;
4935
4936     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4937     do {
4938       GstFlowReturn flow;
4939
4940       GST_OBJECT_LOCK (qtdemux);
4941       flow = qtdemux_add_fragmented_samples (qtdemux);
4942       GST_OBJECT_UNLOCK (qtdemux);
4943
4944       if (flow != GST_FLOW_OK)
4945         goto eos;
4946     }
4947     while (stream->sample_index >= stream->n_samples);
4948   }
4949
4950   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4951     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4952         stream->sample_index);
4953     return FALSE;
4954   }
4955
4956   /* now get the info for the sample we're at */
4957   sample = &stream->samples[stream->sample_index];
4958
4959   *dts = QTSAMPLE_DTS (stream, sample);
4960   *pts = QTSAMPLE_PTS (stream, sample);
4961   *offset = sample->offset;
4962   *size = sample->size;
4963   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4964   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4965
4966   return TRUE;
4967
4968   /* special cases */
4969 eos:
4970   {
4971     stream->time_position = GST_CLOCK_TIME_NONE;
4972     return FALSE;
4973   }
4974 }
4975
4976 /* move to the next sample in @stream.
4977  *
4978  * Moves to the next segment when needed.
4979  */
4980 static void
4981 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4982 {
4983   QtDemuxSample *sample;
4984   QtDemuxSegment *segment;
4985
4986   /* get current segment */
4987   segment = &stream->segments[stream->segment_index];
4988
4989   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4990     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4991     goto next_segment;
4992   }
4993
4994   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4995     /* Mark the stream as EOS */
4996     GST_DEBUG_OBJECT (qtdemux,
4997         "reached max allowed sample %u, mark EOS", stream->to_sample);
4998     stream->time_position = GST_CLOCK_TIME_NONE;
4999     return;
5000   }
5001
5002   /* move to next sample */
5003   stream->sample_index++;
5004   stream->offset_in_sample = 0;
5005
5006   /* reached the last sample, we need the next segment */
5007   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5008     goto next_segment;
5009
5010   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5011     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5012         stream->sample_index);
5013     return;
5014   }
5015
5016   /* get next sample */
5017   sample = &stream->samples[stream->sample_index];
5018
5019   /* see if we are past the segment */
5020   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5021     goto next_segment;
5022
5023   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5024     /* inside the segment, update time_position, looks very familiar to
5025      * GStreamer segments, doesn't it? */
5026     stream->time_position =
5027         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5028   } else {
5029     /* not yet in segment, time does not yet increment. This means
5030      * that we are still prerolling keyframes to the decoder so it can
5031      * decode the first sample of the segment. */
5032     stream->time_position = segment->time;
5033   }
5034   return;
5035
5036   /* move to the next segment */
5037 next_segment:
5038   {
5039     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5040
5041     if (stream->segment_index == stream->n_segments - 1) {
5042       /* are we at the end of the last segment, we're EOS */
5043       stream->time_position = GST_CLOCK_TIME_NONE;
5044     } else {
5045       /* else we're only at the end of the current segment */
5046       stream->time_position = segment->stop_time;
5047     }
5048     /* make sure we select a new segment */
5049
5050     /* accumulate previous segments */
5051     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5052       stream->accumulated_base +=
5053           (stream->segment.stop -
5054           stream->segment.start) / ABS (stream->segment.rate);
5055
5056     stream->segment_index = -1;
5057   }
5058 }
5059
5060 static void
5061 gst_qtdemux_sync_streams (GstQTDemux * demux)
5062 {
5063   gint i;
5064
5065   if (demux->n_streams <= 1)
5066     return;
5067
5068   for (i = 0; i < demux->n_streams; i++) {
5069     QtDemuxStream *stream;
5070     GstClockTime end_time;
5071
5072     stream = demux->streams[i];
5073
5074     if (!stream->pad)
5075       continue;
5076
5077     /* TODO advance time on subtitle streams here, if any some day */
5078
5079     /* some clips/trailers may have unbalanced streams at the end,
5080      * so send EOS on shorter stream to prevent stalling others */
5081
5082     /* do not mess with EOS if SEGMENT seeking */
5083     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5084       continue;
5085
5086     if (demux->pullbased) {
5087       /* loop mode is sample time based */
5088       if (!STREAM_IS_EOS (stream))
5089         continue;
5090     } else {
5091       /* push mode is byte position based */
5092       if (stream->n_samples &&
5093           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5094         continue;
5095     }
5096
5097     if (stream->sent_eos)
5098       continue;
5099
5100     /* only act if some gap */
5101     end_time = stream->segments[stream->n_segments - 1].stop_time;
5102     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5103         ", stream end: %" GST_TIME_FORMAT,
5104         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5105     if (GST_CLOCK_TIME_IS_VALID (end_time)
5106         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5107       GstEvent *event;
5108
5109       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5110           GST_PAD_NAME (stream->pad));
5111       stream->sent_eos = TRUE;
5112       event = gst_event_new_eos ();
5113       if (demux->segment_seqnum)
5114         gst_event_set_seqnum (event, demux->segment_seqnum);
5115       gst_pad_push_event (stream->pad, event);
5116     }
5117   }
5118 }
5119
5120 /* EOS and NOT_LINKED need to be combined. This means that we return:
5121  *
5122  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5123  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5124  */
5125 static GstFlowReturn
5126 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5127     GstFlowReturn ret)
5128 {
5129   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5130
5131   if (stream->pad)
5132     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5133         ret);
5134   else
5135     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5136
5137   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5138   return ret;
5139 }
5140
5141 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5142  * completely clipped
5143  *
5144  * Should be used only with raw buffers */
5145 static GstBuffer *
5146 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5147     GstBuffer * buf)
5148 {
5149   guint64 start, stop, cstart, cstop, diff;
5150   GstClockTime pts, duration;
5151   gsize size, osize;
5152   gint num_rate, denom_rate;
5153   gint frame_size;
5154   gboolean clip_data;
5155   guint offset;
5156
5157   osize = size = gst_buffer_get_size (buf);
5158   offset = 0;
5159
5160   /* depending on the type, setup the clip parameters */
5161   if (stream->subtype == FOURCC_soun) {
5162     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5163     num_rate = GST_SECOND;
5164     denom_rate = (gint) CUR_STREAM (stream)->rate;
5165     clip_data = TRUE;
5166   } else if (stream->subtype == FOURCC_vide) {
5167     frame_size = size;
5168     num_rate = CUR_STREAM (stream)->fps_n;
5169     denom_rate = CUR_STREAM (stream)->fps_d;
5170     clip_data = FALSE;
5171   } else
5172     goto wrong_type;
5173
5174   if (frame_size <= 0)
5175     goto bad_frame_size;
5176
5177   /* we can only clip if we have a valid pts */
5178   pts = GST_BUFFER_PTS (buf);
5179   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5180     goto no_pts;
5181
5182   duration = GST_BUFFER_DURATION (buf);
5183
5184   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5185     duration =
5186         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5187   }
5188
5189   start = pts;
5190   stop = start + duration;
5191
5192   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5193               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5194     goto clipped;
5195
5196   /* see if some clipping happened */
5197   diff = cstart - start;
5198   if (diff > 0) {
5199     pts += diff;
5200     duration -= diff;
5201
5202     if (clip_data) {
5203       /* bring clipped time to samples and to bytes */
5204       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5205       diff *= frame_size;
5206
5207       GST_DEBUG_OBJECT (qtdemux,
5208           "clipping start to %" GST_TIME_FORMAT " %"
5209           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5210
5211       offset = diff;
5212       size -= diff;
5213     }
5214   }
5215   diff = stop - cstop;
5216   if (diff > 0) {
5217     duration -= diff;
5218
5219     if (clip_data) {
5220       /* bring clipped time to samples and then to bytes */
5221       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5222       diff *= frame_size;
5223       GST_DEBUG_OBJECT (qtdemux,
5224           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5225           " bytes", GST_TIME_ARGS (cstop), diff);
5226       size -= diff;
5227     }
5228   }
5229
5230   if (offset != 0 || size != osize)
5231     gst_buffer_resize (buf, offset, size);
5232
5233   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5234   GST_BUFFER_PTS (buf) = pts;
5235   GST_BUFFER_DURATION (buf) = duration;
5236
5237   return buf;
5238
5239   /* dropped buffer */
5240 wrong_type:
5241   {
5242     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5243     return buf;
5244   }
5245 bad_frame_size:
5246   {
5247     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5248     return buf;
5249   }
5250 no_pts:
5251   {
5252     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5253     return buf;
5254   }
5255 clipped:
5256   {
5257     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5258     gst_buffer_unref (buf);
5259     return NULL;
5260   }
5261 }
5262
5263 static GstBuffer *
5264 gst_qtdemux_align_buffer (GstQTDemux * demux,
5265     GstBuffer * buffer, gsize alignment)
5266 {
5267   GstMapInfo map;
5268
5269   gst_buffer_map (buffer, &map, GST_MAP_READ);
5270
5271   if (map.size < sizeof (guintptr)) {
5272     gst_buffer_unmap (buffer, &map);
5273     return buffer;
5274   }
5275
5276   if (((guintptr) map.data) & (alignment - 1)) {
5277     GstBuffer *new_buffer;
5278     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5279
5280     new_buffer = gst_buffer_new_allocate (NULL,
5281         gst_buffer_get_size (buffer), &params);
5282
5283     /* Copy data "by hand", so ensure alignment is kept: */
5284     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5285
5286     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5287     GST_DEBUG_OBJECT (demux,
5288         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5289         alignment);
5290
5291     gst_buffer_unmap (buffer, &map);
5292     gst_buffer_unref (buffer);
5293
5294     return new_buffer;
5295   }
5296
5297   gst_buffer_unmap (buffer, &map);
5298   return buffer;
5299 }
5300
5301 /* the input buffer metadata must be writable,
5302  * but time/duration etc not yet set and need not be preserved */
5303 static GstBuffer *
5304 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5305     GstBuffer * buf)
5306 {
5307   GstMapInfo map;
5308   guint nsize = 0;
5309   gchar *str;
5310
5311   /* not many cases for now */
5312   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5313     /* send a one time dvd clut event */
5314     if (stream->pending_event && stream->pad)
5315       gst_pad_push_event (stream->pad, stream->pending_event);
5316     stream->pending_event = NULL;
5317   }
5318
5319   if (G_UNLIKELY (stream->subtype != FOURCC_text
5320           && stream->subtype != FOURCC_sbtl &&
5321           stream->subtype != FOURCC_subp)) {
5322     return buf;
5323   }
5324
5325   gst_buffer_map (buf, &map, GST_MAP_READ);
5326
5327   /* empty buffer is sent to terminate previous subtitle */
5328   if (map.size <= 2) {
5329     gst_buffer_unmap (buf, &map);
5330     gst_buffer_unref (buf);
5331     return NULL;
5332   }
5333   if (stream->subtype == FOURCC_subp) {
5334     /* That's all the processing needed for subpictures */
5335     gst_buffer_unmap (buf, &map);
5336     return buf;
5337   }
5338
5339   nsize = GST_READ_UINT16_BE (map.data);
5340   nsize = MIN (nsize, map.size - 2);
5341
5342   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5343       nsize, map.size);
5344
5345   /* takes care of UTF-8 validation or UTF-16 recognition,
5346    * no other encoding expected */
5347   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5348   gst_buffer_unmap (buf, &map);
5349   if (str) {
5350     gst_buffer_unref (buf);
5351     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5352   } else {
5353     /* this should not really happen unless the subtitle is corrupted */
5354     gst_buffer_unref (buf);
5355     buf = NULL;
5356   }
5357
5358   /* FIXME ? convert optional subsequent style info to markup */
5359
5360   return buf;
5361 }
5362
5363 /* Sets a buffer's attributes properly and pushes it downstream.
5364  * Also checks for additional actions and custom processing that may
5365  * need to be done first.
5366  */
5367 static GstFlowReturn
5368 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5369     QtDemuxStream * stream, GstBuffer * buf,
5370     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5371     gboolean keyframe, GstClockTime position, guint64 byte_position)
5372 {
5373   GstFlowReturn ret = GST_FLOW_OK;
5374
5375   /* offset the timestamps according to the edit list */
5376
5377   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5378     gchar *url;
5379     GstMapInfo map;
5380
5381     gst_buffer_map (buf, &map, GST_MAP_READ);
5382     url = g_strndup ((gchar *) map.data, map.size);
5383     gst_buffer_unmap (buf, &map);
5384     if (url != NULL && strlen (url) != 0) {
5385       /* we have RTSP redirect now */
5386       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5387           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5388               gst_structure_new ("redirect",
5389                   "new-location", G_TYPE_STRING, url, NULL)));
5390       qtdemux->posted_redirect = TRUE;
5391     } else {
5392       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5393           "posting");
5394     }
5395     g_free (url);
5396   }
5397
5398   /* position reporting */
5399   if (qtdemux->segment.rate >= 0) {
5400     qtdemux->segment.position = position;
5401     gst_qtdemux_sync_streams (qtdemux);
5402   }
5403
5404   if (G_UNLIKELY (!stream->pad)) {
5405     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5406     gst_buffer_unref (buf);
5407     goto exit;
5408   }
5409
5410   /* send out pending buffers */
5411   while (stream->buffers) {
5412     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5413
5414     if (G_UNLIKELY (stream->discont)) {
5415       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5416       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5417       stream->discont = FALSE;
5418     } else {
5419       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5420     }
5421
5422     if (stream->alignment > 1)
5423       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5424     gst_pad_push (stream->pad, buffer);
5425
5426     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5427   }
5428
5429   /* we're going to modify the metadata */
5430   buf = gst_buffer_make_writable (buf);
5431
5432   if (G_UNLIKELY (stream->need_process))
5433     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5434
5435   if (!buf) {
5436     goto exit;
5437   }
5438
5439   GST_BUFFER_DTS (buf) = dts;
5440   GST_BUFFER_PTS (buf) = pts;
5441   GST_BUFFER_DURATION (buf) = duration;
5442   GST_BUFFER_OFFSET (buf) = -1;
5443   GST_BUFFER_OFFSET_END (buf) = -1;
5444
5445   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5446     gst_buffer_append_memory (buf,
5447         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5448
5449   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5450     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5451   }
5452 #if 0
5453   if (G_UNLIKELY (qtdemux->element_index)) {
5454     GstClockTime stream_time;
5455
5456     stream_time =
5457         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5458         timestamp);
5459     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5460       GST_LOG_OBJECT (qtdemux,
5461           "adding association %" GST_TIME_FORMAT "-> %"
5462           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5463       gst_index_add_association (qtdemux->element_index,
5464           qtdemux->index_id,
5465           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5466           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5467           GST_FORMAT_BYTES, byte_position, NULL);
5468     }
5469   }
5470 #endif
5471
5472   if (stream->need_clip)
5473     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5474
5475   if (G_UNLIKELY (buf == NULL))
5476     goto exit;
5477
5478   if (G_UNLIKELY (stream->discont)) {
5479     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5480     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5481     stream->discont = FALSE;
5482   } else {
5483     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5484   }
5485
5486   if (!keyframe) {
5487     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5488     stream->on_keyframe = FALSE;
5489   } else {
5490     stream->on_keyframe = TRUE;
5491   }
5492
5493
5494   GST_LOG_OBJECT (qtdemux,
5495       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5496       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5497       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5498       GST_PAD_NAME (stream->pad));
5499
5500   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5501     GstStructure *crypto_info;
5502     QtDemuxCencSampleSetInfo *info =
5503         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5504     gint index;
5505     GstEvent *event;
5506
5507     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5508       gst_pad_push_event (stream->pad, event);
5509     }
5510
5511     if (info->crypto_info == NULL) {
5512       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5513       gst_buffer_unref (buf);
5514       goto exit;
5515     }
5516
5517     /* The end of the crypto_info array matches our n_samples position,
5518      * so count backward from there */
5519     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5520     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5521       /* steal structure from array */
5522       crypto_info = g_ptr_array_index (info->crypto_info, index);
5523       g_ptr_array_index (info->crypto_info, index) = NULL;
5524       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5525           info->crypto_info->len);
5526       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5527         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5528     } else {
5529       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5530           index, stream->sample_index);
5531     }
5532   }
5533
5534   if (stream->alignment > 1)
5535     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5536
5537   ret = gst_pad_push (stream->pad, buf);
5538
5539   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5540     /* mark position in stream, we'll need this to know when to send GAP event */
5541     stream->segment.position = pts + duration;
5542   }
5543
5544 exit:
5545   return ret;
5546 }
5547
5548 static const QtDemuxRandomAccessEntry *
5549 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5550     GstClockTime pos, gboolean after)
5551 {
5552   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5553   guint n_entries = stream->n_ra_entries;
5554   guint i;
5555
5556   /* we assume the table is sorted */
5557   for (i = 0; i < n_entries; ++i) {
5558     if (entries[i].ts > pos)
5559       break;
5560   }
5561
5562   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5563    * probably okay to assume that the index lists the very first fragment */
5564   if (i == 0)
5565     return &entries[0];
5566
5567   if (after)
5568     return &entries[i];
5569   else
5570     return &entries[i - 1];
5571 }
5572
5573 static gboolean
5574 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5575 {
5576   const QtDemuxRandomAccessEntry *best_entry = NULL;
5577   guint i;
5578
5579   GST_OBJECT_LOCK (qtdemux);
5580
5581   g_assert (qtdemux->n_streams > 0);
5582
5583   for (i = 0; i < qtdemux->n_streams; i++) {
5584     const QtDemuxRandomAccessEntry *entry;
5585     QtDemuxStream *stream;
5586     gboolean is_audio_or_video;
5587
5588     stream = qtdemux->streams[i];
5589
5590     g_free (stream->samples);
5591     stream->samples = NULL;
5592     stream->n_samples = 0;
5593     stream->stbl_index = -1;    /* no samples have yet been parsed */
5594     stream->sample_index = -1;
5595
5596     if (stream->protection_scheme_info) {
5597       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5598       if (stream->protection_scheme_type == FOURCC_cenc) {
5599         QtDemuxCencSampleSetInfo *info =
5600             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5601         if (info->crypto_info) {
5602           g_ptr_array_free (info->crypto_info, TRUE);
5603           info->crypto_info = NULL;
5604         }
5605       }
5606     }
5607
5608     if (stream->ra_entries == NULL)
5609       continue;
5610
5611     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5612       is_audio_or_video = TRUE;
5613     else
5614       is_audio_or_video = FALSE;
5615
5616     entry =
5617         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5618         stream->time_position, !is_audio_or_video);
5619
5620     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5621         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5622
5623     stream->pending_seek = entry;
5624
5625     /* decide position to jump to just based on audio/video tracks, not subs */
5626     if (!is_audio_or_video)
5627       continue;
5628
5629     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5630       best_entry = entry;
5631   }
5632
5633   if (best_entry == NULL) {
5634     GST_OBJECT_UNLOCK (qtdemux);
5635     return FALSE;
5636   }
5637
5638   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5639       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5640       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5641       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5642
5643   qtdemux->moof_offset = best_entry->moof_offset;
5644
5645   qtdemux_add_fragmented_samples (qtdemux);
5646
5647   GST_OBJECT_UNLOCK (qtdemux);
5648   return TRUE;
5649 }
5650
5651 static GstFlowReturn
5652 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5653 {
5654   GstFlowReturn ret = GST_FLOW_OK;
5655   GstBuffer *buf = NULL;
5656   QtDemuxStream *stream;
5657   GstClockTime min_time;
5658   guint64 offset = 0;
5659   GstClockTime dts = GST_CLOCK_TIME_NONE;
5660   GstClockTime pts = GST_CLOCK_TIME_NONE;
5661   GstClockTime duration = 0;
5662   gboolean keyframe = FALSE;
5663   guint sample_size = 0;
5664   gboolean empty = 0;
5665   guint size;
5666   gint index;
5667   gint i;
5668
5669   gst_qtdemux_push_pending_newsegment (qtdemux);
5670
5671   if (qtdemux->fragmented_seek_pending) {
5672     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5673     gst_qtdemux_do_fragmented_seek (qtdemux);
5674     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5675     qtdemux->fragmented_seek_pending = FALSE;
5676   }
5677
5678   /* Figure out the next stream sample to output, min_time is expressed in
5679    * global time and runs over the edit list segments. */
5680   min_time = G_MAXUINT64;
5681   index = -1;
5682   for (i = 0; i < qtdemux->n_streams; i++) {
5683     GstClockTime position;
5684
5685     stream = qtdemux->streams[i];
5686     position = stream->time_position;
5687
5688     /* position of -1 is EOS */
5689     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5690       min_time = position;
5691       index = i;
5692     }
5693   }
5694   /* all are EOS */
5695   if (G_UNLIKELY (index == -1)) {
5696     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5697     goto eos;
5698   }
5699
5700   /* check for segment end */
5701   if (G_UNLIKELY (qtdemux->segment.stop != -1
5702           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5703               || (qtdemux->segment.rate < 0
5704                   && qtdemux->segment.start > min_time))
5705           && qtdemux->streams[index]->on_keyframe)) {
5706     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5707     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5708     goto eos_stream;
5709   }
5710
5711   /* gap events for subtitle streams */
5712   for (i = 0; i < qtdemux->n_streams; i++) {
5713     stream = qtdemux->streams[i];
5714     if (stream->pad && (stream->subtype == FOURCC_subp
5715             || stream->subtype == FOURCC_text
5716             || stream->subtype == FOURCC_sbtl)) {
5717       /* send one second gap events until the stream catches up */
5718       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5719       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5720           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5721           stream->segment.position + GST_SECOND < min_time) {
5722         GstEvent *gap =
5723             gst_event_new_gap (stream->segment.position, GST_SECOND);
5724         gst_pad_push_event (stream->pad, gap);
5725         stream->segment.position += GST_SECOND;
5726       }
5727     }
5728   }
5729
5730   stream = qtdemux->streams[index];
5731   /* fetch info for the current sample of this stream */
5732   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5733               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5734     goto eos_stream;
5735
5736   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5737   if (stream->new_caps) {
5738     gst_qtdemux_configure_stream (qtdemux, stream);
5739     qtdemux_do_allocation (qtdemux, stream);
5740   }
5741
5742   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5743   if (G_UNLIKELY (qtdemux->
5744           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5745     if (stream->subtype == FOURCC_vide && !keyframe) {
5746       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5747       goto next;
5748     }
5749   }
5750
5751   GST_DEBUG_OBJECT (qtdemux,
5752       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5753       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5754       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5755       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5756
5757   if (G_UNLIKELY (empty)) {
5758     /* empty segment, push a gap and move to the next one */
5759     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5760     stream->segment.position = pts + duration;
5761     goto next;
5762   }
5763
5764   /* hmm, empty sample, skip and move to next sample */
5765   if (G_UNLIKELY (sample_size <= 0))
5766     goto next;
5767
5768   /* last pushed sample was out of boundary, goto next sample */
5769   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5770     goto next;
5771
5772   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5773     size = sample_size;
5774   } else {
5775     GST_DEBUG_OBJECT (qtdemux,
5776         "size %d larger than stream max_buffer_size %d, trimming",
5777         sample_size, stream->max_buffer_size);
5778     size =
5779         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5780   }
5781
5782   if (qtdemux->cenc_aux_info_offset > 0) {
5783     GstMapInfo map;
5784     GstByteReader br;
5785     GstBuffer *aux_info = NULL;
5786
5787     /* pull the data stored before the sample */
5788     ret =
5789         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5790         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5791     if (G_UNLIKELY (ret != GST_FLOW_OK))
5792       goto beach;
5793     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5794     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5795     gst_byte_reader_init (&br, map.data + 8, map.size);
5796     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5797             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5798       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5799       gst_buffer_unmap (aux_info, &map);
5800       gst_buffer_unref (aux_info);
5801       ret = GST_FLOW_ERROR;
5802       goto beach;
5803     }
5804     gst_buffer_unmap (aux_info, &map);
5805     gst_buffer_unref (aux_info);
5806   }
5807
5808   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5809       offset);
5810
5811   if (stream->use_allocator) {
5812     /* if we have a per-stream allocator, use it */
5813     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5814   }
5815
5816   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5817       size, &buf);
5818   if (G_UNLIKELY (ret != GST_FLOW_OK))
5819     goto beach;
5820
5821   if (size != sample_size) {
5822     pts += gst_util_uint64_scale_int (GST_SECOND,
5823         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5824         stream->timescale);
5825     dts +=
5826         gst_util_uint64_scale_int (GST_SECOND,
5827         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5828         stream->timescale);
5829     duration =
5830         gst_util_uint64_scale_int (GST_SECOND,
5831         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5832   }
5833
5834   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5835       dts, pts, duration, keyframe, min_time, offset);
5836
5837   if (size != sample_size) {
5838     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5839     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5840
5841     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5842         sample->timestamp +
5843         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5844     if (time_position >= segment->media_start) {
5845       /* inside the segment, update time_position, looks very familiar to
5846        * GStreamer segments, doesn't it? */
5847       stream->time_position = (time_position - segment->media_start) +
5848           segment->time;
5849     } else {
5850       /* not yet in segment, time does not yet increment. This means
5851        * that we are still prerolling keyframes to the decoder so it can
5852        * decode the first sample of the segment. */
5853       stream->time_position = segment->time;
5854     }
5855   }
5856
5857   /* combine flows */
5858   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5859   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5860    * we have no more data for the pad to push */
5861   if (ret == GST_FLOW_EOS)
5862     ret = GST_FLOW_OK;
5863
5864   stream->offset_in_sample += size;
5865   if (stream->offset_in_sample >= sample_size) {
5866     gst_qtdemux_advance_sample (qtdemux, stream);
5867   }
5868   goto beach;
5869
5870 next:
5871   gst_qtdemux_advance_sample (qtdemux, stream);
5872
5873 beach:
5874   return ret;
5875
5876   /* special cases */
5877 eos:
5878   {
5879     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5880     ret = GST_FLOW_EOS;
5881     goto beach;
5882   }
5883 eos_stream:
5884   {
5885     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5886     /* EOS will be raised if all are EOS */
5887     ret = GST_FLOW_OK;
5888     goto beach;
5889   }
5890 }
5891
5892 static void
5893 gst_qtdemux_loop (GstPad * pad)
5894 {
5895   GstQTDemux *qtdemux;
5896   guint64 cur_offset;
5897   GstFlowReturn ret;
5898
5899   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5900
5901   cur_offset = qtdemux->offset;
5902   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5903       cur_offset, qt_demux_state_string (qtdemux->state));
5904
5905   switch (qtdemux->state) {
5906     case QTDEMUX_STATE_INITIAL:
5907     case QTDEMUX_STATE_HEADER:
5908       ret = gst_qtdemux_loop_state_header (qtdemux);
5909       break;
5910     case QTDEMUX_STATE_MOVIE:
5911       ret = gst_qtdemux_loop_state_movie (qtdemux);
5912       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5913         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5914       }
5915       break;
5916     default:
5917       /* ouch */
5918       goto invalid_state;
5919   }
5920
5921   /* if something went wrong, pause */
5922   if (ret != GST_FLOW_OK)
5923     goto pause;
5924
5925 done:
5926   gst_object_unref (qtdemux);
5927   return;
5928
5929   /* ERRORS */
5930 invalid_state:
5931   {
5932     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5933         (NULL), ("streaming stopped, invalid state"));
5934     gst_pad_pause_task (pad);
5935     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5936     goto done;
5937   }
5938 pause:
5939   {
5940     const gchar *reason = gst_flow_get_name (ret);
5941
5942     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5943
5944     gst_pad_pause_task (pad);
5945
5946     /* fatal errors need special actions */
5947     /* check EOS */
5948     if (ret == GST_FLOW_EOS) {
5949       if (qtdemux->n_streams == 0) {
5950         /* we have no streams, post an error */
5951         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5952       }
5953       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5954         gint64 stop;
5955
5956         if ((stop = qtdemux->segment.stop) == -1)
5957           stop = qtdemux->segment.duration;
5958
5959         if (qtdemux->segment.rate >= 0) {
5960           GstMessage *message;
5961           GstEvent *event;
5962
5963           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5964           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5965               GST_FORMAT_TIME, stop);
5966           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5967           if (qtdemux->segment_seqnum) {
5968             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5969             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5970           }
5971           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5972           gst_qtdemux_push_event (qtdemux, event);
5973         } else {
5974           GstMessage *message;
5975           GstEvent *event;
5976
5977           /*  For Reverse Playback */
5978           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5979           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5980               GST_FORMAT_TIME, qtdemux->segment.start);
5981           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5982               qtdemux->segment.start);
5983           if (qtdemux->segment_seqnum) {
5984             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5985             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5986           }
5987           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5988           gst_qtdemux_push_event (qtdemux, event);
5989         }
5990       } else {
5991         GstEvent *event;
5992
5993         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5994         event = gst_event_new_eos ();
5995         if (qtdemux->segment_seqnum)
5996           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5997         gst_qtdemux_push_event (qtdemux, event);
5998       }
5999     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6000       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6001       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6002     }
6003     goto done;
6004   }
6005 }
6006
6007 /*
6008  * has_next_entry
6009  *
6010  * Returns if there are samples to be played.
6011  */
6012 static gboolean
6013 has_next_entry (GstQTDemux * demux)
6014 {
6015   QtDemuxStream *stream;
6016   int i;
6017
6018   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6019
6020   for (i = 0; i < demux->n_streams; i++) {
6021     stream = demux->streams[i];
6022
6023     if (stream->sample_index == -1) {
6024       stream->sample_index = 0;
6025       stream->offset_in_sample = 0;
6026     }
6027
6028     if (stream->sample_index >= stream->n_samples) {
6029       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6030       continue;
6031     }
6032     GST_DEBUG_OBJECT (demux, "Found a sample");
6033     return TRUE;
6034   }
6035
6036   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6037   return FALSE;
6038 }
6039
6040 /*
6041  * next_entry_size
6042  *
6043  * Returns the size of the first entry at the current offset.
6044  * If -1, there are none (which means EOS or empty file).
6045  */
6046 static guint64
6047 next_entry_size (GstQTDemux * demux)
6048 {
6049   QtDemuxStream *stream;
6050   int i;
6051   int smallidx = -1;
6052   guint64 smalloffs = (guint64) - 1;
6053   QtDemuxSample *sample;
6054
6055   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6056       demux->offset);
6057
6058   for (i = 0; i < demux->n_streams; i++) {
6059     stream = demux->streams[i];
6060
6061     if (stream->sample_index == -1) {
6062       stream->sample_index = 0;
6063       stream->offset_in_sample = 0;
6064     }
6065
6066     if (stream->sample_index >= stream->n_samples) {
6067       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6068       continue;
6069     }
6070
6071     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6072       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6073           stream->sample_index);
6074       return -1;
6075     }
6076
6077     sample = &stream->samples[stream->sample_index];
6078
6079     GST_LOG_OBJECT (demux,
6080         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6081         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6082         sample->offset, sample->size);
6083
6084     if (((smalloffs == -1)
6085             || (sample->offset < smalloffs)) && (sample->size)) {
6086       smallidx = i;
6087       smalloffs = sample->offset;
6088     }
6089   }
6090
6091   GST_LOG_OBJECT (demux,
6092       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6093       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6094
6095   if (smallidx == -1)
6096     return -1;
6097
6098   stream = demux->streams[smallidx];
6099   sample = &stream->samples[stream->sample_index];
6100
6101   if (sample->offset >= demux->offset) {
6102     demux->todrop = sample->offset - demux->offset;
6103     return sample->size + demux->todrop;
6104   }
6105
6106   GST_DEBUG_OBJECT (demux,
6107       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6108   return -1;
6109 }
6110
6111 static void
6112 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6113 {
6114   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6115
6116   gst_element_post_message (GST_ELEMENT_CAST (demux),
6117       gst_message_new_element (GST_OBJECT_CAST (demux),
6118           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6119 }
6120
6121 static gboolean
6122 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6123 {
6124   GstEvent *event;
6125   gboolean res = 0;
6126
6127   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6128
6129   event =
6130       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6131       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6132       GST_SEEK_TYPE_NONE, -1);
6133
6134   /* store seqnum to drop flush events, they don't need to reach downstream */
6135   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6136   res = gst_pad_push_event (demux->sinkpad, event);
6137   demux->offset_seek_seqnum = 0;
6138
6139   return res;
6140 }
6141
6142 /* check for seekable upstream, above and beyond a mere query */
6143 static void
6144 gst_qtdemux_check_seekability (GstQTDemux * demux)
6145 {
6146   GstQuery *query;
6147   gboolean seekable = FALSE;
6148   gint64 start = -1, stop = -1;
6149
6150   if (demux->upstream_size)
6151     return;
6152
6153   if (demux->upstream_format_is_time)
6154     return;
6155
6156   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6157   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6158     GST_DEBUG_OBJECT (demux, "seeking query failed");
6159     goto done;
6160   }
6161
6162   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6163
6164   /* try harder to query upstream size if we didn't get it the first time */
6165   if (seekable && stop == -1) {
6166     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6167     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6168   }
6169
6170   /* if upstream doesn't know the size, it's likely that it's not seekable in
6171    * practice even if it technically may be seekable */
6172   if (seekable && (start != 0 || stop <= start)) {
6173     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6174     seekable = FALSE;
6175   }
6176
6177 done:
6178   gst_query_unref (query);
6179
6180   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6181       G_GUINT64_FORMAT ")", seekable, start, stop);
6182   demux->upstream_seekable = seekable;
6183   demux->upstream_size = seekable ? stop : -1;
6184 }
6185
6186 static void
6187 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6188 {
6189   g_return_if_fail (bytes <= demux->todrop);
6190
6191   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6192   gst_adapter_flush (demux->adapter, bytes);
6193   demux->neededbytes -= bytes;
6194   demux->offset += bytes;
6195   demux->todrop -= bytes;
6196 }
6197
6198 static void
6199 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6200 {
6201   if (G_UNLIKELY (demux->pending_newsegment)) {
6202     gint i;
6203
6204     gst_qtdemux_push_pending_newsegment (demux);
6205     /* clear to send tags on all streams */
6206     for (i = 0; i < demux->n_streams; i++) {
6207       QtDemuxStream *stream;
6208       stream = demux->streams[i];
6209       gst_qtdemux_push_tags (demux, stream);
6210       if (CUR_STREAM (stream)->sparse) {
6211         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6212         gst_pad_push_event (stream->pad,
6213             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6214       }
6215     }
6216   }
6217 }
6218
6219 static void
6220 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6221     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6222 {
6223   GstClockTime ts, dur;
6224   GstEvent *gap;
6225
6226   ts = pos;
6227   dur =
6228       stream->segments[segment_index].duration - (pos -
6229       stream->segments[segment_index].time);
6230   gap = gst_event_new_gap (ts, dur);
6231   stream->time_position += dur;
6232
6233   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6234       "segment: %" GST_PTR_FORMAT, gap);
6235   gst_pad_push_event (stream->pad, gap);
6236 }
6237
6238 static void
6239 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6240     QtDemuxStream * stream)
6241 {
6242   gint i;
6243
6244   /* Push any initial gap segments before proceeding to the
6245    * 'real' data */
6246   for (i = 0; i < stream->n_segments; i++) {
6247     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6248
6249     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6250       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6251           stream->time_position);
6252     } else {
6253       /* Only support empty segment at the beginning followed by
6254        * one non-empty segment, this was checked when parsing the
6255        * edts atom, arriving here is unexpected */
6256       g_assert (i + 1 == stream->n_segments);
6257       break;
6258     }
6259   }
6260 }
6261
6262 static GstFlowReturn
6263 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6264 {
6265   GstQTDemux *demux;
6266
6267   demux = GST_QTDEMUX (parent);
6268
6269   GST_DEBUG_OBJECT (demux,
6270       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6271       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6272       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6273       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6274       gst_buffer_get_size (inbuf), demux->offset);
6275
6276   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6277     gboolean is_gap_input = FALSE;
6278     gint i;
6279
6280     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6281
6282     for (i = 0; i < demux->n_streams; i++) {
6283       demux->streams[i]->discont = TRUE;
6284     }
6285
6286     /* Check if we can land back on our feet in the case where upstream is
6287      * handling the seeking/pushing of samples with gaps in between (like
6288      * in the case of trick-mode DASH for example) */
6289     if (demux->upstream_format_is_time
6290         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6291       gint i;
6292       for (i = 0; i < demux->n_streams; i++) {
6293         guint32 res;
6294         GST_LOG_OBJECT (demux,
6295             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6296             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6297         res =
6298             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6299             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6300         if (res != -1) {
6301           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6302           GST_LOG_OBJECT (demux,
6303               "Checking if sample %d from stream %d is valid (offset:%"
6304               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6305               sample->offset, sample->size);
6306           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6307             GST_LOG_OBJECT (demux,
6308                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6309                 res);
6310             is_gap_input = TRUE;
6311             /* We can go back to standard playback mode */
6312             demux->state = QTDEMUX_STATE_MOVIE;
6313             /* Remember which sample this stream is at */
6314             demux->streams[i]->sample_index = res;
6315             /* Finally update all push-based values to the expected values */
6316             demux->neededbytes = demux->streams[i]->samples[res].size;
6317             demux->offset = GST_BUFFER_OFFSET (inbuf);
6318             demux->mdatleft =
6319                 demux->mdatsize - demux->offset + demux->mdatoffset;
6320             demux->todrop = 0;
6321           }
6322         }
6323       }
6324       if (!is_gap_input) {
6325         /* Reset state if it's a real discont */
6326         demux->neededbytes = 16;
6327         demux->state = QTDEMUX_STATE_INITIAL;
6328         demux->offset = GST_BUFFER_OFFSET (inbuf);
6329       }
6330     }
6331     /* Reverse fragmented playback, need to flush all we have before
6332      * consuming a new fragment.
6333      * The samples array have the timestamps calculated by accumulating the
6334      * durations but this won't work for reverse playback of fragments as
6335      * the timestamps of a subsequent fragment should be smaller than the
6336      * previously received one. */
6337     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6338       gst_qtdemux_process_adapter (demux, TRUE);
6339       for (i = 0; i < demux->n_streams; i++)
6340         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6341     }
6342   }
6343
6344   gst_adapter_push (demux->adapter, inbuf);
6345
6346   GST_DEBUG_OBJECT (demux,
6347       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6348       demux->neededbytes, gst_adapter_available (demux->adapter));
6349
6350   return gst_qtdemux_process_adapter (demux, FALSE);
6351 }
6352
6353 static GstFlowReturn
6354 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6355 {
6356   GstFlowReturn ret = GST_FLOW_OK;
6357
6358   /* we never really mean to buffer that much */
6359   if (demux->neededbytes == -1) {
6360     goto eos;
6361   }
6362
6363   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6364       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6365
6366 #ifndef GST_DISABLE_GST_DEBUG
6367     {
6368       guint64 discont_offset, distance_from_discont;
6369
6370       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6371       distance_from_discont =
6372           gst_adapter_distance_from_discont (demux->adapter);
6373
6374       GST_DEBUG_OBJECT (demux,
6375           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6376           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6377           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6378           demux->offset, discont_offset, distance_from_discont);
6379     }
6380 #endif
6381
6382     switch (demux->state) {
6383       case QTDEMUX_STATE_INITIAL:{
6384         const guint8 *data;
6385         guint32 fourcc;
6386         guint64 size;
6387
6388         gst_qtdemux_check_seekability (demux);
6389
6390         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6391
6392         /* get fourcc/length, set neededbytes */
6393         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6394             &size, &fourcc);
6395         gst_adapter_unmap (demux->adapter);
6396         data = NULL;
6397         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6398             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6399         if (size == 0) {
6400           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6401               (_("This file is invalid and cannot be played.")),
6402               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6403                   GST_FOURCC_ARGS (fourcc)));
6404           ret = GST_FLOW_ERROR;
6405           break;
6406         }
6407         if (fourcc == FOURCC_mdat) {
6408           gint next_entry = next_entry_size (demux);
6409           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6410             /* we have the headers, start playback */
6411             demux->state = QTDEMUX_STATE_MOVIE;
6412             demux->neededbytes = next_entry;
6413             demux->mdatleft = size;
6414             demux->mdatsize = demux->mdatleft;
6415           } else {
6416             /* no headers yet, try to get them */
6417             guint bs;
6418             gboolean res;
6419             guint64 old, target;
6420
6421           buffer_data:
6422             old = demux->offset;
6423             target = old + size;
6424
6425             /* try to jump over the atom with a seek */
6426             /* only bother if it seems worth doing so,
6427              * and avoids possible upstream/server problems */
6428             if (demux->upstream_seekable &&
6429                 demux->upstream_size > 4 * (1 << 20)) {
6430               res = qtdemux_seek_offset (demux, target);
6431             } else {
6432               GST_DEBUG_OBJECT (demux, "skipping seek");
6433               res = FALSE;
6434             }
6435
6436             if (res) {
6437               GST_DEBUG_OBJECT (demux, "seek success");
6438               /* remember the offset fo the first mdat so we can seek back to it
6439                * after we have the headers */
6440               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6441                 demux->first_mdat = old;
6442                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6443                     demux->first_mdat);
6444               }
6445               /* seek worked, continue reading */
6446               demux->offset = target;
6447               demux->neededbytes = 16;
6448               demux->state = QTDEMUX_STATE_INITIAL;
6449             } else {
6450               /* seek failed, need to buffer */
6451               demux->offset = old;
6452               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6453               /* there may be multiple mdat (or alike) buffers */
6454               /* sanity check */
6455               if (demux->mdatbuffer)
6456                 bs = gst_buffer_get_size (demux->mdatbuffer);
6457               else
6458                 bs = 0;
6459               if (size + bs > 10 * (1 << 20))
6460                 goto no_moov;
6461               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6462               demux->neededbytes = size;
6463               if (!demux->mdatbuffer)
6464                 demux->mdatoffset = demux->offset;
6465             }
6466           }
6467         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6468           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6469               (_("This file is invalid and cannot be played.")),
6470               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6471                   GST_FOURCC_ARGS (fourcc), size));
6472           ret = GST_FLOW_ERROR;
6473           break;
6474         } else {
6475           /* this means we already started buffering and still no moov header,
6476            * let's continue buffering everything till we get moov */
6477           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6478                   || fourcc == FOURCC_moof))
6479             goto buffer_data;
6480           demux->neededbytes = size;
6481           demux->state = QTDEMUX_STATE_HEADER;
6482         }
6483         break;
6484       }
6485       case QTDEMUX_STATE_HEADER:{
6486         const guint8 *data;
6487         guint32 fourcc;
6488
6489         GST_DEBUG_OBJECT (demux, "In header");
6490
6491         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6492
6493         /* parse the header */
6494         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6495             &fourcc);
6496         if (fourcc == FOURCC_moov) {
6497           gint n;
6498
6499           /* in usual fragmented setup we could try to scan for more
6500            * and end up at the the moov (after mdat) again */
6501           if (demux->got_moov && demux->n_streams > 0 &&
6502               (!demux->fragmented
6503                   || demux->last_moov_offset == demux->offset)) {
6504             GST_DEBUG_OBJECT (demux,
6505                 "Skipping moov atom as we have (this) one already");
6506           } else {
6507             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6508
6509             if (demux->got_moov && demux->fragmented) {
6510               GST_DEBUG_OBJECT (demux,
6511                   "Got a second moov, clean up data from old one");
6512               if (demux->moov_node_compressed) {
6513                 g_node_destroy (demux->moov_node_compressed);
6514                 if (demux->moov_node)
6515                   g_free (demux->moov_node->data);
6516               }
6517               demux->moov_node_compressed = NULL;
6518               if (demux->moov_node)
6519                 g_node_destroy (demux->moov_node);
6520               demux->moov_node = NULL;
6521             } else {
6522               /* prepare newsegment to send when streaming actually starts */
6523               if (!demux->pending_newsegment) {
6524                 demux->pending_newsegment =
6525                     gst_event_new_segment (&demux->segment);
6526                 if (demux->segment_seqnum)
6527                   gst_event_set_seqnum (demux->pending_newsegment,
6528                       demux->segment_seqnum);
6529               }
6530             }
6531
6532             demux->last_moov_offset = demux->offset;
6533
6534             qtdemux_parse_moov (demux, data, demux->neededbytes);
6535             qtdemux_node_dump (demux, demux->moov_node);
6536             qtdemux_parse_tree (demux);
6537             qtdemux_prepare_streams (demux);
6538             if (!demux->got_moov)
6539               qtdemux_expose_streams (demux);
6540             else {
6541
6542               for (n = 0; n < demux->n_streams; n++) {
6543                 QtDemuxStream *stream = demux->streams[n];
6544
6545                 gst_qtdemux_configure_stream (demux, stream);
6546               }
6547             }
6548
6549             demux->got_moov = TRUE;
6550             gst_qtdemux_check_send_pending_segment (demux);
6551
6552             /* fragmented streams headers shouldn't contain edts atoms */
6553             if (!demux->fragmented) {
6554               for (n = 0; n < demux->n_streams; n++) {
6555                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6556                     demux->streams[n]);
6557               }
6558             }
6559
6560             if (demux->moov_node_compressed) {
6561               g_node_destroy (demux->moov_node_compressed);
6562               g_free (demux->moov_node->data);
6563             }
6564             demux->moov_node_compressed = NULL;
6565             g_node_destroy (demux->moov_node);
6566             demux->moov_node = NULL;
6567             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6568           }
6569         } else if (fourcc == FOURCC_moof) {
6570           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6571             guint64 dist = 0;
6572             GstClockTime prev_pts;
6573             guint64 prev_offset;
6574             guint64 adapter_discont_offset, adapter_discont_dist;
6575
6576             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6577
6578             /*
6579              * The timestamp of the moof buffer is relevant as some scenarios
6580              * won't have the initial timestamp in the atoms. Whenever a new
6581              * buffer has started, we get that buffer's PTS and use it as a base
6582              * timestamp for the trun entries.
6583              *
6584              * To keep track of the current buffer timestamp and starting point
6585              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6586              * from the beggining of the buffer, with the distance and demux->offset
6587              * we know if it is still the same buffer or not.
6588              */
6589             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6590             prev_offset = demux->offset - dist;
6591             if (demux->fragment_start_offset == -1
6592                 || prev_offset > demux->fragment_start_offset) {
6593               demux->fragment_start_offset = prev_offset;
6594               demux->fragment_start = prev_pts;
6595               GST_DEBUG_OBJECT (demux,
6596                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6597                   GST_TIME_FORMAT, demux->fragment_start_offset,
6598                   GST_TIME_ARGS (demux->fragment_start));
6599             }
6600
6601             /* We can't use prev_offset() here because this would require
6602              * upstream to set consistent and correct offsets on all buffers
6603              * since the discont. Nothing ever did that in the past and we
6604              * would break backwards compatibility here then.
6605              * Instead take the offset we had at the last discont and count
6606              * the bytes from there. This works with old code as there would
6607              * be no discont between moov and moof, and also works with
6608              * adaptivedemux which correctly sets offset and will set the
6609              * DISCONT flag accordingly when needed.
6610              *
6611              * We also only do this for upstream TIME segments as otherwise
6612              * there are potential backwards compatibility problems with
6613              * seeking in PUSH mode and upstream providing inconsistent
6614              * timestamps. */
6615             adapter_discont_offset =
6616                 gst_adapter_offset_at_discont (demux->adapter);
6617             adapter_discont_dist =
6618                 gst_adapter_distance_from_discont (demux->adapter);
6619
6620             GST_DEBUG_OBJECT (demux,
6621                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6622                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6623                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6624
6625             if (demux->upstream_format_is_time) {
6626               demux->moof_offset = adapter_discont_offset;
6627               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6628                 demux->moof_offset += adapter_discont_dist;
6629               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6630                 demux->moof_offset = demux->offset;
6631             } else {
6632               demux->moof_offset = demux->offset;
6633             }
6634
6635             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6636                     demux->moof_offset, NULL)) {
6637               gst_adapter_unmap (demux->adapter);
6638               ret = GST_FLOW_ERROR;
6639               goto done;
6640             }
6641             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6642             if (demux->mss_mode && !demux->exposed) {
6643               if (!demux->pending_newsegment) {
6644                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6645                 demux->pending_newsegment =
6646                     gst_event_new_segment (&demux->segment);
6647                 if (demux->segment_seqnum)
6648                   gst_event_set_seqnum (demux->pending_newsegment,
6649                       demux->segment_seqnum);
6650               }
6651               qtdemux_expose_streams (demux);
6652             }
6653           } else {
6654             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6655           }
6656         } else if (fourcc == FOURCC_ftyp) {
6657           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6658           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6659         } else if (fourcc == FOURCC_uuid) {
6660           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6661           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6662         } else if (fourcc == FOURCC_sidx) {
6663           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6664           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6665         } else {
6666           switch (fourcc) {
6667             case FOURCC_styp:
6668               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6669                * FALLTHROUGH */
6670             case FOURCC_free:
6671               /* [free] is a padding atom */
6672               GST_DEBUG_OBJECT (demux,
6673                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6674                   GST_FOURCC_ARGS (fourcc));
6675               break;
6676             default:
6677               GST_WARNING_OBJECT (demux,
6678                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6679                   GST_FOURCC_ARGS (fourcc));
6680               /* Let's jump that one and go back to initial state */
6681               break;
6682           }
6683         }
6684         gst_adapter_unmap (demux->adapter);
6685         data = NULL;
6686
6687         if (demux->mdatbuffer && demux->n_streams) {
6688           gsize remaining_data_size = 0;
6689
6690           /* the mdat was before the header */
6691           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6692               demux->n_streams, demux->mdatbuffer);
6693           /* restore our adapter/offset view of things with upstream;
6694            * put preceding buffered data ahead of current moov data.
6695            * This should also handle evil mdat, moov, mdat cases and alike */
6696           gst_adapter_flush (demux->adapter, demux->neededbytes);
6697
6698           /* Store any remaining data after the mdat for later usage */
6699           remaining_data_size = gst_adapter_available (demux->adapter);
6700           if (remaining_data_size > 0) {
6701             g_assert (demux->restoredata_buffer == NULL);
6702             demux->restoredata_buffer =
6703                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6704             demux->restoredata_offset = demux->offset + demux->neededbytes;
6705             GST_DEBUG_OBJECT (demux,
6706                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6707                 G_GUINT64_FORMAT, remaining_data_size,
6708                 demux->restoredata_offset);
6709           }
6710
6711           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6712           demux->mdatbuffer = NULL;
6713           demux->offset = demux->mdatoffset;
6714           demux->neededbytes = next_entry_size (demux);
6715           demux->state = QTDEMUX_STATE_MOVIE;
6716           demux->mdatleft = gst_adapter_available (demux->adapter);
6717           demux->mdatsize = demux->mdatleft;
6718         } else {
6719           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6720           gst_adapter_flush (demux->adapter, demux->neededbytes);
6721
6722           /* only go back to the mdat if there are samples to play */
6723           if (demux->got_moov && demux->first_mdat != -1
6724               && has_next_entry (demux)) {
6725             gboolean res;
6726
6727             /* we need to seek back */
6728             res = qtdemux_seek_offset (demux, demux->first_mdat);
6729             if (res) {
6730               demux->offset = demux->first_mdat;
6731             } else {
6732               GST_DEBUG_OBJECT (demux, "Seek back failed");
6733             }
6734           } else {
6735             demux->offset += demux->neededbytes;
6736           }
6737           demux->neededbytes = 16;
6738           demux->state = QTDEMUX_STATE_INITIAL;
6739         }
6740
6741         break;
6742       }
6743       case QTDEMUX_STATE_BUFFER_MDAT:{
6744         GstBuffer *buf;
6745         guint8 fourcc[4];
6746
6747         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6748             demux->offset);
6749         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6750         gst_buffer_extract (buf, 0, fourcc, 4);
6751         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6752             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6753         if (demux->mdatbuffer)
6754           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6755         else
6756           demux->mdatbuffer = buf;
6757         demux->offset += demux->neededbytes;
6758         demux->neededbytes = 16;
6759         demux->state = QTDEMUX_STATE_INITIAL;
6760         gst_qtdemux_post_progress (demux, 1, 1);
6761
6762         break;
6763       }
6764       case QTDEMUX_STATE_MOVIE:{
6765         QtDemuxStream *stream = NULL;
6766         QtDemuxSample *sample;
6767         int i = -1;
6768         GstClockTime dts, pts, duration;
6769         gboolean keyframe;
6770
6771         GST_DEBUG_OBJECT (demux,
6772             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6773
6774         if (demux->fragmented) {
6775           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6776               demux->mdatleft);
6777           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6778             /* if needed data starts within this atom,
6779              * then it should not exceed this atom */
6780             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6781               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6782                   (_("This file is invalid and cannot be played.")),
6783                   ("sample data crosses atom boundary"));
6784               ret = GST_FLOW_ERROR;
6785               break;
6786             }
6787             demux->mdatleft -= demux->neededbytes;
6788           } else {
6789             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6790             /* so we are dropping more than left in this atom */
6791             gst_qtdemux_drop_data (demux, demux->mdatleft);
6792             demux->mdatleft = 0;
6793
6794             /* need to resume atom parsing so we do not miss any other pieces */
6795             demux->state = QTDEMUX_STATE_INITIAL;
6796             demux->neededbytes = 16;
6797
6798             /* check if there was any stored post mdat data from previous buffers */
6799             if (demux->restoredata_buffer) {
6800               g_assert (gst_adapter_available (demux->adapter) == 0);
6801
6802               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6803               demux->restoredata_buffer = NULL;
6804               demux->offset = demux->restoredata_offset;
6805             }
6806
6807             break;
6808           }
6809         }
6810
6811         if (demux->todrop) {
6812           if (demux->cenc_aux_info_offset > 0) {
6813             GstByteReader br;
6814             const guint8 *data;
6815
6816             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6817             data = gst_adapter_map (demux->adapter, demux->todrop);
6818             gst_byte_reader_init (&br, data + 8, demux->todrop);
6819             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6820                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6821               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6822               ret = GST_FLOW_ERROR;
6823               gst_adapter_unmap (demux->adapter);
6824               g_free (demux->cenc_aux_info_sizes);
6825               demux->cenc_aux_info_sizes = NULL;
6826               goto done;
6827             }
6828             demux->cenc_aux_info_offset = 0;
6829             g_free (demux->cenc_aux_info_sizes);
6830             demux->cenc_aux_info_sizes = NULL;
6831             gst_adapter_unmap (demux->adapter);
6832           }
6833           gst_qtdemux_drop_data (demux, demux->todrop);
6834         }
6835
6836         /* first buffer? */
6837         /* initial newsegment sent here after having added pads,
6838          * possible others in sink_event */
6839         gst_qtdemux_check_send_pending_segment (demux);
6840
6841         /* Figure out which stream this packet belongs to */
6842         for (i = 0; i < demux->n_streams; i++) {
6843           stream = demux->streams[i];
6844           if (stream->sample_index >= stream->n_samples)
6845             continue;
6846           GST_LOG_OBJECT (demux,
6847               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6848               " / size:%d)", i, stream->sample_index,
6849               stream->samples[stream->sample_index].offset,
6850               stream->samples[stream->sample_index].size);
6851
6852           if (stream->samples[stream->sample_index].offset == demux->offset)
6853             break;
6854         }
6855
6856         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6857           goto unknown_stream;
6858
6859         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6860
6861         if (stream->new_caps) {
6862           gst_qtdemux_configure_stream (demux, stream);
6863         }
6864
6865         /* Put data in a buffer, set timestamps, caps, ... */
6866         sample = &stream->samples[stream->sample_index];
6867
6868         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6869           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6870               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6871
6872           dts = QTSAMPLE_DTS (stream, sample);
6873           pts = QTSAMPLE_PTS (stream, sample);
6874           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6875           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6876
6877           /* check for segment end */
6878           if (G_UNLIKELY (demux->segment.stop != -1
6879                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6880             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6881             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6882
6883             /* skip this data, stream is EOS */
6884             gst_adapter_flush (demux->adapter, demux->neededbytes);
6885
6886             /* check if all streams are eos */
6887             ret = GST_FLOW_EOS;
6888             for (i = 0; i < demux->n_streams; i++) {
6889               if (!STREAM_IS_EOS (demux->streams[i])) {
6890                 ret = GST_FLOW_OK;
6891                 break;
6892               }
6893             }
6894
6895             if (ret == GST_FLOW_EOS) {
6896               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6897               goto eos;
6898             }
6899           } else {
6900             GstBuffer *outbuf;
6901
6902             outbuf =
6903                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6904
6905             /* FIXME: should either be an assert or a plain check */
6906             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6907
6908             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6909                 dts, pts, duration, keyframe, dts, demux->offset);
6910           }
6911
6912           /* combine flows */
6913           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6914         } else {
6915           /* skip this data, stream is EOS */
6916           gst_adapter_flush (demux->adapter, demux->neededbytes);
6917         }
6918
6919         stream->sample_index++;
6920         stream->offset_in_sample = 0;
6921
6922         /* update current offset and figure out size of next buffer */
6923         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6924             demux->offset, demux->neededbytes);
6925         demux->offset += demux->neededbytes;
6926         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6927             demux->offset);
6928
6929         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6930           if (demux->fragmented) {
6931             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6932             /* there may be more to follow, only finish this atom */
6933             demux->todrop = demux->mdatleft;
6934             demux->neededbytes = demux->todrop;
6935             break;
6936           }
6937           goto eos;
6938         }
6939         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
6940           goto non_ok_unlinked_flow;
6941         }
6942         break;
6943       }
6944       default:
6945         goto invalid_state;
6946     }
6947   }
6948
6949   /* when buffering movie data, at least show user something is happening */
6950   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6951       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6952     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6953         demux->neededbytes);
6954   }
6955 done:
6956
6957   return ret;
6958
6959   /* ERRORS */
6960 non_ok_unlinked_flow:
6961   {
6962     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6963         gst_flow_get_name (ret));
6964     return ret;
6965   }
6966 unknown_stream:
6967   {
6968     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6969     ret = GST_FLOW_ERROR;
6970     goto done;
6971   }
6972 eos:
6973   {
6974     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6975     ret = GST_FLOW_EOS;
6976     goto done;
6977   }
6978 invalid_state:
6979   {
6980     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6981         (NULL), ("qtdemuxer invalid state %d", demux->state));
6982     ret = GST_FLOW_ERROR;
6983     goto done;
6984   }
6985 no_moov:
6986   {
6987     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6988         (NULL), ("no 'moov' atom within the first 10 MB"));
6989     ret = GST_FLOW_ERROR;
6990     goto done;
6991   }
6992 }
6993
6994 static gboolean
6995 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6996 {
6997   GstQuery *query;
6998   gboolean pull_mode;
6999
7000   query = gst_query_new_scheduling ();
7001
7002   if (!gst_pad_peer_query (sinkpad, query)) {
7003     gst_query_unref (query);
7004     goto activate_push;
7005   }
7006
7007   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7008       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7009   gst_query_unref (query);
7010
7011   if (!pull_mode)
7012     goto activate_push;
7013
7014   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7015   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7016
7017 activate_push:
7018   {
7019     GST_DEBUG_OBJECT (sinkpad, "activating push");
7020     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7021   }
7022 }
7023
7024 static gboolean
7025 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7026     GstPadMode mode, gboolean active)
7027 {
7028   gboolean res;
7029   GstQTDemux *demux = GST_QTDEMUX (parent);
7030
7031   switch (mode) {
7032     case GST_PAD_MODE_PUSH:
7033       demux->pullbased = FALSE;
7034       res = TRUE;
7035       break;
7036     case GST_PAD_MODE_PULL:
7037       if (active) {
7038         demux->pullbased = TRUE;
7039         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7040             sinkpad, NULL);
7041       } else {
7042         res = gst_pad_stop_task (sinkpad);
7043       }
7044       break;
7045     default:
7046       res = FALSE;
7047       break;
7048   }
7049   return res;
7050 }
7051
7052 #ifdef HAVE_ZLIB
7053 static void *
7054 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7055 {
7056   guint8 *buffer;
7057   z_stream z;
7058   int ret;
7059
7060   memset (&z, 0, sizeof (z));
7061   z.zalloc = NULL;
7062   z.zfree = NULL;
7063   z.opaque = NULL;
7064
7065   if ((ret = inflateInit (&z)) != Z_OK) {
7066     GST_ERROR ("inflateInit() returned %d", ret);
7067     return NULL;
7068   }
7069
7070   z.next_in = z_buffer;
7071   z.avail_in = z_length;
7072
7073   buffer = (guint8 *) g_malloc (*length);
7074   z.avail_out = *length;
7075   z.next_out = (Bytef *) buffer;
7076   do {
7077     ret = inflate (&z, Z_NO_FLUSH);
7078     if (ret == Z_STREAM_END) {
7079       break;
7080     } else if (ret != Z_OK) {
7081       GST_WARNING ("inflate() returned %d", ret);
7082       break;
7083     }
7084
7085     *length += 4096;
7086     buffer = (guint8 *) g_realloc (buffer, *length);
7087     z.next_out = (Bytef *) (buffer + z.total_out);
7088     z.avail_out += 4096;
7089   } while (z.avail_in > 0);
7090
7091   if (ret != Z_STREAM_END) {
7092     g_free (buffer);
7093     buffer = NULL;
7094     *length = 0;
7095   } else {
7096     *length = z.total_out;
7097   }
7098
7099   inflateEnd (&z);
7100
7101   return buffer;
7102 }
7103 #endif /* HAVE_ZLIB */
7104
7105 static gboolean
7106 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7107 {
7108   GNode *cmov;
7109
7110   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7111
7112   /* counts as header data */
7113   qtdemux->header_size += length;
7114
7115   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7116   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7117
7118   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7119   if (cmov) {
7120     guint32 method;
7121     GNode *dcom;
7122     GNode *cmvd;
7123     guint32 dcom_len;
7124
7125     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7126     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7127     if (dcom == NULL || cmvd == NULL)
7128       goto invalid_compression;
7129
7130     dcom_len = QT_UINT32 (dcom->data);
7131     if (dcom_len < 12)
7132       goto invalid_compression;
7133
7134     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7135     switch (method) {
7136 #ifdef HAVE_ZLIB
7137       case FOURCC_zlib:{
7138         guint uncompressed_length;
7139         guint compressed_length;
7140         guint8 *buf;
7141         guint32 cmvd_len;
7142
7143         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7144         if (cmvd_len < 12)
7145           goto invalid_compression;
7146
7147         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7148         compressed_length = cmvd_len - 12;
7149         GST_LOG ("length = %u", uncompressed_length);
7150
7151         buf =
7152             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7153             compressed_length, &uncompressed_length);
7154
7155         if (buf) {
7156           qtdemux->moov_node_compressed = qtdemux->moov_node;
7157           qtdemux->moov_node = g_node_new (buf);
7158
7159           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7160               uncompressed_length);
7161         }
7162         break;
7163       }
7164 #endif /* HAVE_ZLIB */
7165       default:
7166         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7167             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7168         break;
7169     }
7170   }
7171   return TRUE;
7172
7173   /* ERRORS */
7174 invalid_compression:
7175   {
7176     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7177     return FALSE;
7178   }
7179 }
7180
7181 static gboolean
7182 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7183     const guint8 * end)
7184 {
7185   while (G_UNLIKELY (buf < end)) {
7186     GNode *child;
7187     guint32 len;
7188
7189     if (G_UNLIKELY (buf + 4 > end)) {
7190       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7191       break;
7192     }
7193     len = QT_UINT32 (buf);
7194     if (G_UNLIKELY (len == 0)) {
7195       GST_LOG_OBJECT (qtdemux, "empty container");
7196       break;
7197     }
7198     if (G_UNLIKELY (len < 8)) {
7199       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7200       break;
7201     }
7202     if (G_UNLIKELY (len > (end - buf))) {
7203       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7204           (gint) (end - buf));
7205       break;
7206     }
7207
7208     child = g_node_new ((guint8 *) buf);
7209     g_node_append (node, child);
7210     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7211     qtdemux_parse_node (qtdemux, child, buf, len);
7212
7213     buf += len;
7214   }
7215   return TRUE;
7216 }
7217
7218 static gboolean
7219 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7220     GNode * xdxt)
7221 {
7222   int len = QT_UINT32 (xdxt->data);
7223   guint8 *buf = xdxt->data;
7224   guint8 *end = buf + len;
7225   GstBuffer *buffer;
7226
7227   /* skip size and type */
7228   buf += 8;
7229   end -= 8;
7230
7231   while (buf < end) {
7232     gint size;
7233     guint32 type;
7234
7235     size = QT_UINT32 (buf);
7236     type = QT_FOURCC (buf + 4);
7237
7238     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7239
7240     if (buf + size > end || size <= 0)
7241       break;
7242
7243     buf += 8;
7244     size -= 8;
7245
7246     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7247         GST_FOURCC_ARGS (type));
7248
7249     switch (type) {
7250       case FOURCC_tCtH:
7251         buffer = gst_buffer_new_and_alloc (size);
7252         gst_buffer_fill (buffer, 0, buf, size);
7253         stream->buffers = g_slist_append (stream->buffers, buffer);
7254         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7255         break;
7256       case FOURCC_tCt_:
7257         buffer = gst_buffer_new_and_alloc (size);
7258         gst_buffer_fill (buffer, 0, buf, size);
7259         stream->buffers = g_slist_append (stream->buffers, buffer);
7260         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7261         break;
7262       case FOURCC_tCtC:
7263         buffer = gst_buffer_new_and_alloc (size);
7264         gst_buffer_fill (buffer, 0, buf, size);
7265         stream->buffers = g_slist_append (stream->buffers, buffer);
7266         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7267         break;
7268       default:
7269         GST_WARNING_OBJECT (qtdemux,
7270             "unknown theora cookie %" GST_FOURCC_FORMAT,
7271             GST_FOURCC_ARGS (type));
7272         break;
7273     }
7274     buf += size;
7275   }
7276   return TRUE;
7277 }
7278
7279 static gboolean
7280 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7281     guint length)
7282 {
7283   guint32 fourcc = 0;
7284   guint32 node_length = 0;
7285   const QtNodeType *type;
7286   const guint8 *end;
7287
7288   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7289
7290   if (G_UNLIKELY (length < 8))
7291     goto not_enough_data;
7292
7293   node_length = QT_UINT32 (buffer);
7294   fourcc = QT_FOURCC (buffer + 4);
7295
7296   /* ignore empty nodes */
7297   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7298     return TRUE;
7299
7300   type = qtdemux_type_get (fourcc);
7301
7302   end = buffer + length;
7303
7304   GST_LOG_OBJECT (qtdemux,
7305       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7306       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7307
7308   if (node_length > length)
7309     goto broken_atom_size;
7310
7311   if (type->flags & QT_FLAG_CONTAINER) {
7312     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7313   } else {
7314     switch (fourcc) {
7315       case FOURCC_stsd:
7316       {
7317         if (node_length < 20) {
7318           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7319           break;
7320         }
7321         GST_DEBUG_OBJECT (qtdemux,
7322             "parsing stsd (sample table, sample description) atom");
7323         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7324         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7325         break;
7326       }
7327       case FOURCC_mp4a:
7328       case FOURCC_alac:
7329       case FOURCC_fLaC:
7330       {
7331         guint32 version;
7332         guint32 offset;
7333         guint min_size;
7334
7335         /* also read alac (or whatever) in stead of mp4a in the following,
7336          * since a similar layout is used in other cases as well */
7337         if (fourcc == FOURCC_mp4a)
7338           min_size = 20;
7339         else if (fourcc == FOURCC_fLaC)
7340           min_size = 86;
7341         else
7342           min_size = 40;
7343
7344         /* There are two things we might encounter here: a true mp4a atom, and
7345            an mp4a entry in an stsd atom. The latter is what we're interested
7346            in, and it looks like an atom, but isn't really one. The true mp4a
7347            atom is short, so we detect it based on length here. */
7348         if (length < min_size) {
7349           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7350               GST_FOURCC_ARGS (fourcc));
7351           break;
7352         }
7353
7354         /* 'version' here is the sound sample description version. Types 0 and
7355            1 are documented in the QTFF reference, but type 2 is not: it's
7356            described in Apple header files instead (struct SoundDescriptionV2
7357            in Movies.h) */
7358         version = QT_UINT16 (buffer + 16);
7359
7360         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7361             GST_FOURCC_ARGS (fourcc), version);
7362
7363         /* parse any esds descriptors */
7364         switch (version) {
7365           case 0:
7366             offset = 0x24;
7367             break;
7368           case 1:
7369             offset = 0x34;
7370             break;
7371           case 2:
7372             offset = 0x48;
7373             break;
7374           default:
7375             GST_WARNING_OBJECT (qtdemux,
7376                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7377                 GST_FOURCC_ARGS (fourcc), version);
7378             offset = 0;
7379             break;
7380         }
7381         if (offset)
7382           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7383         break;
7384       }
7385       case FOURCC_mp4v:
7386       case FOURCC_MP4V:
7387       case FOURCC_fmp4:
7388       case FOURCC_FMP4:
7389       case FOURCC_apcs:
7390       case FOURCC_apch:
7391       case FOURCC_apcn:
7392       case FOURCC_apco:
7393       case FOURCC_ap4h:
7394       case FOURCC_xvid:
7395       case FOURCC_XVID:
7396       case FOURCC_H264:
7397       case FOURCC_avc1:
7398       case FOURCC_avc3:
7399       case FOURCC_H265:
7400       case FOURCC_hvc1:
7401       case FOURCC_hev1:
7402       case FOURCC_mjp2:
7403       case FOURCC_encv:
7404       {
7405         guint32 version;
7406         guint32 str_len;
7407
7408         /* codec_data is contained inside these atoms, which all have
7409          * the same format. */
7410         /* video sample description size is 86 bytes without extension.
7411          * node_length have to be bigger than 86 bytes because video sample
7412          * description can include extenstions such as esds, fiel, glbl, etc. */
7413         if (node_length < 86) {
7414           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7415               " sample description length too short (%u < 86)",
7416               GST_FOURCC_ARGS (fourcc), node_length);
7417           break;
7418         }
7419
7420         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7421             GST_FOURCC_ARGS (fourcc));
7422
7423         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7424          *              its data format.
7425          * revision level (2 bytes) : must be set to 0. */
7426         version = QT_UINT32 (buffer + 16);
7427         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7428
7429         /* compressor name : PASCAL string and informative purposes
7430          * first byte : the number of bytes to be displayed.
7431          *              it has to be less than 32 because it is reserved
7432          *              space of 32 bytes total including itself. */
7433         str_len = QT_UINT8 (buffer + 50);
7434         if (str_len < 32)
7435           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7436               (char *) buffer + 51);
7437         else
7438           GST_WARNING_OBJECT (qtdemux,
7439               "compressorname length too big (%u > 31)", str_len);
7440
7441         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7442             end - buffer);
7443         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7444         break;
7445       }
7446       case FOURCC_meta:
7447       {
7448         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7449         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7450         break;
7451       }
7452       case FOURCC_mp4s:
7453       {
7454         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7455         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7456         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7457         break;
7458       }
7459       case FOURCC_XiTh:
7460       {
7461         guint32 version;
7462         guint32 offset;
7463
7464         if (length < 16) {
7465           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7466               GST_FOURCC_ARGS (fourcc));
7467           break;
7468         }
7469
7470         version = QT_UINT32 (buffer + 12);
7471         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7472
7473         switch (version) {
7474           case 0x00000001:
7475             offset = 0x62;
7476             break;
7477           default:
7478             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7479             offset = 0;
7480             break;
7481         }
7482         if (offset) {
7483           if (length < offset) {
7484             GST_WARNING_OBJECT (qtdemux,
7485                 "skipping too small %" GST_FOURCC_FORMAT " box",
7486                 GST_FOURCC_ARGS (fourcc));
7487             break;
7488           }
7489           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7490         }
7491         break;
7492       }
7493       case FOURCC_in24:
7494       {
7495         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7496         break;
7497       }
7498       case FOURCC_uuid:
7499       {
7500         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7501         break;
7502       }
7503       case FOURCC_enca:
7504       {
7505         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7506         break;
7507       }
7508       default:
7509         if (!strcmp (type->name, "unknown"))
7510           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7511         break;
7512     }
7513   }
7514   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7515       GST_FOURCC_ARGS (fourcc));
7516   return TRUE;
7517
7518 /* ERRORS */
7519 not_enough_data:
7520   {
7521     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7522         (_("This file is corrupt and cannot be played.")),
7523         ("Not enough data for an atom header, got only %u bytes", length));
7524     return FALSE;
7525   }
7526 broken_atom_size:
7527   {
7528     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7529         (_("This file is corrupt and cannot be played.")),
7530         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7531             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7532             length));
7533     return FALSE;
7534   }
7535 }
7536
7537 static GNode *
7538 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7539 {
7540   GNode *child;
7541   guint8 *buffer;
7542   guint32 child_fourcc;
7543
7544   for (child = g_node_first_child (node); child;
7545       child = g_node_next_sibling (child)) {
7546     buffer = (guint8 *) child->data;
7547
7548     child_fourcc = QT_FOURCC (buffer + 4);
7549
7550     if (G_UNLIKELY (child_fourcc == fourcc)) {
7551       return child;
7552     }
7553   }
7554   return NULL;
7555 }
7556
7557 static GNode *
7558 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7559     GstByteReader * parser)
7560 {
7561   GNode *child;
7562   guint8 *buffer;
7563   guint32 child_fourcc, child_len;
7564
7565   for (child = g_node_first_child (node); child;
7566       child = g_node_next_sibling (child)) {
7567     buffer = (guint8 *) child->data;
7568
7569     child_len = QT_UINT32 (buffer);
7570     child_fourcc = QT_FOURCC (buffer + 4);
7571
7572     if (G_UNLIKELY (child_fourcc == fourcc)) {
7573       if (G_UNLIKELY (child_len < (4 + 4)))
7574         return NULL;
7575       /* FIXME: must verify if atom length < parent atom length */
7576       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7577       return child;
7578     }
7579   }
7580   return NULL;
7581 }
7582
7583 static GNode *
7584 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7585 {
7586   return g_node_nth_child (node, index);
7587 }
7588
7589 static GNode *
7590 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7591     GstByteReader * parser)
7592 {
7593   GNode *child;
7594   guint8 *buffer;
7595   guint32 child_fourcc, child_len;
7596
7597   for (child = g_node_next_sibling (node); child;
7598       child = g_node_next_sibling (child)) {
7599     buffer = (guint8 *) child->data;
7600
7601     child_fourcc = QT_FOURCC (buffer + 4);
7602
7603     if (child_fourcc == fourcc) {
7604       if (parser) {
7605         child_len = QT_UINT32 (buffer);
7606         if (G_UNLIKELY (child_len < (4 + 4)))
7607           return NULL;
7608         /* FIXME: must verify if atom length < parent atom length */
7609         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7610       }
7611       return child;
7612     }
7613   }
7614   return NULL;
7615 }
7616
7617 static GNode *
7618 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7619 {
7620   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7621 }
7622
7623 static void
7624 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7625 {
7626 /* FIXME: This can only reliably work if demuxers have a
7627  * separate streaming thread per srcpad. This should be
7628  * done in a demuxer base class, which integrates parts
7629  * of multiqueue
7630  *
7631  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7632  */
7633 #if 0
7634   GstQuery *query;
7635
7636   query = gst_query_new_allocation (stream->caps, FALSE);
7637
7638   if (!gst_pad_peer_query (stream->pad, query)) {
7639     /* not a problem, just debug a little */
7640     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7641   }
7642
7643   if (stream->allocator)
7644     gst_object_unref (stream->allocator);
7645
7646   if (gst_query_get_n_allocation_params (query) > 0) {
7647     /* try the allocator */
7648     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7649         &stream->params);
7650     stream->use_allocator = TRUE;
7651   } else {
7652     stream->allocator = NULL;
7653     gst_allocation_params_init (&stream->params);
7654     stream->use_allocator = FALSE;
7655   }
7656   gst_query_unref (query);
7657 #endif
7658 }
7659
7660 static gboolean
7661 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7662     QtDemuxStream * stream)
7663 {
7664   GstStructure *s;
7665   const gchar *selected_system;
7666
7667   g_return_val_if_fail (qtdemux != NULL, FALSE);
7668   g_return_val_if_fail (stream != NULL, FALSE);
7669   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7670       FALSE);
7671
7672   if (stream->protection_scheme_type != FOURCC_cenc) {
7673     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7674     return FALSE;
7675   }
7676   if (qtdemux->protection_system_ids == NULL) {
7677     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7678         "cenc protection system information has been found");
7679     return FALSE;
7680   }
7681   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7682   selected_system = gst_protection_select_system ((const gchar **)
7683       qtdemux->protection_system_ids->pdata);
7684   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7685       qtdemux->protection_system_ids->len - 1);
7686   if (!selected_system) {
7687     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7688         "suitable decryptor element has been found");
7689     return FALSE;
7690   }
7691
7692   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7693   if (!gst_structure_has_name (s, "application/x-cenc")) {
7694     gst_structure_set (s,
7695         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7696         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7697         NULL);
7698     gst_structure_set_name (s, "application/x-cenc");
7699   }
7700   return TRUE;
7701 }
7702
7703 static gboolean
7704 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7705 {
7706   if (stream->subtype == FOURCC_vide) {
7707     /* fps is calculated base on the duration of the average framerate since
7708      * qt does not have a fixed framerate. */
7709     gboolean fps_available = TRUE;
7710
7711     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7712       /* still frame */
7713       CUR_STREAM (stream)->fps_n = 0;
7714       CUR_STREAM (stream)->fps_d = 1;
7715     } else {
7716       if (stream->duration == 0 || stream->n_samples < 2) {
7717         CUR_STREAM (stream)->fps_n = stream->timescale;
7718         CUR_STREAM (stream)->fps_d = 1;
7719         fps_available = FALSE;
7720       } else {
7721         GstClockTime avg_duration;
7722         guint64 duration;
7723         guint32 n_samples;
7724
7725         /* duration and n_samples can be updated for fragmented format
7726          * so, framerate of fragmented format is calculated using data in a moof */
7727         if (qtdemux->fragmented && stream->n_samples_moof > 0
7728             && stream->duration_moof > 0) {
7729           n_samples = stream->n_samples_moof;
7730           duration = stream->duration_moof;
7731         } else {
7732           n_samples = stream->n_samples;
7733           duration = stream->duration;
7734         }
7735
7736         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7737         /* stream->duration is guint64, timescale, n_samples are guint32 */
7738         avg_duration =
7739             gst_util_uint64_scale_round (duration -
7740             stream->first_duration, GST_SECOND,
7741             (guint64) (stream->timescale) * (n_samples - 1));
7742
7743         GST_LOG_OBJECT (qtdemux,
7744             "Calculating avg sample duration based on stream (or moof) duration %"
7745             G_GUINT64_FORMAT
7746             " minus first sample %u, leaving %d samples gives %"
7747             GST_TIME_FORMAT, duration, stream->first_duration,
7748             n_samples - 1, GST_TIME_ARGS (avg_duration));
7749
7750         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7751             &CUR_STREAM (stream)->fps_d);
7752
7753         GST_DEBUG_OBJECT (qtdemux,
7754             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7755             stream->timescale, CUR_STREAM (stream)->fps_n,
7756             CUR_STREAM (stream)->fps_d);
7757       }
7758     }
7759
7760     if (CUR_STREAM (stream)->caps) {
7761       CUR_STREAM (stream)->caps =
7762           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7763
7764       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7765           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7766           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7767
7768       /* set framerate if calculated framerate is reliable */
7769       if (fps_available) {
7770         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7771             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7772             CUR_STREAM (stream)->fps_d, NULL);
7773       }
7774
7775       /* calculate pixel-aspect-ratio using display width and height */
7776       GST_DEBUG_OBJECT (qtdemux,
7777           "video size %dx%d, target display size %dx%d",
7778           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7779           stream->display_width, stream->display_height);
7780       /* qt file might have pasp atom */
7781       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7782         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7783             CUR_STREAM (stream)->par_h);
7784         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7785             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7786             CUR_STREAM (stream)->par_h, NULL);
7787       } else if (stream->display_width > 0 && stream->display_height > 0
7788           && CUR_STREAM (stream)->width > 0
7789           && CUR_STREAM (stream)->height > 0) {
7790         gint n, d;
7791
7792         /* calculate the pixel aspect ratio using the display and pixel w/h */
7793         n = stream->display_width * CUR_STREAM (stream)->height;
7794         d = stream->display_height * CUR_STREAM (stream)->width;
7795         if (n == d)
7796           n = d = 1;
7797         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7798         CUR_STREAM (stream)->par_w = n;
7799         CUR_STREAM (stream)->par_h = d;
7800         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7801             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7802             CUR_STREAM (stream)->par_h, NULL);
7803       }
7804
7805       if (CUR_STREAM (stream)->interlace_mode > 0) {
7806         if (CUR_STREAM (stream)->interlace_mode == 1) {
7807           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7808               G_TYPE_STRING, "progressive", NULL);
7809         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7810           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7811               G_TYPE_STRING, "interleaved", NULL);
7812           if (CUR_STREAM (stream)->field_order == 9) {
7813             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7814                 G_TYPE_STRING, "top-field-first", NULL);
7815           } else if (CUR_STREAM (stream)->field_order == 14) {
7816             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7817                 G_TYPE_STRING, "bottom-field-first", NULL);
7818           }
7819         }
7820       }
7821
7822       /* Create incomplete colorimetry here if needed */
7823       if (CUR_STREAM (stream)->colorimetry.range ||
7824           CUR_STREAM (stream)->colorimetry.matrix ||
7825           CUR_STREAM (stream)->colorimetry.transfer
7826           || CUR_STREAM (stream)->colorimetry.primaries) {
7827         gchar *colorimetry =
7828             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7829         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7830             G_TYPE_STRING, colorimetry, NULL);
7831         g_free (colorimetry);
7832       }
7833
7834       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7835         guint par_w = 1, par_h = 1;
7836
7837         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7838           par_w = CUR_STREAM (stream)->par_w;
7839           par_h = CUR_STREAM (stream)->par_h;
7840         }
7841
7842         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7843                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7844                 par_h)) {
7845           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7846         }
7847
7848         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7849             "multiview-mode", G_TYPE_STRING,
7850             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7851             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7852             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7853       }
7854     }
7855   }
7856
7857   else if (stream->subtype == FOURCC_soun) {
7858     if (CUR_STREAM (stream)->caps) {
7859       CUR_STREAM (stream)->caps =
7860           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7861       if (CUR_STREAM (stream)->rate > 0)
7862         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7863             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
7864       if (CUR_STREAM (stream)->n_channels > 0)
7865         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7866             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
7867       if (CUR_STREAM (stream)->n_channels > 2) {
7868         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7869          * correctly; this is just the minimum we can do - assume
7870          * we don't actually have any channel positions. */
7871         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7872             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7873       }
7874     }
7875   }
7876
7877   if (stream->pad) {
7878     GstCaps *prev_caps = NULL;
7879
7880     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7881     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7882     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7883     gst_pad_set_active (stream->pad, TRUE);
7884
7885     gst_pad_use_fixed_caps (stream->pad);
7886
7887     if (stream->protected) {
7888       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7889         GST_ERROR_OBJECT (qtdemux,
7890             "Failed to configure protected stream caps.");
7891         return FALSE;
7892       }
7893     }
7894
7895     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7896         CUR_STREAM (stream)->caps);
7897     if (stream->new_stream) {
7898       gchar *stream_id;
7899       GstEvent *event;
7900       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7901
7902       event =
7903           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7904           0);
7905       if (event) {
7906         gst_event_parse_stream_flags (event, &stream_flags);
7907         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7908           qtdemux->have_group_id = TRUE;
7909         else
7910           qtdemux->have_group_id = FALSE;
7911         gst_event_unref (event);
7912       } else if (!qtdemux->have_group_id) {
7913         qtdemux->have_group_id = TRUE;
7914         qtdemux->group_id = gst_util_group_id_next ();
7915       }
7916
7917       stream->new_stream = FALSE;
7918       stream_id =
7919           gst_pad_create_stream_id_printf (stream->pad,
7920           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7921       event = gst_event_new_stream_start (stream_id);
7922       if (qtdemux->have_group_id)
7923         gst_event_set_group_id (event, qtdemux->group_id);
7924       if (stream->disabled)
7925         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7926       if (CUR_STREAM (stream)->sparse) {
7927         stream_flags |= GST_STREAM_FLAG_SPARSE;
7928       } else {
7929         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
7930       }
7931       gst_event_set_stream_flags (event, stream_flags);
7932       gst_pad_push_event (stream->pad, event);
7933       g_free (stream_id);
7934     }
7935
7936     prev_caps = gst_pad_get_current_caps (stream->pad);
7937
7938     if (CUR_STREAM (stream)->caps) {
7939       if (!prev_caps
7940           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
7941         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7942             CUR_STREAM (stream)->caps);
7943         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
7944       } else {
7945         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7946       }
7947     } else {
7948       GST_WARNING_OBJECT (qtdemux, "stream without caps");
7949     }
7950
7951     if (prev_caps)
7952       gst_caps_unref (prev_caps);
7953     stream->new_caps = FALSE;
7954   }
7955   return TRUE;
7956 }
7957
7958 static void
7959 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
7960     QtDemuxStream * stream)
7961 {
7962   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
7963     return;
7964
7965   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
7966       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
7967   if (G_UNLIKELY (stream->stsd_sample_description_id >=
7968           stream->stsd_entries_length)) {
7969     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7970         (_("This file is invalid and cannot be played.")),
7971         ("New sample description id is out of bounds (%d >= %d)",
7972             stream->stsd_sample_description_id, stream->stsd_entries_length));
7973   } else {
7974     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
7975     stream->new_caps = TRUE;
7976   }
7977 }
7978
7979 static gboolean
7980 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7981     QtDemuxStream * stream, GstTagList * list)
7982 {
7983   gboolean ret = TRUE;
7984   /* consistent default for push based mode */
7985   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7986
7987   if (stream->subtype == FOURCC_vide) {
7988     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7989
7990     stream->pad =
7991         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7992     g_free (name);
7993
7994     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7995       gst_object_unref (stream->pad);
7996       stream->pad = NULL;
7997       ret = FALSE;
7998       goto done;
7999     }
8000
8001     qtdemux->n_video_streams++;
8002   } else if (stream->subtype == FOURCC_soun) {
8003     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8004
8005     stream->pad =
8006         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8007     g_free (name);
8008     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8009       gst_object_unref (stream->pad);
8010       stream->pad = NULL;
8011       ret = FALSE;
8012       goto done;
8013     }
8014     qtdemux->n_audio_streams++;
8015   } else if (stream->subtype == FOURCC_strm) {
8016     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8017   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8018       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8019     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8020
8021     stream->pad =
8022         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8023     g_free (name);
8024     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8025       gst_object_unref (stream->pad);
8026       stream->pad = NULL;
8027       ret = FALSE;
8028       goto done;
8029     }
8030     qtdemux->n_sub_streams++;
8031   } else if (CUR_STREAM (stream)->caps) {
8032     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8033
8034     stream->pad =
8035         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8036     g_free (name);
8037     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8038       gst_object_unref (stream->pad);
8039       stream->pad = NULL;
8040       ret = FALSE;
8041       goto done;
8042     }
8043     qtdemux->n_video_streams++;
8044   } else {
8045     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8046     goto done;
8047   }
8048
8049   if (stream->pad) {
8050     GList *l;
8051
8052     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8053         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8054     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8055     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8056
8057     if (stream->stream_tags)
8058       gst_tag_list_unref (stream->stream_tags);
8059     stream->stream_tags = list;
8060     list = NULL;
8061     /* global tags go on each pad anyway */
8062     stream->send_global_tags = TRUE;
8063     /* send upstream GST_EVENT_PROTECTION events that were received before
8064        this source pad was created */
8065     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8066       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8067   }
8068 done:
8069   if (list)
8070     gst_tag_list_unref (list);
8071   return ret;
8072 }
8073
8074 /* find next atom with @fourcc starting at @offset */
8075 static GstFlowReturn
8076 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8077     guint64 * length, guint32 fourcc)
8078 {
8079   GstFlowReturn ret;
8080   guint32 lfourcc;
8081   GstBuffer *buf;
8082
8083   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8084       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8085
8086   while (TRUE) {
8087     GstMapInfo map;
8088
8089     buf = NULL;
8090     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8091     if (G_UNLIKELY (ret != GST_FLOW_OK))
8092       goto locate_failed;
8093     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8094       /* likely EOF */
8095       ret = GST_FLOW_EOS;
8096       gst_buffer_unref (buf);
8097       goto locate_failed;
8098     }
8099     gst_buffer_map (buf, &map, GST_MAP_READ);
8100     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8101     gst_buffer_unmap (buf, &map);
8102     gst_buffer_unref (buf);
8103
8104     if (G_UNLIKELY (*length == 0)) {
8105       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8106       ret = GST_FLOW_ERROR;
8107       goto locate_failed;
8108     }
8109
8110     if (lfourcc == fourcc) {
8111       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8112           *offset);
8113       break;
8114     } else {
8115       GST_LOG_OBJECT (qtdemux,
8116           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8117           GST_FOURCC_ARGS (fourcc), *offset);
8118       *offset += *length;
8119     }
8120   }
8121
8122   return GST_FLOW_OK;
8123
8124 locate_failed:
8125   {
8126     /* might simply have had last one */
8127     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8128     return ret;
8129   }
8130 }
8131
8132 /* should only do something in pull mode */
8133 /* call with OBJECT lock */
8134 static GstFlowReturn
8135 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8136 {
8137   guint64 length, offset;
8138   GstBuffer *buf = NULL;
8139   GstFlowReturn ret = GST_FLOW_OK;
8140   GstFlowReturn res = GST_FLOW_OK;
8141   GstMapInfo map;
8142
8143   offset = qtdemux->moof_offset;
8144   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8145
8146   if (!offset) {
8147     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8148     return GST_FLOW_EOS;
8149   }
8150
8151   /* best not do pull etc with lock held */
8152   GST_OBJECT_UNLOCK (qtdemux);
8153
8154   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8155   if (ret != GST_FLOW_OK)
8156     goto flow_failed;
8157
8158   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8159   if (G_UNLIKELY (ret != GST_FLOW_OK))
8160     goto flow_failed;
8161   gst_buffer_map (buf, &map, GST_MAP_READ);
8162   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8163     gst_buffer_unmap (buf, &map);
8164     gst_buffer_unref (buf);
8165     buf = NULL;
8166     goto parse_failed;
8167   }
8168
8169   gst_buffer_unmap (buf, &map);
8170   gst_buffer_unref (buf);
8171   buf = NULL;
8172
8173   offset += length;
8174   /* look for next moof */
8175   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8176   if (G_UNLIKELY (ret != GST_FLOW_OK))
8177     goto flow_failed;
8178
8179 exit:
8180   GST_OBJECT_LOCK (qtdemux);
8181
8182   qtdemux->moof_offset = offset;
8183
8184   return res;
8185
8186 parse_failed:
8187   {
8188     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8189     offset = 0;
8190     res = GST_FLOW_ERROR;
8191     goto exit;
8192   }
8193 flow_failed:
8194   {
8195     /* maybe upstream temporarily flushing */
8196     if (ret != GST_FLOW_FLUSHING) {
8197       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8198       offset = 0;
8199     } else {
8200       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8201       /* resume at current position next time */
8202     }
8203     res = ret;
8204     goto exit;
8205   }
8206 }
8207
8208 /* initialise bytereaders for stbl sub-atoms */
8209 static gboolean
8210 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8211 {
8212   stream->stbl_index = -1;      /* no samples have yet been parsed */
8213   stream->sample_index = -1;
8214
8215   /* time-to-sample atom */
8216   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8217     goto corrupt_file;
8218
8219   /* copy atom data into a new buffer for later use */
8220   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8221
8222   /* skip version + flags */
8223   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8224       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8225     goto corrupt_file;
8226   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8227
8228   /* make sure there's enough data */
8229   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8230     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8231     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8232         stream->n_sample_times);
8233     if (!stream->n_sample_times)
8234       goto corrupt_file;
8235   }
8236
8237   /* sync sample atom */
8238   stream->stps_present = FALSE;
8239   if ((stream->stss_present =
8240           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8241               &stream->stss) ? TRUE : FALSE) == TRUE) {
8242     /* copy atom data into a new buffer for later use */
8243     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8244
8245     /* skip version + flags */
8246     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8247         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8248       goto corrupt_file;
8249
8250     if (stream->n_sample_syncs) {
8251       /* make sure there's enough data */
8252       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8253         goto corrupt_file;
8254     }
8255
8256     /* partial sync sample atom */
8257     if ((stream->stps_present =
8258             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8259                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8260       /* copy atom data into a new buffer for later use */
8261       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8262
8263       /* skip version + flags */
8264       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8265           !gst_byte_reader_get_uint32_be (&stream->stps,
8266               &stream->n_sample_partial_syncs))
8267         goto corrupt_file;
8268
8269       /* if there are no entries, the stss table contains the real
8270        * sync samples */
8271       if (stream->n_sample_partial_syncs) {
8272         /* make sure there's enough data */
8273         if (!qt_atom_parser_has_chunks (&stream->stps,
8274                 stream->n_sample_partial_syncs, 4))
8275           goto corrupt_file;
8276       }
8277     }
8278   }
8279
8280   /* sample size */
8281   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8282     goto no_samples;
8283
8284   /* copy atom data into a new buffer for later use */
8285   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8286
8287   /* skip version + flags */
8288   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8289       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8290     goto corrupt_file;
8291
8292   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8293     goto corrupt_file;
8294
8295   if (!stream->n_samples)
8296     goto no_samples;
8297
8298   /* sample-to-chunk atom */
8299   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8300     goto corrupt_file;
8301
8302   /* copy atom data into a new buffer for later use */
8303   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8304
8305   /* skip version + flags */
8306   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8307       !gst_byte_reader_get_uint32_be (&stream->stsc,
8308           &stream->n_samples_per_chunk))
8309     goto corrupt_file;
8310
8311   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8312       stream->n_samples_per_chunk);
8313
8314   /* make sure there's enough data */
8315   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8316           12))
8317     goto corrupt_file;
8318
8319
8320   /* chunk offset */
8321   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8322     stream->co_size = sizeof (guint32);
8323   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8324           &stream->stco))
8325     stream->co_size = sizeof (guint64);
8326   else
8327     goto corrupt_file;
8328
8329   /* copy atom data into a new buffer for later use */
8330   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8331
8332   /* skip version + flags */
8333   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8334     goto corrupt_file;
8335
8336   /* chunks_are_samples == TRUE means treat chunks as samples */
8337   stream->chunks_are_samples = stream->sample_size
8338       && !CUR_STREAM (stream)->sampled;
8339   if (stream->chunks_are_samples) {
8340     /* treat chunks as samples */
8341     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8342       goto corrupt_file;
8343   } else {
8344     /* skip number of entries */
8345     if (!gst_byte_reader_skip (&stream->stco, 4))
8346       goto corrupt_file;
8347
8348     /* make sure there are enough data in the stsz atom */
8349     if (!stream->sample_size) {
8350       /* different sizes for each sample */
8351       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8352         goto corrupt_file;
8353     }
8354   }
8355
8356   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8357       stream->n_samples, (guint) sizeof (QtDemuxSample),
8358       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8359
8360   if (stream->n_samples >=
8361       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8362     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8363         "be larger than %uMB (broken file?)", stream->n_samples,
8364         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8365     return FALSE;
8366   }
8367
8368   g_assert (stream->samples == NULL);
8369   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8370   if (!stream->samples) {
8371     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8372         stream->n_samples);
8373     return FALSE;
8374   }
8375
8376   /* composition time-to-sample */
8377   if ((stream->ctts_present =
8378           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8379               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8380     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8381
8382     /* copy atom data into a new buffer for later use */
8383     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8384
8385     /* skip version + flags */
8386     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8387         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8388             &stream->n_composition_times))
8389       goto corrupt_file;
8390
8391     /* make sure there's enough data */
8392     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8393             4 + 4))
8394       goto corrupt_file;
8395
8396     /* This is optional, if missing we iterate the ctts */
8397     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8398       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8399           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8400         g_free ((gpointer) cslg.data);
8401         goto corrupt_file;
8402       }
8403     } else {
8404       gint32 cslg_least = 0;
8405       guint num_entries, pos;
8406       gint i;
8407
8408       pos = gst_byte_reader_get_pos (&stream->ctts);
8409       num_entries = stream->n_composition_times;
8410
8411       stream->cslg_shift = 0;
8412
8413       for (i = 0; i < num_entries; i++) {
8414         gint32 offset;
8415
8416         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8417         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8418
8419         if (offset < cslg_least)
8420           cslg_least = offset;
8421       }
8422
8423       if (cslg_least < 0)
8424         stream->cslg_shift = ABS (cslg_least);
8425       else
8426         stream->cslg_shift = 0;
8427
8428       /* reset the reader so we can generate sample table */
8429       gst_byte_reader_set_pos (&stream->ctts, pos);
8430     }
8431   } else {
8432     /* Ensure the cslg_shift value is consistent so we can use it
8433      * unconditionnally to produce TS and Segment */
8434     stream->cslg_shift = 0;
8435   }
8436
8437   return TRUE;
8438
8439 corrupt_file:
8440   {
8441     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8442         (_("This file is corrupt and cannot be played.")), (NULL));
8443     return FALSE;
8444   }
8445 no_samples:
8446   {
8447     gst_qtdemux_stbl_free (stream);
8448     if (!qtdemux->fragmented) {
8449       /* not quite good */
8450       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8451       return FALSE;
8452     } else {
8453       /* may pick up samples elsewhere */
8454       return TRUE;
8455     }
8456   }
8457 }
8458
8459 /* collect samples from the next sample to be parsed up to sample @n for @stream
8460  * by reading the info from @stbl
8461  *
8462  * This code can be executed from both the streaming thread and the seeking
8463  * thread so it takes the object lock to protect itself
8464  */
8465 static gboolean
8466 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8467 {
8468   gint i, j, k;
8469   QtDemuxSample *samples, *first, *cur, *last;
8470   guint32 n_samples_per_chunk;
8471   guint32 n_samples;
8472
8473   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8474       GST_FOURCC_FORMAT ", pad %s",
8475       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8476       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8477
8478   n_samples = stream->n_samples;
8479
8480   if (n >= n_samples)
8481     goto out_of_samples;
8482
8483   GST_OBJECT_LOCK (qtdemux);
8484   if (n <= stream->stbl_index)
8485     goto already_parsed;
8486
8487   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8488
8489   if (!stream->stsz.data) {
8490     /* so we already parsed and passed all the moov samples;
8491      * onto fragmented ones */
8492     g_assert (qtdemux->fragmented);
8493     goto done;
8494   }
8495
8496   /* pointer to the sample table */
8497   samples = stream->samples;
8498
8499   /* starts from -1, moves to the next sample index to parse */
8500   stream->stbl_index++;
8501
8502   /* keep track of the first and last sample to fill */
8503   first = &samples[stream->stbl_index];
8504   last = &samples[n];
8505
8506   if (!stream->chunks_are_samples) {
8507     /* set the sample sizes */
8508     if (stream->sample_size == 0) {
8509       /* different sizes for each sample */
8510       for (cur = first; cur <= last; cur++) {
8511         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8512         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8513             (guint) (cur - samples), cur->size);
8514       }
8515     } else {
8516       /* samples have the same size */
8517       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8518       for (cur = first; cur <= last; cur++)
8519         cur->size = stream->sample_size;
8520     }
8521   }
8522
8523   n_samples_per_chunk = stream->n_samples_per_chunk;
8524   cur = first;
8525
8526   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8527     guint32 last_chunk;
8528
8529     if (stream->stsc_chunk_index >= stream->last_chunk
8530         || stream->stsc_chunk_index < stream->first_chunk) {
8531       stream->first_chunk =
8532           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8533       stream->samples_per_chunk =
8534           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8535       /* starts from 1 */
8536       stream->stsd_sample_description_id =
8537           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8538
8539       /* chunk numbers are counted from 1 it seems */
8540       if (G_UNLIKELY (stream->first_chunk == 0))
8541         goto corrupt_file;
8542
8543       --stream->first_chunk;
8544
8545       /* the last chunk of each entry is calculated by taking the first chunk
8546        * of the next entry; except if there is no next, where we fake it with
8547        * INT_MAX */
8548       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8549         stream->last_chunk = G_MAXUINT32;
8550       } else {
8551         stream->last_chunk =
8552             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8553         if (G_UNLIKELY (stream->last_chunk == 0))
8554           goto corrupt_file;
8555
8556         --stream->last_chunk;
8557       }
8558
8559       GST_LOG_OBJECT (qtdemux,
8560           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8561           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8562           stream->samples_per_chunk, stream->stsd_sample_description_id);
8563
8564       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8565         goto corrupt_file;
8566
8567       if (stream->last_chunk != G_MAXUINT32) {
8568         if (!qt_atom_parser_peek_sub (&stream->stco,
8569                 stream->first_chunk * stream->co_size,
8570                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8571                 &stream->co_chunk))
8572           goto corrupt_file;
8573
8574       } else {
8575         stream->co_chunk = stream->stco;
8576         if (!gst_byte_reader_skip (&stream->co_chunk,
8577                 stream->first_chunk * stream->co_size))
8578           goto corrupt_file;
8579       }
8580
8581       stream->stsc_chunk_index = stream->first_chunk;
8582     }
8583
8584     last_chunk = stream->last_chunk;
8585
8586     if (stream->chunks_are_samples) {
8587       cur = &samples[stream->stsc_chunk_index];
8588
8589       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8590         if (j > n) {
8591           /* save state */
8592           stream->stsc_chunk_index = j;
8593           goto done;
8594         }
8595
8596         cur->offset =
8597             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8598             stream->co_size);
8599
8600         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8601             "%" G_GUINT64_FORMAT, j, cur->offset);
8602
8603         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8604             CUR_STREAM (stream)->bytes_per_frame > 0) {
8605           cur->size =
8606               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8607               CUR_STREAM (stream)->samples_per_frame *
8608               CUR_STREAM (stream)->bytes_per_frame;
8609         } else {
8610           cur->size = stream->samples_per_chunk;
8611         }
8612
8613         GST_DEBUG_OBJECT (qtdemux,
8614             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8615             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8616                     stream->stco_sample_index)), cur->size);
8617
8618         cur->timestamp = stream->stco_sample_index;
8619         cur->duration = stream->samples_per_chunk;
8620         cur->keyframe = TRUE;
8621         cur++;
8622
8623         stream->stco_sample_index += stream->samples_per_chunk;
8624       }
8625       stream->stsc_chunk_index = j;
8626     } else {
8627       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8628         guint32 samples_per_chunk;
8629         guint64 chunk_offset;
8630
8631         if (!stream->stsc_sample_index
8632             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8633                 &stream->chunk_offset))
8634           goto corrupt_file;
8635
8636         samples_per_chunk = stream->samples_per_chunk;
8637         chunk_offset = stream->chunk_offset;
8638
8639         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8640           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8641               G_GUINT64_FORMAT " and size %d",
8642               (guint) (cur - samples), chunk_offset, cur->size);
8643
8644           cur->offset = chunk_offset;
8645           chunk_offset += cur->size;
8646           cur++;
8647
8648           if (G_UNLIKELY (cur > last)) {
8649             /* save state */
8650             stream->stsc_sample_index = k + 1;
8651             stream->chunk_offset = chunk_offset;
8652             stream->stsc_chunk_index = j;
8653             goto done2;
8654           }
8655         }
8656         stream->stsc_sample_index = 0;
8657       }
8658       stream->stsc_chunk_index = j;
8659     }
8660     stream->stsc_index++;
8661   }
8662
8663   if (stream->chunks_are_samples)
8664     goto ctts;
8665 done2:
8666   {
8667     guint32 n_sample_times;
8668
8669     n_sample_times = stream->n_sample_times;
8670     cur = first;
8671
8672     for (i = stream->stts_index; i < n_sample_times; i++) {
8673       guint32 stts_samples;
8674       gint32 stts_duration;
8675       gint64 stts_time;
8676
8677       if (stream->stts_sample_index >= stream->stts_samples
8678           || !stream->stts_sample_index) {
8679
8680         stream->stts_samples =
8681             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8682         stream->stts_duration =
8683             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8684
8685         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8686             i, stream->stts_samples, stream->stts_duration);
8687
8688         stream->stts_sample_index = 0;
8689       }
8690
8691       stts_samples = stream->stts_samples;
8692       stts_duration = stream->stts_duration;
8693       stts_time = stream->stts_time;
8694
8695       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8696         GST_DEBUG_OBJECT (qtdemux,
8697             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8698             (guint) (cur - samples), j,
8699             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8700
8701         cur->timestamp = stts_time;
8702         cur->duration = stts_duration;
8703
8704         /* avoid 32-bit wrap-around,
8705          * but still mind possible 'negative' duration */
8706         stts_time += (gint64) stts_duration;
8707         cur++;
8708
8709         if (G_UNLIKELY (cur > last)) {
8710           /* save values */
8711           stream->stts_time = stts_time;
8712           stream->stts_sample_index = j + 1;
8713           if (stream->stts_sample_index >= stream->stts_samples)
8714             stream->stts_index++;
8715           goto done3;
8716         }
8717       }
8718       stream->stts_sample_index = 0;
8719       stream->stts_time = stts_time;
8720       stream->stts_index++;
8721     }
8722     /* fill up empty timestamps with the last timestamp, this can happen when
8723      * the last samples do not decode and so we don't have timestamps for them.
8724      * We however look at the last timestamp to estimate the track length so we
8725      * need something in here. */
8726     for (; cur < last; cur++) {
8727       GST_DEBUG_OBJECT (qtdemux,
8728           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8729           (guint) (cur - samples),
8730           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8731       cur->timestamp = stream->stts_time;
8732       cur->duration = -1;
8733     }
8734   }
8735 done3:
8736   {
8737     /* sample sync, can be NULL */
8738     if (stream->stss_present == TRUE) {
8739       guint32 n_sample_syncs;
8740
8741       n_sample_syncs = stream->n_sample_syncs;
8742
8743       if (!n_sample_syncs) {
8744         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8745         stream->all_keyframe = TRUE;
8746       } else {
8747         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8748           /* note that the first sample is index 1, not 0 */
8749           guint32 index;
8750
8751           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8752
8753           if (G_LIKELY (index > 0 && index <= n_samples)) {
8754             index -= 1;
8755             samples[index].keyframe = TRUE;
8756             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8757             /* and exit if we have enough samples */
8758             if (G_UNLIKELY (index >= n)) {
8759               i++;
8760               break;
8761             }
8762           }
8763         }
8764         /* save state */
8765         stream->stss_index = i;
8766       }
8767
8768       /* stps marks partial sync frames like open GOP I-Frames */
8769       if (stream->stps_present == TRUE) {
8770         guint32 n_sample_partial_syncs;
8771
8772         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8773
8774         /* if there are no entries, the stss table contains the real
8775          * sync samples */
8776         if (n_sample_partial_syncs) {
8777           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8778             /* note that the first sample is index 1, not 0 */
8779             guint32 index;
8780
8781             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8782
8783             if (G_LIKELY (index > 0 && index <= n_samples)) {
8784               index -= 1;
8785               samples[index].keyframe = TRUE;
8786               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8787               /* and exit if we have enough samples */
8788               if (G_UNLIKELY (index >= n)) {
8789                 i++;
8790                 break;
8791               }
8792             }
8793           }
8794           /* save state */
8795           stream->stps_index = i;
8796         }
8797       }
8798     } else {
8799       /* no stss, all samples are keyframes */
8800       stream->all_keyframe = TRUE;
8801       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8802     }
8803   }
8804
8805 ctts:
8806   /* composition time to sample */
8807   if (stream->ctts_present == TRUE) {
8808     guint32 n_composition_times;
8809     guint32 ctts_count;
8810     gint32 ctts_soffset;
8811
8812     /* Fill in the pts_offsets */
8813     cur = first;
8814     n_composition_times = stream->n_composition_times;
8815
8816     for (i = stream->ctts_index; i < n_composition_times; i++) {
8817       if (stream->ctts_sample_index >= stream->ctts_count
8818           || !stream->ctts_sample_index) {
8819         stream->ctts_count =
8820             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8821         stream->ctts_soffset =
8822             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8823         stream->ctts_sample_index = 0;
8824       }
8825
8826       ctts_count = stream->ctts_count;
8827       ctts_soffset = stream->ctts_soffset;
8828
8829       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8830         cur->pts_offset = ctts_soffset;
8831         cur++;
8832
8833         if (G_UNLIKELY (cur > last)) {
8834           /* save state */
8835           stream->ctts_sample_index = j + 1;
8836           goto done;
8837         }
8838       }
8839       stream->ctts_sample_index = 0;
8840       stream->ctts_index++;
8841     }
8842   }
8843 done:
8844   stream->stbl_index = n;
8845   /* if index has been completely parsed, free data that is no-longer needed */
8846   if (n + 1 == stream->n_samples) {
8847     gst_qtdemux_stbl_free (stream);
8848     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8849     if (qtdemux->pullbased) {
8850       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8851       while (n + 1 == stream->n_samples)
8852         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8853           break;
8854     }
8855   }
8856   GST_OBJECT_UNLOCK (qtdemux);
8857
8858   return TRUE;
8859
8860   /* SUCCESS */
8861 already_parsed:
8862   {
8863     GST_LOG_OBJECT (qtdemux,
8864         "Tried to parse up to sample %u but this sample has already been parsed",
8865         n);
8866     /* if fragmented, there may be more */
8867     if (qtdemux->fragmented && n == stream->stbl_index)
8868       goto done;
8869     GST_OBJECT_UNLOCK (qtdemux);
8870     return TRUE;
8871   }
8872   /* ERRORS */
8873 out_of_samples:
8874   {
8875     GST_LOG_OBJECT (qtdemux,
8876         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8877         stream->n_samples);
8878     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8879         (_("This file is corrupt and cannot be played.")), (NULL));
8880     return FALSE;
8881   }
8882 corrupt_file:
8883   {
8884     GST_OBJECT_UNLOCK (qtdemux);
8885     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8886         (_("This file is corrupt and cannot be played.")), (NULL));
8887     return FALSE;
8888   }
8889 }
8890
8891 /* collect all segment info for @stream.
8892  */
8893 static gboolean
8894 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8895     GNode * trak)
8896 {
8897   GNode *edts;
8898   /* accept edts if they contain gaps at start and there is only
8899    * one media segment */
8900   gboolean allow_pushbased_edts = TRUE;
8901   gint media_segments_count = 0;
8902
8903   /* parse and prepare segment info from the edit list */
8904   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8905   stream->n_segments = 0;
8906   stream->segments = NULL;
8907   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8908     GNode *elst;
8909     gint n_segments;
8910     gint i, count, entry_size;
8911     guint64 time;
8912     GstClockTime stime;
8913     const guint8 *buffer;
8914     guint8 version;
8915     guint32 size;
8916
8917     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8918     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8919       goto done;
8920
8921     buffer = elst->data;
8922
8923     size = QT_UINT32 (buffer);
8924     /* version, flags, n_segments */
8925     if (size < 16) {
8926       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8927       goto done;
8928     }
8929     version = QT_UINT8 (buffer + 8);
8930     entry_size = (version == 1) ? 20 : 12;
8931
8932     n_segments = QT_UINT32 (buffer + 12);
8933
8934     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
8935       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8936       goto done;
8937     }
8938
8939     /* we might allocate a bit too much, at least allocate 1 segment */
8940     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8941
8942     /* segments always start from 0 */
8943     time = 0;
8944     stime = 0;
8945     count = 0;
8946     buffer += 16;
8947     for (i = 0; i < n_segments; i++) {
8948       guint64 duration;
8949       guint64 media_time;
8950       gboolean time_valid = TRUE;
8951       QtDemuxSegment *segment;
8952       guint32 rate_int;
8953       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8954
8955       if (version == 1) {
8956         media_time = QT_UINT64 (buffer + 8);
8957         duration = QT_UINT64 (buffer);
8958         if (media_time == G_MAXUINT64)
8959           time_valid = FALSE;
8960       } else {
8961         media_time = QT_UINT32 (buffer + 4);
8962         duration = QT_UINT32 (buffer);
8963         if (media_time == G_MAXUINT32)
8964           time_valid = FALSE;
8965       }
8966
8967       if (time_valid)
8968         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8969
8970       segment = &stream->segments[count++];
8971
8972       /* time and duration expressed in global timescale */
8973       segment->time = stime;
8974       /* add non scaled values so we don't cause roundoff errors */
8975       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8976         time += duration;
8977         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8978         segment->duration = stime - segment->time;
8979       } else {
8980         /* zero duration does not imply media_start == media_stop
8981          * but, only specify media_start.*/
8982         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8983         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8984             && stime >= media_start) {
8985           segment->duration = stime - media_start;
8986         } else {
8987           segment->duration = GST_CLOCK_TIME_NONE;
8988         }
8989       }
8990       segment->stop_time = stime;
8991
8992       segment->trak_media_start = media_time;
8993       /* media_time expressed in stream timescale */
8994       if (time_valid) {
8995         segment->media_start = media_start;
8996         segment->media_stop = segment->media_start + segment->duration;
8997         media_segments_count++;
8998       } else {
8999         segment->media_start = GST_CLOCK_TIME_NONE;
9000         segment->media_stop = GST_CLOCK_TIME_NONE;
9001       }
9002       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9003
9004       if (rate_int <= 1) {
9005         /* 0 is not allowed, some programs write 1 instead of the floating point
9006          * value */
9007         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9008             rate_int);
9009         segment->rate = 1;
9010       } else {
9011         segment->rate = rate_int / 65536.0;
9012       }
9013
9014       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9015           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9016           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9017           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9018           i, GST_TIME_ARGS (segment->time),
9019           GST_TIME_ARGS (segment->duration),
9020           GST_TIME_ARGS (segment->media_start), media_time,
9021           GST_TIME_ARGS (segment->media_stop),
9022           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9023           stream->timescale);
9024       if (segment->stop_time > qtdemux->segment.stop) {
9025         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9026             " extends to %" GST_TIME_FORMAT
9027             " past the end of the file duration %" GST_TIME_FORMAT
9028             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9029             GST_TIME_ARGS (qtdemux->segment.stop));
9030         qtdemux->segment.stop = segment->stop_time;
9031       }
9032
9033       buffer += entry_size;
9034     }
9035     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9036     stream->n_segments = count;
9037     if (media_segments_count != 1)
9038       allow_pushbased_edts = FALSE;
9039   }
9040 done:
9041
9042   /* push based does not handle segments, so act accordingly here,
9043    * and warn if applicable */
9044   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9045     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9046     /* remove and use default one below, we stream like it anyway */
9047     g_free (stream->segments);
9048     stream->segments = NULL;
9049     stream->n_segments = 0;
9050   }
9051
9052   /* no segments, create one to play the complete trak */
9053   if (stream->n_segments == 0) {
9054     GstClockTime stream_duration =
9055         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9056
9057     if (stream->segments == NULL)
9058       stream->segments = g_new (QtDemuxSegment, 1);
9059
9060     /* represent unknown our way */
9061     if (stream_duration == 0)
9062       stream_duration = GST_CLOCK_TIME_NONE;
9063
9064     stream->segments[0].time = 0;
9065     stream->segments[0].stop_time = stream_duration;
9066     stream->segments[0].duration = stream_duration;
9067     stream->segments[0].media_start = 0;
9068     stream->segments[0].media_stop = stream_duration;
9069     stream->segments[0].rate = 1.0;
9070     stream->segments[0].trak_media_start = 0;
9071
9072     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9073         GST_TIME_ARGS (stream_duration));
9074     stream->n_segments = 1;
9075     stream->dummy_segment = TRUE;
9076   }
9077   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9078
9079   return TRUE;
9080 }
9081
9082 /*
9083  * Parses the stsd atom of a svq3 trak looking for
9084  * the SMI and gama atoms.
9085  */
9086 static void
9087 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9088     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9089 {
9090   const guint8 *_gamma = NULL;
9091   GstBuffer *_seqh = NULL;
9092   const guint8 *stsd_data = stsd_entry_data;
9093   guint32 length = QT_UINT32 (stsd_data);
9094   guint16 version;
9095
9096   if (length < 32) {
9097     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9098     goto end;
9099   }
9100
9101   stsd_data += 16;
9102   length -= 16;
9103   version = QT_UINT16 (stsd_data);
9104   if (version == 3) {
9105     if (length >= 70) {
9106       length -= 70;
9107       stsd_data += 70;
9108       while (length > 8) {
9109         guint32 fourcc, size;
9110         const guint8 *data;
9111         size = QT_UINT32 (stsd_data);
9112         fourcc = QT_FOURCC (stsd_data + 4);
9113         data = stsd_data + 8;
9114
9115         if (size == 0) {
9116           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9117               "svq3 atom parsing");
9118           goto end;
9119         }
9120
9121         switch (fourcc) {
9122           case FOURCC_gama:{
9123             if (size == 12) {
9124               _gamma = data;
9125             } else {
9126               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9127                   " for gama atom, expected 12", size);
9128             }
9129             break;
9130           }
9131           case FOURCC_SMI_:{
9132             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9133               guint32 seqh_size;
9134               if (_seqh != NULL) {
9135                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9136                     " found, ignoring");
9137               } else {
9138                 seqh_size = QT_UINT32 (data + 4);
9139                 if (seqh_size > 0) {
9140                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9141                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9142                 }
9143               }
9144             }
9145             break;
9146           }
9147           default:{
9148             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9149                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9150           }
9151         }
9152
9153         if (size <= length) {
9154           length -= size;
9155           stsd_data += size;
9156         }
9157       }
9158     } else {
9159       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9160     }
9161   } else {
9162     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9163         G_GUINT16_FORMAT, version);
9164     goto end;
9165   }
9166
9167 end:
9168   if (gamma) {
9169     *gamma = _gamma;
9170   }
9171   if (seqh) {
9172     *seqh = _seqh;
9173   } else if (_seqh) {
9174     gst_buffer_unref (_seqh);
9175   }
9176 }
9177
9178 static gchar *
9179 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9180 {
9181   GNode *dinf;
9182   GstByteReader dref;
9183   gchar *uri = NULL;
9184
9185   /*
9186    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9187    * atom that might contain a 'data' atom with the rtsp uri.
9188    * This case was reported in bug #597497, some info about
9189    * the hndl atom can be found in TN1195
9190    */
9191   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9192   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9193
9194   if (dinf) {
9195     guint32 dref_num_entries = 0;
9196     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9197         gst_byte_reader_skip (&dref, 4) &&
9198         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9199       gint i;
9200
9201       /* search dref entries for hndl atom */
9202       for (i = 0; i < dref_num_entries; i++) {
9203         guint32 size = 0, type;
9204         guint8 string_len = 0;
9205         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9206             qt_atom_parser_get_fourcc (&dref, &type)) {
9207           if (type == FOURCC_hndl) {
9208             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9209
9210             /* skip data reference handle bytes and the
9211              * following pascal string and some extra 4
9212              * bytes I have no idea what are */
9213             if (!gst_byte_reader_skip (&dref, 4) ||
9214                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9215                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9216               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9217               break;
9218             }
9219
9220             /* iterate over the atoms to find the data atom */
9221             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9222               guint32 atom_size;
9223               guint32 atom_type;
9224
9225               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9226                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9227                 if (atom_type == FOURCC_data) {
9228                   const guint8 *uri_aux = NULL;
9229
9230                   /* found the data atom that might contain the rtsp uri */
9231                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9232                       "hndl atom, interpreting it as an URI");
9233                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9234                           &uri_aux)) {
9235                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9236                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9237                     else
9238                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9239                           "didn't contain a rtsp address");
9240                   } else {
9241                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9242                         "atom contents");
9243                   }
9244                   break;
9245                 }
9246                 /* skipping to the next entry */
9247                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9248                   break;
9249               } else {
9250                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9251                     "atom header");
9252                 break;
9253               }
9254             }
9255             break;
9256           }
9257           /* skip to the next entry */
9258           if (!gst_byte_reader_skip (&dref, size - 8))
9259             break;
9260         } else {
9261           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9262         }
9263       }
9264       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9265     }
9266   }
9267   return uri;
9268 }
9269
9270 #define AMR_NB_ALL_MODES        0x81ff
9271 #define AMR_WB_ALL_MODES        0x83ff
9272 static guint
9273 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9274 {
9275   /* The 'damr' atom is of the form:
9276    *
9277    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9278    *    32 b       8 b          16 b           8 b                 8 b
9279    *
9280    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9281    * represents the highest mode used in the stream (and thus the maximum
9282    * bitrate), with a couple of special cases as seen below.
9283    */
9284
9285   /* Map of frame type ID -> bitrate */
9286   static const guint nb_bitrates[] = {
9287     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9288   };
9289   static const guint wb_bitrates[] = {
9290     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9291   };
9292   GstMapInfo map;
9293   gsize max_mode;
9294   guint16 mode_set;
9295
9296   gst_buffer_map (buf, &map, GST_MAP_READ);
9297
9298   if (map.size != 0x11) {
9299     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9300     goto bad_data;
9301   }
9302
9303   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9304     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9305         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9306     goto bad_data;
9307   }
9308
9309   mode_set = QT_UINT16 (map.data + 13);
9310
9311   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9312     max_mode = 7 + (wb ? 1 : 0);
9313   else
9314     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9315     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9316
9317   if (max_mode == -1) {
9318     GST_DEBUG ("No mode indication was found (mode set) = %x",
9319         (guint) mode_set);
9320     goto bad_data;
9321   }
9322
9323   gst_buffer_unmap (buf, &map);
9324   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9325
9326 bad_data:
9327   gst_buffer_unmap (buf, &map);
9328   return 0;
9329 }
9330
9331 static gboolean
9332 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9333     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9334 {
9335   /*
9336    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9337    * [0 1 2]
9338    * [3 4 5]
9339    * [6 7 8]
9340    */
9341
9342   if (gst_byte_reader_get_remaining (reader) < 36)
9343     return FALSE;
9344
9345   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9346   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9347   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9348   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9349   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9350   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9351   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9352   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9353   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9354
9355   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9356   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9357       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9358       matrix[2] & 0xFF);
9359   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9360       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9361       matrix[5] & 0xFF);
9362   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9363       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9364       matrix[8] & 0xFF);
9365
9366   return TRUE;
9367 }
9368
9369 static void
9370 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9371     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9372 {
9373
9374 /* [a b c]
9375  * [d e f]
9376  * [g h i]
9377  *
9378  * This macro will only compare value abdegh, it expects cfi to have already
9379  * been checked
9380  */
9381 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9382                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9383
9384   /* only handle the cases where the last column has standard values */
9385   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9386     const gchar *rotation_tag = NULL;
9387
9388     /* no rotation needed */
9389     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9390       /* NOP */
9391     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9392       rotation_tag = "rotate-90";
9393     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9394       rotation_tag = "rotate-180";
9395     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9396       rotation_tag = "rotate-270";
9397     } else {
9398       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9399     }
9400
9401     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9402         rotation_tag);
9403     if (rotation_tag != NULL) {
9404       if (*taglist == NULL)
9405         *taglist = gst_tag_list_new_empty ();
9406       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9407           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9408     }
9409   } else {
9410     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9411   }
9412 }
9413
9414 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9415  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9416  * Common Encryption (cenc), the function will also parse the tenc box (defined
9417  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9418  * (typically an enc[v|a|t|s] sample entry); the function will set
9419  * @original_fmt to the fourcc of the original unencrypted stream format.
9420  * Returns TRUE if successful; FALSE otherwise. */
9421 static gboolean
9422 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9423     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9424 {
9425   GNode *sinf;
9426   GNode *frma;
9427   GNode *schm;
9428   GNode *schi;
9429
9430   g_return_val_if_fail (qtdemux != NULL, FALSE);
9431   g_return_val_if_fail (stream != NULL, FALSE);
9432   g_return_val_if_fail (container != NULL, FALSE);
9433   g_return_val_if_fail (original_fmt != NULL, FALSE);
9434
9435   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9436   if (G_UNLIKELY (!sinf)) {
9437     if (stream->protection_scheme_type == FOURCC_cenc) {
9438       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9439           "mandatory for Common Encryption");
9440       return FALSE;
9441     }
9442     return TRUE;
9443   }
9444
9445   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9446   if (G_UNLIKELY (!frma)) {
9447     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9448     return FALSE;
9449   }
9450
9451   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9452   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9453       GST_FOURCC_ARGS (*original_fmt));
9454
9455   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9456   if (!schm) {
9457     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9458     return FALSE;
9459   }
9460   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9461   stream->protection_scheme_version =
9462       QT_UINT32 ((const guint8 *) schm->data + 16);
9463
9464   GST_DEBUG_OBJECT (qtdemux,
9465       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9466       "protection_scheme_version: %#010x",
9467       GST_FOURCC_ARGS (stream->protection_scheme_type),
9468       stream->protection_scheme_version);
9469
9470   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9471   if (!schi) {
9472     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9473     return FALSE;
9474   }
9475   if (stream->protection_scheme_type == FOURCC_cenc) {
9476     QtDemuxCencSampleSetInfo *info;
9477     GNode *tenc;
9478     const guint8 *tenc_data;
9479     guint32 isEncrypted;
9480     guint8 iv_size;
9481     const guint8 *default_kid;
9482     GstBuffer *kid_buf;
9483
9484     if (G_UNLIKELY (!stream->protection_scheme_info))
9485       stream->protection_scheme_info =
9486           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9487
9488     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9489
9490     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9491     if (!tenc) {
9492       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9493           "which is mandatory for Common Encryption");
9494       return FALSE;
9495     }
9496     tenc_data = (const guint8 *) tenc->data + 12;
9497     isEncrypted = QT_UINT24 (tenc_data);
9498     iv_size = QT_UINT8 (tenc_data + 3);
9499     default_kid = (tenc_data + 4);
9500     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9501     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9502     if (info->default_properties)
9503       gst_structure_free (info->default_properties);
9504     info->default_properties =
9505         gst_structure_new ("application/x-cenc",
9506         "iv_size", G_TYPE_UINT, iv_size,
9507         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9508         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9509     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9510         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9511     gst_buffer_unref (kid_buf);
9512   }
9513   return TRUE;
9514 }
9515
9516 /* parse the traks.
9517  * With each track we associate a new QtDemuxStream that contains all the info
9518  * about the trak.
9519  * traks that do not decode to something (like strm traks) will not have a pad.
9520  */
9521 static gboolean
9522 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9523 {
9524   GstByteReader tkhd;
9525   int offset;
9526   GNode *mdia;
9527   GNode *mdhd;
9528   GNode *hdlr;
9529   GNode *minf;
9530   GNode *stbl;
9531   GNode *stsd;
9532   GNode *mp4a;
9533   GNode *mp4v;
9534   GNode *wave;
9535   GNode *esds;
9536   GNode *pasp;
9537   GNode *colr;
9538   GNode *tref;
9539   GNode *udta;
9540   GNode *svmi;
9541   GNode *fiel;
9542
9543   QtDemuxStream *stream = NULL;
9544   gboolean new_stream = FALSE;
9545   gchar *codec = NULL;
9546   const guint8 *stsd_data;
9547   const guint8 *stsd_entry_data;
9548   guint remaining_stsd_len;
9549   guint stsd_entry_count;
9550   guint stsd_index;
9551   guint16 lang_code;            /* quicktime lang code or packed iso code */
9552   guint32 version;
9553   guint32 tkhd_flags = 0;
9554   guint8 tkhd_version = 0;
9555   guint32 w = 0, h = 0;
9556   guint32 fourcc;
9557   guint value_size, stsd_len, len;
9558   guint32 track_id;
9559   guint32 dummy;
9560
9561   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9562
9563   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9564       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9565       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9566     goto corrupt_file;
9567
9568   /* pick between 64 or 32 bits */
9569   value_size = tkhd_version == 1 ? 8 : 4;
9570   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9571       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9572     goto corrupt_file;
9573
9574   if (!qtdemux->got_moov) {
9575     if (qtdemux_find_stream (qtdemux, track_id))
9576       goto existing_stream;
9577     stream = _create_stream ();
9578     stream->track_id = track_id;
9579     new_stream = TRUE;
9580   } else {
9581     stream = qtdemux_find_stream (qtdemux, track_id);
9582     if (!stream) {
9583       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9584       goto skip_track;
9585     }
9586
9587     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
9588
9589     /* flush samples data from this track from previous moov */
9590     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9591     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9592   }
9593   /* need defaults for fragments */
9594   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9595
9596   if ((tkhd_flags & 1) == 0)
9597     stream->disabled = TRUE;
9598
9599   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9600       tkhd_version, tkhd_flags, stream->track_id);
9601
9602   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9603     goto corrupt_file;
9604
9605   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9606     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9607     if (qtdemux->major_brand != FOURCC_mjp2 ||
9608         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9609       goto corrupt_file;
9610   }
9611
9612   len = QT_UINT32 ((guint8 *) mdhd->data);
9613   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9614   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9615   if (version == 0x01000000) {
9616     if (len < 38)
9617       goto corrupt_file;
9618     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9619     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9620     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9621   } else {
9622     if (len < 30)
9623       goto corrupt_file;
9624     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9625     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9626     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9627   }
9628
9629   if (lang_code < 0x400) {
9630     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9631   } else if (lang_code == 0x7fff) {
9632     stream->lang_id[0] = 0;     /* unspecified */
9633   } else {
9634     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9635     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9636     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9637     stream->lang_id[3] = 0;
9638   }
9639
9640   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9641       stream->timescale);
9642   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9643       stream->duration);
9644   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9645       lang_code, stream->lang_id);
9646
9647   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9648     goto corrupt_file;
9649
9650   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9651     /* chapters track reference */
9652     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9653     if (chap) {
9654       gsize length = GST_READ_UINT32_BE (chap->data);
9655       if (qtdemux->chapters_track_id)
9656         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9657
9658       if (length >= 12) {
9659         qtdemux->chapters_track_id =
9660             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9661       }
9662     }
9663   }
9664
9665   /* fragmented files may have bogus duration in moov */
9666   if (!qtdemux->fragmented &&
9667       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9668     guint64 tdur1, tdur2;
9669
9670     /* don't overflow */
9671     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9672     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9673
9674     /* HACK:
9675      * some of those trailers, nowadays, have prologue images that are
9676      * themselves video tracks as well. I haven't really found a way to
9677      * identify those yet, except for just looking at their duration. */
9678     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9679       GST_WARNING_OBJECT (qtdemux,
9680           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9681           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9682           "found, assuming preview image or something; skipping track",
9683           stream->duration, stream->timescale, qtdemux->duration,
9684           qtdemux->timescale);
9685       if (new_stream)
9686         gst_qtdemux_stream_free (qtdemux, stream);
9687       return TRUE;
9688     }
9689   }
9690
9691   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9692     goto corrupt_file;
9693
9694   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9695       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9696
9697   len = QT_UINT32 ((guint8 *) hdlr->data);
9698   if (len >= 20)
9699     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9700   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9701       GST_FOURCC_ARGS (stream->subtype));
9702
9703   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9704     goto corrupt_file;
9705
9706   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9707     goto corrupt_file;
9708
9709   /*parse svmi header if existing */
9710   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9711   if (svmi) {
9712     len = QT_UINT32 ((guint8 *) svmi->data);
9713     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9714     if (!version) {
9715       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9716       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9717       guint8 frame_type, frame_layout;
9718
9719       /* MPEG-A stereo video */
9720       if (qtdemux->major_brand == FOURCC_ss02)
9721         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9722
9723       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9724       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9725       switch (frame_type) {
9726         case 0:
9727           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9728           break;
9729         case 1:
9730           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9731           break;
9732         case 2:
9733           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9734           break;
9735         case 3:
9736           /* mode 3 is primary/secondary view sequence, ie
9737            * left/right views in separate tracks. See section 7.2
9738            * of ISO/IEC 23000-11:2009 */
9739           GST_FIXME_OBJECT (qtdemux,
9740               "Implement stereo video in separate streams");
9741       }
9742
9743       if ((frame_layout & 0x1) == 0)
9744         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9745
9746       GST_LOG_OBJECT (qtdemux,
9747           "StereoVideo: composition type: %u, is_left_first: %u",
9748           frame_type, frame_layout);
9749       stream->multiview_mode = mode;
9750       stream->multiview_flags = flags;
9751     }
9752   }
9753
9754   /* parse rest of tkhd */
9755   if (stream->subtype == FOURCC_vide) {
9756     guint32 matrix[9];
9757
9758     /* version 1 uses some 64-bit ints */
9759     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9760       goto corrupt_file;
9761
9762     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9763       goto corrupt_file;
9764
9765     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9766         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9767       goto corrupt_file;
9768
9769     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9770         &stream->stream_tags);
9771   }
9772
9773   /* parse stsd */
9774   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9775     goto corrupt_file;
9776   stsd_data = (const guint8 *) stsd->data;
9777
9778   /* stsd should at least have one entry */
9779   stsd_len = QT_UINT32 (stsd_data);
9780   if (stsd_len < 24) {
9781     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9782     if (stream->subtype == FOURCC_vivo) {
9783       if (new_stream)
9784         gst_qtdemux_stream_free (qtdemux, stream);
9785       return TRUE;
9786     } else {
9787       goto corrupt_file;
9788     }
9789   }
9790
9791   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9792   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9793   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9794   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9795
9796   stsd_entry_data = stsd_data + 16;
9797   remaining_stsd_len = stsd_len - 16;
9798   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9799     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9800
9801     /* and that entry should fit within stsd */
9802     len = QT_UINT32 (stsd_entry_data);
9803     if (len > remaining_stsd_len)
9804       goto corrupt_file;
9805
9806     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9807     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9808         GST_FOURCC_ARGS (entry->fourcc));
9809     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9810
9811     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9812       goto error_encrypted;
9813
9814     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9815       /* FIXME this looks wrong, there might be multiple children
9816        * with the same type */
9817       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9818       stream->protected = TRUE;
9819       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9820         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9821     }
9822
9823     if (stream->subtype == FOURCC_vide) {
9824       gboolean gray;
9825       gint depth, palette_size, palette_count;
9826       guint32 *palette_data = NULL;
9827
9828       entry->sampled = TRUE;
9829
9830       stream->display_width = w >> 16;
9831       stream->display_height = h >> 16;
9832
9833       offset = 16;
9834       if (len < 86)             /* TODO verify */
9835         goto corrupt_file;
9836
9837       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
9838       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
9839       entry->fps_n = 0;         /* this is filled in later */
9840       entry->fps_d = 0;         /* this is filled in later */
9841       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
9842       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
9843
9844       /* if color_table_id is 0, ctab atom must follow; however some files
9845        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9846        * if color table is not present we'll correct the value */
9847       if (entry->color_table_id == 0 &&
9848           (len < 90
9849               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
9850         entry->color_table_id = -1;
9851       }
9852
9853       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9854           entry->width, entry->height, entry->bits_per_sample,
9855           entry->color_table_id);
9856
9857       depth = entry->bits_per_sample;
9858
9859       /* more than 32 bits means grayscale */
9860       gray = (depth > 32);
9861       /* low 32 bits specify the depth  */
9862       depth &= 0x1F;
9863
9864       /* different number of palette entries is determined by depth. */
9865       palette_count = 0;
9866       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9867         palette_count = (1 << depth);
9868       palette_size = palette_count * 4;
9869
9870       if (entry->color_table_id) {
9871         switch (palette_count) {
9872           case 0:
9873             break;
9874           case 2:
9875             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9876             break;
9877           case 4:
9878             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9879             break;
9880           case 16:
9881             if (gray)
9882               palette_data =
9883                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
9884             else
9885               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9886             break;
9887           case 256:
9888             if (gray)
9889               palette_data =
9890                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
9891             else
9892               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9893             break;
9894           default:
9895             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9896                 (_("The video in this file might not play correctly.")),
9897                 ("unsupported palette depth %d", depth));
9898             break;
9899         }
9900       } else {
9901         gint i, j, start, end;
9902
9903         if (len < 94)
9904           goto corrupt_file;
9905
9906         /* read table */
9907         start = QT_UINT32 (stsd_entry_data + offset + 70);
9908         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
9909         end = QT_UINT16 (stsd_entry_data + offset + 76);
9910
9911         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9912             start, end, palette_count);
9913
9914         if (end > 255)
9915           end = 255;
9916         if (start > end)
9917           start = end;
9918
9919         if (len < 94 + (end - start) * 8)
9920           goto corrupt_file;
9921
9922         /* palette is always the same size */
9923         palette_data = g_malloc0 (256 * 4);
9924         palette_size = 256 * 4;
9925
9926         for (j = 0, i = start; i <= end; j++, i++) {
9927           guint32 a, r, g, b;
9928
9929           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
9930           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
9931           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
9932           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
9933
9934           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9935               (g & 0xff00) | (b >> 8);
9936         }
9937       }
9938
9939       if (entry->caps)
9940         gst_caps_unref (entry->caps);
9941
9942       entry->caps =
9943           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
9944           &codec);
9945       if (G_UNLIKELY (!entry->caps)) {
9946         g_free (palette_data);
9947         goto unknown_stream;
9948       }
9949
9950       if (codec) {
9951         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
9952             GST_TAG_VIDEO_CODEC, codec, NULL);
9953         g_free (codec);
9954         codec = NULL;
9955       }
9956
9957       if (palette_data) {
9958         GstStructure *s;
9959
9960         if (entry->rgb8_palette)
9961           gst_memory_unref (entry->rgb8_palette);
9962         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9963             palette_data, palette_size, 0, palette_size, palette_data, g_free);
9964
9965         s = gst_caps_get_structure (entry->caps, 0);
9966
9967         /* non-raw video has a palette_data property. raw video has the palette as
9968          * an extra plane that we append to the output buffers before we push
9969          * them*/
9970         if (!gst_structure_has_name (s, "video/x-raw")) {
9971           GstBuffer *palette;
9972
9973           palette = gst_buffer_new ();
9974           gst_buffer_append_memory (palette, entry->rgb8_palette);
9975           entry->rgb8_palette = NULL;
9976
9977           gst_caps_set_simple (entry->caps, "palette_data",
9978               GST_TYPE_BUFFER, palette, NULL);
9979           gst_buffer_unref (palette);
9980         }
9981       } else if (palette_count != 0) {
9982         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9983             (NULL), ("Unsupported palette depth %d", depth));
9984       }
9985
9986       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9987           QT_UINT16 (stsd_entry_data + offset + 32));
9988
9989       esds = NULL;
9990       pasp = NULL;
9991       colr = NULL;
9992       fiel = NULL;
9993       /* pick 'the' stsd child */
9994       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
9995       if (!stream->protected) {
9996         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
9997           mp4v = NULL;
9998         }
9999       } else {
10000         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10001           mp4v = NULL;
10002         }
10003       }
10004
10005       if (mp4v) {
10006         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10007         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10008         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10009         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10010       }
10011
10012       if (pasp) {
10013         const guint8 *pasp_data = (const guint8 *) pasp->data;
10014         gint len = QT_UINT32 (pasp_data);
10015
10016         if (len == 16) {
10017           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10018           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10019         } else {
10020           CUR_STREAM (stream)->par_w = 0;
10021           CUR_STREAM (stream)->par_h = 0;
10022         }
10023       } else {
10024         CUR_STREAM (stream)->par_w = 0;
10025         CUR_STREAM (stream)->par_h = 0;
10026       }
10027
10028       if (fiel) {
10029         const guint8 *fiel_data = (const guint8 *) fiel->data;
10030         gint len = QT_UINT32 (fiel_data);
10031
10032         if (len == 10) {
10033           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10034           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10035         }
10036       }
10037
10038       if (colr) {
10039         const guint8 *colr_data = (const guint8 *) colr->data;
10040         gint len = QT_UINT32 (colr_data);
10041
10042         if (len == 19 || len == 18) {
10043           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10044
10045           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10046             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10047             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10048             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10049             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10050
10051             switch (primaries) {
10052               case 1:
10053                 CUR_STREAM (stream)->colorimetry.primaries =
10054                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10055                 break;
10056               case 5:
10057                 CUR_STREAM (stream)->colorimetry.primaries =
10058                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10059                 break;
10060               case 6:
10061                 CUR_STREAM (stream)->colorimetry.primaries =
10062                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10063                 break;
10064               case 9:
10065                 CUR_STREAM (stream)->colorimetry.primaries =
10066                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10067                 break;
10068               default:
10069                 break;
10070             }
10071
10072             switch (transfer_function) {
10073               case 1:
10074                 CUR_STREAM (stream)->colorimetry.transfer =
10075                     GST_VIDEO_TRANSFER_BT709;
10076                 break;
10077               case 7:
10078                 CUR_STREAM (stream)->colorimetry.transfer =
10079                     GST_VIDEO_TRANSFER_SMPTE240M;
10080                 break;
10081               default:
10082                 break;
10083             }
10084
10085             switch (matrix) {
10086               case 1:
10087                 CUR_STREAM (stream)->colorimetry.matrix =
10088                     GST_VIDEO_COLOR_MATRIX_BT709;
10089                 break;
10090               case 6:
10091                 CUR_STREAM (stream)->colorimetry.matrix =
10092                     GST_VIDEO_COLOR_MATRIX_BT601;
10093                 break;
10094               case 7:
10095                 CUR_STREAM (stream)->colorimetry.matrix =
10096                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10097                 break;
10098               case 9:
10099                 CUR_STREAM (stream)->colorimetry.matrix =
10100                     GST_VIDEO_COLOR_MATRIX_BT2020;
10101                 break;
10102               default:
10103                 break;
10104             }
10105
10106             CUR_STREAM (stream)->colorimetry.range =
10107                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10108                 GST_VIDEO_COLOR_RANGE_16_235;
10109           } else {
10110             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10111           }
10112         } else {
10113           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10114         }
10115       }
10116
10117       if (esds) {
10118         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10119             stream->stream_tags);
10120       } else {
10121         switch (fourcc) {
10122           case FOURCC_H264:
10123           case FOURCC_avc1:
10124           case FOURCC_avc3:
10125           {
10126             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10127             const guint8 *avc_data = stsd_entry_data + 0x56;
10128
10129             /* find avcC */
10130             while (len >= 0x8) {
10131               gint size;
10132
10133               if (QT_UINT32 (avc_data) <= len)
10134                 size = QT_UINT32 (avc_data) - 0x8;
10135               else
10136                 size = len - 0x8;
10137
10138               if (size < 1)
10139                 /* No real data, so break out */
10140                 break;
10141
10142               switch (QT_FOURCC (avc_data + 0x4)) {
10143                 case FOURCC_avcC:
10144                 {
10145                   /* parse, if found */
10146                   GstBuffer *buf;
10147
10148                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10149
10150                   /* First 4 bytes are the length of the atom, the next 4 bytes
10151                    * are the fourcc, the next 1 byte is the version, and the
10152                    * subsequent bytes are profile_tier_level structure like data. */
10153                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10154                       avc_data + 8 + 1, size - 1);
10155                   buf = gst_buffer_new_and_alloc (size);
10156                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10157                   gst_caps_set_simple (entry->caps,
10158                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10159                   gst_buffer_unref (buf);
10160
10161                   break;
10162                 }
10163                 case FOURCC_strf:
10164                 {
10165                   GstBuffer *buf;
10166
10167                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10168
10169                   /* First 4 bytes are the length of the atom, the next 4 bytes
10170                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10171                    * next 1 byte is the version, and the
10172                    * subsequent bytes are sequence parameter set like data. */
10173
10174                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10175                   if (size > 1) {
10176                     gst_codec_utils_h264_caps_set_level_and_profile
10177                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10178
10179                     buf = gst_buffer_new_and_alloc (size);
10180                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10181                     gst_caps_set_simple (entry->caps,
10182                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10183                     gst_buffer_unref (buf);
10184                   }
10185                   break;
10186                 }
10187                 case FOURCC_btrt:
10188                 {
10189                   guint avg_bitrate, max_bitrate;
10190
10191                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10192                   if (size < 12)
10193                     break;
10194
10195                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10196                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10197
10198                   if (!max_bitrate && !avg_bitrate)
10199                     break;
10200
10201                   /* Some muxers seem to swap the average and maximum bitrates
10202                    * (I'm looking at you, YouTube), so we swap for sanity. */
10203                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10204                     guint temp = avg_bitrate;
10205
10206                     avg_bitrate = max_bitrate;
10207                     max_bitrate = temp;
10208                   }
10209
10210                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10211                     gst_tag_list_add (stream->stream_tags,
10212                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10213                         max_bitrate, NULL);
10214                   }
10215                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10216                     gst_tag_list_add (stream->stream_tags,
10217                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10218                         NULL);
10219                   }
10220
10221                   break;
10222                 }
10223
10224                 default:
10225                   break;
10226               }
10227
10228               len -= size + 8;
10229               avc_data += size + 8;
10230             }
10231
10232             break;
10233           }
10234           case FOURCC_H265:
10235           case FOURCC_hvc1:
10236           case FOURCC_hev1:
10237           {
10238             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10239             const guint8 *hevc_data = stsd_entry_data + 0x56;
10240
10241             /* find hevc */
10242             while (len >= 0x8) {
10243               gint size;
10244
10245               if (QT_UINT32 (hevc_data) <= len)
10246                 size = QT_UINT32 (hevc_data) - 0x8;
10247               else
10248                 size = len - 0x8;
10249
10250               if (size < 1)
10251                 /* No real data, so break out */
10252                 break;
10253
10254               switch (QT_FOURCC (hevc_data + 0x4)) {
10255                 case FOURCC_hvcC:
10256                 {
10257                   /* parse, if found */
10258                   GstBuffer *buf;
10259
10260                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10261
10262                   /* First 4 bytes are the length of the atom, the next 4 bytes
10263                    * are the fourcc, the next 1 byte is the version, and the
10264                    * subsequent bytes are sequence parameter set like data. */
10265                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10266                       (entry->caps, hevc_data + 8 + 1, size - 1);
10267
10268                   buf = gst_buffer_new_and_alloc (size);
10269                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10270                   gst_caps_set_simple (entry->caps,
10271                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10272                   gst_buffer_unref (buf);
10273                   break;
10274                 }
10275                 default:
10276                   break;
10277               }
10278               len -= size + 8;
10279               hevc_data += size + 8;
10280             }
10281             break;
10282           }
10283           case FOURCC_mp4v:
10284           case FOURCC_MP4V:
10285           case FOURCC_fmp4:
10286           case FOURCC_FMP4:
10287           case FOURCC_xvid:
10288           case FOURCC_XVID:
10289           {
10290             GNode *glbl;
10291
10292             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10293                 GST_FOURCC_ARGS (fourcc));
10294
10295             /* codec data might be in glbl extension atom */
10296             glbl = mp4v ?
10297                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10298             if (glbl) {
10299               guint8 *data;
10300               GstBuffer *buf;
10301               gint len;
10302
10303               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10304               data = glbl->data;
10305               len = QT_UINT32 (data);
10306               if (len > 0x8) {
10307                 len -= 0x8;
10308                 buf = gst_buffer_new_and_alloc (len);
10309                 gst_buffer_fill (buf, 0, data + 8, len);
10310                 gst_caps_set_simple (entry->caps,
10311                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10312                 gst_buffer_unref (buf);
10313               }
10314             }
10315             break;
10316           }
10317           case FOURCC_mjp2:
10318           {
10319             /* see annex I of the jpeg2000 spec */
10320             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10321             const guint8 *data;
10322             const gchar *colorspace = NULL;
10323             gint ncomp = 0;
10324             guint32 ncomp_map = 0;
10325             gint32 *comp_map = NULL;
10326             guint32 nchan_def = 0;
10327             gint32 *chan_def = NULL;
10328
10329             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10330             /* some required atoms */
10331             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10332             if (!mjp2)
10333               break;
10334             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10335             if (!jp2h)
10336               break;
10337
10338             /* number of components; redundant with info in codestream, but useful
10339                to a muxer */
10340             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10341             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10342               break;
10343             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10344
10345             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10346             if (!colr)
10347               break;
10348             GST_DEBUG_OBJECT (qtdemux, "found colr");
10349             /* extract colour space info */
10350             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10351               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10352                 case 16:
10353                   colorspace = "sRGB";
10354                   break;
10355                 case 17:
10356                   colorspace = "GRAY";
10357                   break;
10358                 case 18:
10359                   colorspace = "sYUV";
10360                   break;
10361                 default:
10362                   colorspace = NULL;
10363                   break;
10364               }
10365             }
10366             if (!colorspace)
10367               /* colr is required, and only values 16, 17, and 18 are specified,
10368                  so error if we have no colorspace */
10369               break;
10370
10371             /* extract component mapping */
10372             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10373             if (cmap) {
10374               guint32 cmap_len = 0;
10375               int i;
10376               cmap_len = QT_UINT32 (cmap->data);
10377               if (cmap_len >= 8) {
10378                 /* normal box, subtract off header */
10379                 cmap_len -= 8;
10380                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10381                 if (cmap_len % 4 == 0) {
10382                   ncomp_map = (cmap_len / 4);
10383                   comp_map = g_new0 (gint32, ncomp_map);
10384                   for (i = 0; i < ncomp_map; i++) {
10385                     guint16 cmp;
10386                     guint8 mtyp, pcol;
10387                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10388                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10389                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10390                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10391                   }
10392                 }
10393               }
10394             }
10395             /* extract channel definitions */
10396             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10397             if (cdef) {
10398               guint32 cdef_len = 0;
10399               int i;
10400               cdef_len = QT_UINT32 (cdef->data);
10401               if (cdef_len >= 10) {
10402                 /* normal box, subtract off header and len */
10403                 cdef_len -= 10;
10404                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10405                 if (cdef_len % 6 == 0) {
10406                   nchan_def = (cdef_len / 6);
10407                   chan_def = g_new0 (gint32, nchan_def);
10408                   for (i = 0; i < nchan_def; i++)
10409                     chan_def[i] = -1;
10410                   for (i = 0; i < nchan_def; i++) {
10411                     guint16 cn, typ, asoc;
10412                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10413                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10414                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10415                     if (cn < nchan_def) {
10416                       switch (typ) {
10417                         case 0:
10418                           chan_def[cn] = asoc;
10419                           break;
10420                         case 1:
10421                           chan_def[cn] = 0;     /* alpha */
10422                           break;
10423                         default:
10424                           chan_def[cn] = -typ;
10425                       }
10426                     }
10427                   }
10428                 }
10429               }
10430             }
10431
10432             gst_caps_set_simple (entry->caps,
10433                 "num-components", G_TYPE_INT, ncomp, NULL);
10434             gst_caps_set_simple (entry->caps,
10435                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10436
10437             if (comp_map) {
10438               GValue arr = { 0, };
10439               GValue elt = { 0, };
10440               int i;
10441               g_value_init (&arr, GST_TYPE_ARRAY);
10442               g_value_init (&elt, G_TYPE_INT);
10443               for (i = 0; i < ncomp_map; i++) {
10444                 g_value_set_int (&elt, comp_map[i]);
10445                 gst_value_array_append_value (&arr, &elt);
10446               }
10447               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10448                   "component-map", &arr);
10449               g_value_unset (&elt);
10450               g_value_unset (&arr);
10451               g_free (comp_map);
10452             }
10453
10454             if (chan_def) {
10455               GValue arr = { 0, };
10456               GValue elt = { 0, };
10457               int i;
10458               g_value_init (&arr, GST_TYPE_ARRAY);
10459               g_value_init (&elt, G_TYPE_INT);
10460               for (i = 0; i < nchan_def; i++) {
10461                 g_value_set_int (&elt, chan_def[i]);
10462                 gst_value_array_append_value (&arr, &elt);
10463               }
10464               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10465                   "channel-definitions", &arr);
10466               g_value_unset (&elt);
10467               g_value_unset (&arr);
10468               g_free (chan_def);
10469             }
10470
10471             /* some optional atoms */
10472             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10473             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10474
10475             /* indicate possible fields in caps */
10476             if (field) {
10477               data = (guint8 *) field->data + 8;
10478               if (*data != 1)
10479                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10480                     (gint) * data, NULL);
10481             }
10482             /* add codec_data if provided */
10483             if (prefix) {
10484               GstBuffer *buf;
10485               gint len;
10486
10487               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10488               data = prefix->data;
10489               len = QT_UINT32 (data);
10490               if (len > 0x8) {
10491                 len -= 0x8;
10492                 buf = gst_buffer_new_and_alloc (len);
10493                 gst_buffer_fill (buf, 0, data + 8, len);
10494                 gst_caps_set_simple (entry->caps,
10495                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10496                 gst_buffer_unref (buf);
10497               }
10498             }
10499             break;
10500           }
10501           case FOURCC_SVQ3:
10502           case FOURCC_VP31:
10503           {
10504             GstBuffer *buf;
10505             GstBuffer *seqh = NULL;
10506             const guint8 *gamma_data = NULL;
10507             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10508
10509             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10510                 &seqh);
10511             if (gamma_data) {
10512               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10513                   QT_FP32 (gamma_data), NULL);
10514             }
10515             if (seqh) {
10516               /* sorry for the bad name, but we don't know what this is, other
10517                * than its own fourcc */
10518               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10519                   NULL);
10520               gst_buffer_unref (seqh);
10521             }
10522
10523             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10524             buf = gst_buffer_new_and_alloc (len);
10525             gst_buffer_fill (buf, 0, stsd_data, len);
10526             gst_caps_set_simple (entry->caps,
10527                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10528             gst_buffer_unref (buf);
10529             break;
10530           }
10531           case FOURCC_jpeg:
10532           {
10533             /* https://developer.apple.com/standards/qtff-2001.pdf,
10534              * page 92, "Video Sample Description", under table 3.1 */
10535             GstByteReader br;
10536
10537             const gint compressor_offset =
10538                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10539             const gint min_size = compressor_offset + 32 + 2 + 2;
10540             GNode *jpeg;
10541             guint32 len;
10542             guint16 color_table_id = 0;
10543             gboolean ok;
10544
10545             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10546
10547             /* recover information on interlaced/progressive */
10548             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10549             if (!jpeg)
10550               break;
10551
10552             len = QT_UINT32 (jpeg->data);
10553             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10554                 min_size);
10555             if (len >= min_size) {
10556               gst_byte_reader_init (&br, jpeg->data, len);
10557
10558               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10559               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10560               if (color_table_id != 0) {
10561                 /* the spec says there can be concatenated chunks in the data, and we want
10562                  * to find one called field. Walk through them. */
10563                 gint offset = min_size;
10564                 while (offset + 8 < len) {
10565                   guint32 size = 0, tag;
10566                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10567                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10568                   if (!ok || size < 8) {
10569                     GST_WARNING_OBJECT (qtdemux,
10570                         "Failed to walk optional chunk list");
10571                     break;
10572                   }
10573                   GST_DEBUG_OBJECT (qtdemux,
10574                       "Found optional %4.4s chunk, size %u",
10575                       (const char *) &tag, size);
10576                   if (tag == FOURCC_fiel) {
10577                     guint8 n_fields = 0, ordering = 0;
10578                     gst_byte_reader_get_uint8 (&br, &n_fields);
10579                     gst_byte_reader_get_uint8 (&br, &ordering);
10580                     if (n_fields == 1 || n_fields == 2) {
10581                       GST_DEBUG_OBJECT (qtdemux,
10582                           "Found fiel tag with %u fields, ordering %u",
10583                           n_fields, ordering);
10584                       if (n_fields == 2)
10585                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10586                             "interlace-mode", G_TYPE_STRING, "interleaved",
10587                             NULL);
10588                     } else {
10589                       GST_WARNING_OBJECT (qtdemux,
10590                           "Found fiel tag with invalid fields (%u)", n_fields);
10591                     }
10592                   }
10593                   offset += size;
10594                 }
10595               } else {
10596                 GST_DEBUG_OBJECT (qtdemux,
10597                     "Color table ID is 0, not trying to get interlacedness");
10598               }
10599             } else {
10600               GST_WARNING_OBJECT (qtdemux,
10601                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10602             }
10603
10604             break;
10605           }
10606           case FOURCC_rle_:
10607           case FOURCC_WRLE:
10608           {
10609             gst_caps_set_simple (entry->caps,
10610                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 82),
10611                 NULL);
10612             break;
10613           }
10614           case FOURCC_XiTh:
10615           {
10616             GNode *xith, *xdxt;
10617
10618             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10619             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10620             if (!xith)
10621               break;
10622
10623             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10624             if (!xdxt)
10625               break;
10626
10627             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10628             /* collect the headers and store them in a stream list so that we can
10629              * send them out first */
10630             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10631             break;
10632           }
10633           case FOURCC_ovc1:
10634           {
10635             GNode *ovc1;
10636             guint8 *ovc1_data;
10637             guint ovc1_len;
10638             GstBuffer *buf;
10639
10640             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10641             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10642             if (!ovc1)
10643               break;
10644             ovc1_data = ovc1->data;
10645             ovc1_len = QT_UINT32 (ovc1_data);
10646             if (ovc1_len <= 198) {
10647               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10648               break;
10649             }
10650             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10651             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10652             gst_caps_set_simple (entry->caps,
10653                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10654             gst_buffer_unref (buf);
10655             break;
10656           }
10657           case FOURCC_vc_1:
10658           {
10659             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10660             const guint8 *vc1_data = stsd_entry_data + 0x56;
10661
10662             /* find dvc1 */
10663             while (len >= 8) {
10664               gint size;
10665
10666               if (QT_UINT32 (vc1_data) <= len)
10667                 size = QT_UINT32 (vc1_data) - 8;
10668               else
10669                 size = len - 8;
10670
10671               if (size < 1)
10672                 /* No real data, so break out */
10673                 break;
10674
10675               switch (QT_FOURCC (vc1_data + 0x4)) {
10676                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10677                 {
10678                   GstBuffer *buf;
10679
10680                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10681                   buf = gst_buffer_new_and_alloc (size);
10682                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10683                   gst_caps_set_simple (entry->caps,
10684                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10685                   gst_buffer_unref (buf);
10686                   break;
10687                 }
10688                 default:
10689                   break;
10690               }
10691               len -= size + 8;
10692               vc1_data += size + 8;
10693             }
10694             break;
10695           }
10696           default:
10697             break;
10698         }
10699       }
10700
10701       GST_INFO_OBJECT (qtdemux,
10702           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10703           GST_FOURCC_ARGS (fourcc), entry->caps);
10704
10705     } else if (stream->subtype == FOURCC_soun) {
10706       int version, samplesize;
10707       guint16 compression_id;
10708       gboolean amrwb = FALSE;
10709
10710       offset = 16;
10711       /* sample description entry (16) + sound sample description v0 (20) */
10712       if (len < 36)
10713         goto corrupt_file;
10714
10715       version = QT_UINT32 (stsd_entry_data + offset);
10716       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10717       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10718       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10719       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10720
10721       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10722       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10723           QT_UINT32 (stsd_entry_data + offset + 4));
10724       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10725       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10726       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10727       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10728           QT_UINT16 (stsd_entry_data + offset + 14));
10729       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10730
10731       if (compression_id == 0xfffe)
10732         entry->sampled = TRUE;
10733
10734       /* first assume uncompressed audio */
10735       entry->bytes_per_sample = samplesize / 8;
10736       entry->samples_per_frame = entry->n_channels;
10737       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10738       entry->samples_per_packet = entry->samples_per_frame;
10739       entry->bytes_per_packet = entry->bytes_per_sample;
10740
10741       offset = 36;
10742       switch (fourcc) {
10743           /* Yes, these have to be hard-coded */
10744         case FOURCC_MAC6:
10745         {
10746           entry->samples_per_packet = 6;
10747           entry->bytes_per_packet = 1;
10748           entry->bytes_per_frame = 1 * entry->n_channels;
10749           entry->bytes_per_sample = 1;
10750           entry->samples_per_frame = 6 * entry->n_channels;
10751           break;
10752         }
10753         case FOURCC_MAC3:
10754         {
10755           entry->samples_per_packet = 3;
10756           entry->bytes_per_packet = 1;
10757           entry->bytes_per_frame = 1 * entry->n_channels;
10758           entry->bytes_per_sample = 1;
10759           entry->samples_per_frame = 3 * entry->n_channels;
10760           break;
10761         }
10762         case FOURCC_ima4:
10763         {
10764           entry->samples_per_packet = 64;
10765           entry->bytes_per_packet = 34;
10766           entry->bytes_per_frame = 34 * entry->n_channels;
10767           entry->bytes_per_sample = 2;
10768           entry->samples_per_frame = 64 * entry->n_channels;
10769           break;
10770         }
10771         case FOURCC_ulaw:
10772         case FOURCC_alaw:
10773         {
10774           entry->samples_per_packet = 1;
10775           entry->bytes_per_packet = 1;
10776           entry->bytes_per_frame = 1 * entry->n_channels;
10777           entry->bytes_per_sample = 1;
10778           entry->samples_per_frame = 1 * entry->n_channels;
10779           break;
10780         }
10781         case FOURCC_agsm:
10782         {
10783           entry->samples_per_packet = 160;
10784           entry->bytes_per_packet = 33;
10785           entry->bytes_per_frame = 33 * entry->n_channels;
10786           entry->bytes_per_sample = 2;
10787           entry->samples_per_frame = 160 * entry->n_channels;
10788           break;
10789         }
10790         default:
10791           break;
10792       }
10793
10794       if (version == 0x00010000) {
10795         /* sample description entry (16) + sound sample description v1 (20+16) */
10796         if (len < 52)
10797           goto corrupt_file;
10798
10799         switch (fourcc) {
10800           case FOURCC_twos:
10801           case FOURCC_sowt:
10802           case FOURCC_raw_:
10803             break;
10804           default:
10805           {
10806             /* only parse extra decoding config for non-pcm audio */
10807             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10808             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10809             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10810             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10811
10812             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10813                 entry->samples_per_packet);
10814             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10815                 entry->bytes_per_packet);
10816             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10817                 entry->bytes_per_frame);
10818             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10819                 entry->bytes_per_sample);
10820
10821             if (!entry->sampled && entry->bytes_per_packet) {
10822               entry->samples_per_frame = (entry->bytes_per_frame /
10823                   entry->bytes_per_packet) * entry->samples_per_packet;
10824               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10825                   entry->samples_per_frame);
10826             }
10827             break;
10828           }
10829         }
10830       } else if (version == 0x00020000) {
10831         union
10832         {
10833           gdouble fp;
10834           guint64 val;
10835         } qtfp;
10836
10837         /* sample description entry (16) + sound sample description v2 (56) */
10838         if (len < 72)
10839           goto corrupt_file;
10840
10841         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
10842         entry->rate = qtfp.fp;
10843         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
10844
10845         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10846         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
10847         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
10848         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10849             QT_UINT32 (stsd_entry_data + offset + 20));
10850         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10851             QT_UINT32 (stsd_entry_data + offset + 24));
10852         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10853             QT_UINT32 (stsd_entry_data + offset + 28));
10854         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10855             QT_UINT32 (stsd_entry_data + offset + 32));
10856       } else if (version != 0x00000) {
10857         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
10858             version);
10859       }
10860
10861       if (entry->caps)
10862         gst_caps_unref (entry->caps);
10863
10864       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
10865           stsd_entry_data + 32, len - 16, &codec);
10866
10867       switch (fourcc) {
10868         case FOURCC_in24:
10869         {
10870           GNode *enda;
10871           GNode *in24;
10872
10873           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10874
10875           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10876           if (!enda) {
10877             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10878             if (wave)
10879               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10880           }
10881           if (enda) {
10882             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10883             gst_caps_set_simple (entry->caps,
10884                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
10885                 NULL);
10886           }
10887           break;
10888         }
10889         case FOURCC_owma:
10890         {
10891           const guint8 *owma_data;
10892           const gchar *codec_name = NULL;
10893           guint owma_len;
10894           GstBuffer *buf;
10895           gint version = 1;
10896           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10897           /* FIXME this should also be gst_riff_strf_auds,
10898            * but the latter one is actually missing bits-per-sample :( */
10899           typedef struct
10900           {
10901             gint16 wFormatTag;
10902             gint16 nChannels;
10903             gint32 nSamplesPerSec;
10904             gint32 nAvgBytesPerSec;
10905             gint16 nBlockAlign;
10906             gint16 wBitsPerSample;
10907             gint16 cbSize;
10908           } WAVEFORMATEX;
10909           WAVEFORMATEX *wfex;
10910
10911           GST_DEBUG_OBJECT (qtdemux, "parse owma");
10912           owma_data = stsd_entry_data;
10913           owma_len = QT_UINT32 (owma_data);
10914           if (owma_len <= 54) {
10915             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10916             break;
10917           }
10918           wfex = (WAVEFORMATEX *) (owma_data + 36);
10919           buf = gst_buffer_new_and_alloc (owma_len - 54);
10920           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10921           if (wfex->wFormatTag == 0x0161) {
10922             codec_name = "Windows Media Audio";
10923             version = 2;
10924           } else if (wfex->wFormatTag == 0x0162) {
10925             codec_name = "Windows Media Audio 9 Pro";
10926             version = 3;
10927           } else if (wfex->wFormatTag == 0x0163) {
10928             codec_name = "Windows Media Audio 9 Lossless";
10929             /* is that correct? gstffmpegcodecmap.c is missing it, but
10930              * fluendo codec seems to support it */
10931             version = 4;
10932           }
10933
10934           gst_caps_set_simple (entry->caps,
10935               "codec_data", GST_TYPE_BUFFER, buf,
10936               "wmaversion", G_TYPE_INT, version,
10937               "block_align", G_TYPE_INT,
10938               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
10939               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
10940               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
10941               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
10942           gst_buffer_unref (buf);
10943
10944           if (codec_name) {
10945             g_free (codec);
10946             codec = g_strdup (codec_name);
10947           }
10948           break;
10949         }
10950         case FOURCC_wma_:
10951         {
10952           gint len = QT_UINT32 (stsd_entry_data) - offset;
10953           const guint8 *wfex_data = stsd_entry_data + offset;
10954           const gchar *codec_name = NULL;
10955           gint version = 1;
10956           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10957           /* FIXME this should also be gst_riff_strf_auds,
10958            * but the latter one is actually missing bits-per-sample :( */
10959           typedef struct
10960           {
10961             gint16 wFormatTag;
10962             gint16 nChannels;
10963             gint32 nSamplesPerSec;
10964             gint32 nAvgBytesPerSec;
10965             gint16 nBlockAlign;
10966             gint16 wBitsPerSample;
10967             gint16 cbSize;
10968           } WAVEFORMATEX;
10969           WAVEFORMATEX wfex;
10970
10971           /* FIXME: unify with similar wavformatex parsing code above */
10972           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10973
10974           /* find wfex */
10975           while (len >= 8) {
10976             gint size;
10977
10978             if (QT_UINT32 (wfex_data) <= len)
10979               size = QT_UINT32 (wfex_data) - 8;
10980             else
10981               size = len - 8;
10982
10983             if (size < 1)
10984               /* No real data, so break out */
10985               break;
10986
10987             switch (QT_FOURCC (wfex_data + 4)) {
10988               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10989               {
10990                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10991
10992                 if (size < 8 + 18)
10993                   break;
10994
10995                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10996                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10997                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10998                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10999                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11000                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11001                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11002
11003                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11004                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11005                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11006                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11007                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11008                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11009
11010                 if (wfex.wFormatTag == 0x0161) {
11011                   codec_name = "Windows Media Audio";
11012                   version = 2;
11013                 } else if (wfex.wFormatTag == 0x0162) {
11014                   codec_name = "Windows Media Audio 9 Pro";
11015                   version = 3;
11016                 } else if (wfex.wFormatTag == 0x0163) {
11017                   codec_name = "Windows Media Audio 9 Lossless";
11018                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11019                    * fluendo codec seems to support it */
11020                   version = 4;
11021                 }
11022
11023                 gst_caps_set_simple (entry->caps,
11024                     "wmaversion", G_TYPE_INT, version,
11025                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11026                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11027                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11028                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11029
11030                 if (size > wfex.cbSize) {
11031                   GstBuffer *buf;
11032
11033                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11034                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11035                       size - wfex.cbSize);
11036                   gst_caps_set_simple (entry->caps,
11037                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11038                   gst_buffer_unref (buf);
11039                 } else {
11040                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11041                 }
11042
11043                 if (codec_name) {
11044                   g_free (codec);
11045                   codec = g_strdup (codec_name);
11046                 }
11047                 break;
11048               }
11049               default:
11050                 break;
11051             }
11052             len -= size + 8;
11053             wfex_data += size + 8;
11054           }
11055           break;
11056         }
11057         case FOURCC_opus:
11058         {
11059           const guint8 *opus_data;
11060           guint8 *channel_mapping = NULL;
11061           guint32 rate;
11062           guint8 channels;
11063           guint8 channel_mapping_family;
11064           guint8 stream_count;
11065           guint8 coupled_count;
11066           guint8 i;
11067
11068           opus_data = stsd_entry_data;
11069
11070           channels = GST_READ_UINT8 (opus_data + 45);
11071           rate = GST_READ_UINT32_LE (opus_data + 48);
11072           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11073           stream_count = GST_READ_UINT8 (opus_data + 55);
11074           coupled_count = GST_READ_UINT8 (opus_data + 56);
11075
11076           if (channels > 0) {
11077             channel_mapping = g_malloc (channels * sizeof (guint8));
11078             for (i = 0; i < channels; i++)
11079               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11080           }
11081
11082           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11083               channel_mapping_family, stream_count, coupled_count,
11084               channel_mapping);
11085           break;
11086         }
11087         default:
11088           break;
11089       }
11090
11091       if (codec) {
11092         GstStructure *s;
11093         gint bitrate = 0;
11094
11095         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11096             GST_TAG_AUDIO_CODEC, codec, NULL);
11097         g_free (codec);
11098         codec = NULL;
11099
11100         /* some bitrate info may have ended up in caps */
11101         s = gst_caps_get_structure (entry->caps, 0);
11102         gst_structure_get_int (s, "bitrate", &bitrate);
11103         if (bitrate > 0)
11104           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11105               GST_TAG_BITRATE, bitrate, NULL);
11106       }
11107
11108       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11109       if (!stream->protected) {
11110       } else {
11111         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11112           mp4v = NULL;
11113         }
11114       }
11115       if (stream->protected && fourcc == FOURCC_mp4a) {
11116         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11117           mp4a = NULL;
11118         }
11119       } else {
11120         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11121           mp4a = NULL;
11122         }
11123       }
11124
11125       wave = NULL;
11126       esds = NULL;
11127       if (mp4a) {
11128         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11129         if (wave)
11130           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11131         if (!esds)
11132           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11133       }
11134
11135
11136       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11137          16 bits is a byte-swapped wave-style codec identifier,
11138          and we can find a WAVE header internally to a 'wave' atom here.
11139          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11140          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11141          is big-endian).
11142        */
11143       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11144         if (len < offset + 20) {
11145           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11146         } else {
11147           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11148           const guint8 *data = stsd_entry_data + offset + 16;
11149           GNode *wavenode;
11150           GNode *waveheadernode;
11151
11152           wavenode = g_node_new ((guint8 *) data);
11153           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11154             const guint8 *waveheader;
11155             guint32 headerlen;
11156
11157             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11158             if (waveheadernode) {
11159               waveheader = (const guint8 *) waveheadernode->data;
11160               headerlen = QT_UINT32 (waveheader);
11161
11162               if (headerlen > 8) {
11163                 gst_riff_strf_auds *header = NULL;
11164                 GstBuffer *headerbuf;
11165                 GstBuffer *extra;
11166
11167                 waveheader += 8;
11168                 headerlen -= 8;
11169
11170                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11171                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11172
11173                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11174                         headerbuf, &header, &extra)) {
11175                   gst_caps_unref (entry->caps);
11176                   /* FIXME: Need to do something with the channel reorder map */
11177                   entry->caps =
11178                       gst_riff_create_audio_caps (header->format, NULL, header,
11179                       extra, NULL, NULL, NULL);
11180
11181                   if (extra)
11182                     gst_buffer_unref (extra);
11183                   g_free (header);
11184                 }
11185               }
11186             } else
11187               GST_DEBUG ("Didn't find waveheadernode for this codec");
11188           }
11189           g_node_destroy (wavenode);
11190         }
11191       } else if (esds) {
11192         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11193             stream->stream_tags);
11194       } else {
11195         switch (fourcc) {
11196 #if 0
11197             /* FIXME: what is in the chunk? */
11198           case FOURCC_QDMC:
11199           {
11200             gint len = QT_UINT32 (stsd_data);
11201
11202             /* seems to be always = 116 = 0x74 */
11203             break;
11204           }
11205 #endif
11206           case FOURCC_QDM2:
11207           {
11208             gint len = QT_UINT32 (stsd_entry_data);
11209
11210             if (len > 0x3C) {
11211               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11212
11213               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11214               gst_caps_set_simple (entry->caps,
11215                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11216               gst_buffer_unref (buf);
11217             }
11218             gst_caps_set_simple (entry->caps,
11219                 "samplesize", G_TYPE_INT, samplesize, NULL);
11220             break;
11221           }
11222           case FOURCC_alac:
11223           {
11224             GNode *alac, *wave = NULL;
11225
11226             /* apparently, m4a has this atom appended directly in the stsd entry,
11227              * while mov has it in a wave atom */
11228             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11229             if (alac) {
11230               /* alac now refers to stsd entry atom */
11231               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11232               if (wave)
11233                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11234               else
11235                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11236             }
11237             if (alac) {
11238               const guint8 *alac_data = alac->data;
11239               gint len = QT_UINT32 (alac->data);
11240               GstBuffer *buf;
11241
11242               if (len < 36) {
11243                 GST_DEBUG_OBJECT (qtdemux,
11244                     "discarding alac atom with unexpected len %d", len);
11245               } else {
11246                 /* codec-data contains alac atom size and prefix,
11247                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11248                 buf = gst_buffer_new_and_alloc (len);
11249                 gst_buffer_fill (buf, 0, alac->data, len);
11250                 gst_caps_set_simple (entry->caps,
11251                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11252                 gst_buffer_unref (buf);
11253
11254                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11255                 entry->n_channels = QT_UINT8 (alac_data + 21);
11256                 entry->rate = QT_UINT32 (alac_data + 32);
11257               }
11258             }
11259             gst_caps_set_simple (entry->caps,
11260                 "samplesize", G_TYPE_INT, samplesize, NULL);
11261             break;
11262           }
11263           case FOURCC_fLaC:
11264           {
11265             /* The codingname of the sample entry is 'fLaC' */
11266             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11267
11268             if (flac) {
11269               /* The 'dfLa' box is added to the sample entry to convey
11270                  initializing information for the decoder. */
11271               const GNode *dfla =
11272                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11273
11274               if (dfla) {
11275                 const guint32 len = QT_UINT32 (dfla->data);
11276
11277                 /* Must contain at least dfLa box header (12),
11278                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11279                 if (len < 50) {
11280                   GST_DEBUG_OBJECT (qtdemux,
11281                       "discarding dfla atom with unexpected len %d", len);
11282                 } else {
11283                   /* skip dfLa header to get the METADATA_BLOCKs */
11284                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11285                   const guint32 metadata_blocks_len = len - 12;
11286
11287                   gchar *stream_marker = g_strdup ("fLaC");
11288                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11289                       strlen (stream_marker));
11290
11291                   guint32 index = 0;
11292                   guint32 remainder = 0;
11293                   guint32 block_size = 0;
11294                   gboolean is_last = FALSE;
11295
11296                   GValue array = G_VALUE_INIT;
11297                   GValue value = G_VALUE_INIT;
11298
11299                   g_value_init (&array, GST_TYPE_ARRAY);
11300                   g_value_init (&value, GST_TYPE_BUFFER);
11301
11302                   gst_value_set_buffer (&value, block);
11303                   gst_value_array_append_value (&array, &value);
11304                   g_value_reset (&value);
11305
11306                   gst_buffer_unref (block);
11307
11308                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11309                    * of data, and we haven't already finished parsing */
11310                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11311                     remainder = metadata_blocks_len - index;
11312
11313                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11314                     block_size = 4 +
11315                         (metadata_blocks[index + 1] << 16) +
11316                         (metadata_blocks[index + 2] << 8) +
11317                         metadata_blocks[index + 3];
11318
11319                     /* be careful not to read off end of box */
11320                     if (block_size > remainder) {
11321                       break;
11322                     }
11323
11324                     is_last = metadata_blocks[index] >> 7;
11325
11326                     block = gst_buffer_new_and_alloc (block_size);
11327
11328                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11329                         block_size);
11330
11331                     gst_value_set_buffer (&value, block);
11332                     gst_value_array_append_value (&array, &value);
11333                     g_value_reset (&value);
11334
11335                     gst_buffer_unref (block);
11336
11337                     index += block_size;
11338                   }
11339
11340                   /* only append the metadata if we successfully read all of it */
11341                   if (is_last) {
11342                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11343                             (stream)->caps, 0), "streamheader", &array);
11344                   } else {
11345                     GST_WARNING_OBJECT (qtdemux,
11346                         "discarding all METADATA_BLOCKs due to invalid "
11347                         "block_size %d at idx %d, rem %d", block_size, index,
11348                         remainder);
11349                   }
11350
11351                   g_value_unset (&value);
11352                   g_value_unset (&array);
11353
11354                   /* The sample rate obtained from the stsd may not be accurate
11355                    * since it cannot represent rates greater than 65535Hz, so
11356                    * override that value with the sample rate from the
11357                    * METADATA_BLOCK_STREAMINFO block */
11358                   CUR_STREAM (stream)->rate =
11359                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11360                 }
11361               }
11362             }
11363             break;
11364           }
11365           case FOURCC_sawb:
11366             /* Fallthrough! */
11367             amrwb = TRUE;
11368           case FOURCC_samr:
11369           {
11370             gint len = QT_UINT32 (stsd_entry_data);
11371
11372             if (len > 0x24) {
11373               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11374               guint bitrate;
11375
11376               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11377
11378               /* If we have enough data, let's try to get the 'damr' atom. See
11379                * the 3GPP container spec (26.244) for more details. */
11380               if ((len - 0x34) > 8 &&
11381                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11382                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11383                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11384               }
11385
11386               gst_caps_set_simple (entry->caps,
11387                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11388               gst_buffer_unref (buf);
11389             }
11390             break;
11391           }
11392           case FOURCC_mp4a:
11393           {
11394             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11395             gint len = QT_UINT32 (stsd_entry_data);
11396
11397             if (len >= 34) {
11398               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11399
11400               if (sound_version == 1) {
11401                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11402                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11403                 guint8 codec_data[2];
11404                 GstBuffer *buf;
11405                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11406
11407                 gint sample_rate_index =
11408                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11409
11410                 /* build AAC codec data */
11411                 codec_data[0] = profile << 3;
11412                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11413                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11414                 codec_data[1] |= (channels & 0xF) << 3;
11415
11416                 buf = gst_buffer_new_and_alloc (2);
11417                 gst_buffer_fill (buf, 0, codec_data, 2);
11418                 gst_caps_set_simple (entry->caps,
11419                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11420                 gst_buffer_unref (buf);
11421               }
11422             }
11423             break;
11424           }
11425           default:
11426             GST_INFO_OBJECT (qtdemux,
11427                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11428             break;
11429         }
11430       }
11431       GST_INFO_OBJECT (qtdemux,
11432           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11433           GST_FOURCC_ARGS (fourcc), entry->caps);
11434
11435     } else if (stream->subtype == FOURCC_strm) {
11436       if (fourcc == FOURCC_rtsp) {
11437         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11438       } else {
11439         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11440             GST_FOURCC_ARGS (fourcc));
11441         goto unknown_stream;
11442       }
11443       entry->sampled = TRUE;
11444     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11445         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11446
11447       entry->sampled = TRUE;
11448       entry->sparse = TRUE;
11449
11450       entry->caps =
11451           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11452           &codec);
11453       if (codec) {
11454         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11455             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11456         g_free (codec);
11457         codec = NULL;
11458       }
11459
11460       /* hunt for sort-of codec data */
11461       switch (fourcc) {
11462         case FOURCC_mp4s:
11463         {
11464           GNode *mp4s = NULL;
11465           GNode *esds = NULL;
11466
11467           /* look for palette in a stsd->mp4s->esds sub-atom */
11468           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11469           if (mp4s)
11470             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11471           if (esds == NULL) {
11472             /* Invalid STSD */
11473             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11474             break;
11475           }
11476
11477           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11478               stream->stream_tags);
11479           break;
11480         }
11481         default:
11482           GST_INFO_OBJECT (qtdemux,
11483               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11484           break;
11485       }
11486       GST_INFO_OBJECT (qtdemux,
11487           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11488           GST_FOURCC_ARGS (fourcc), entry->caps);
11489     } else {
11490       /* everything in 1 sample */
11491       entry->sampled = TRUE;
11492
11493       entry->caps =
11494           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11495           &codec);
11496
11497       if (entry->caps == NULL)
11498         goto unknown_stream;
11499
11500       if (codec) {
11501         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11502             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11503         g_free (codec);
11504         codec = NULL;
11505       }
11506     }
11507
11508     /* promote to sampled format */
11509     if (entry->fourcc == FOURCC_samr) {
11510       /* force mono 8000 Hz for AMR */
11511       entry->sampled = TRUE;
11512       entry->n_channels = 1;
11513       entry->rate = 8000;
11514     } else if (entry->fourcc == FOURCC_sawb) {
11515       /* force mono 16000 Hz for AMR-WB */
11516       entry->sampled = TRUE;
11517       entry->n_channels = 1;
11518       entry->rate = 16000;
11519     } else if (entry->fourcc == FOURCC_mp4a) {
11520       entry->sampled = TRUE;
11521     }
11522
11523
11524     stsd_entry_data += len;
11525     remaining_stsd_len -= len;
11526
11527   }
11528
11529   /* collect sample information */
11530   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11531     goto samples_failed;
11532
11533   if (qtdemux->fragmented) {
11534     guint64 offset;
11535
11536     /* need all moov samples as basis; probably not many if any at all */
11537     /* prevent moof parsing taking of at this time */
11538     offset = qtdemux->moof_offset;
11539     qtdemux->moof_offset = 0;
11540     if (stream->n_samples &&
11541         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11542       qtdemux->moof_offset = offset;
11543       goto samples_failed;
11544     }
11545     qtdemux->moof_offset = 0;
11546     /* movie duration more reliable in this case (e.g. mehd) */
11547     if (qtdemux->segment.duration &&
11548         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11549       stream->duration =
11550           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11551   }
11552
11553   /* configure segments */
11554   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11555     goto segments_failed;
11556
11557   /* add some language tag, if useful */
11558   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11559       strcmp (stream->lang_id, "und")) {
11560     const gchar *lang_code;
11561
11562     /* convert ISO 639-2 code to ISO 639-1 */
11563     lang_code = gst_tag_get_language_code (stream->lang_id);
11564     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11565         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11566   }
11567
11568   /* Check for UDTA tags */
11569   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11570     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11571   }
11572
11573   /* now we are ready to add the stream */
11574   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11575     goto too_many_streams;
11576
11577   if (!qtdemux->got_moov) {
11578     qtdemux->streams[qtdemux->n_streams] = stream;
11579     qtdemux->n_streams++;
11580     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11581   }
11582
11583   return TRUE;
11584
11585 /* ERRORS */
11586 skip_track:
11587   {
11588     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11589     if (new_stream)
11590       gst_qtdemux_stream_free (qtdemux, stream);
11591     return TRUE;
11592   }
11593 corrupt_file:
11594   {
11595     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11596         (_("This file is corrupt and cannot be played.")), (NULL));
11597     if (new_stream)
11598       gst_qtdemux_stream_free (qtdemux, stream);
11599     return FALSE;
11600   }
11601 error_encrypted:
11602   {
11603     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11604     if (new_stream)
11605       gst_qtdemux_stream_free (qtdemux, stream);
11606     return FALSE;
11607   }
11608 samples_failed:
11609 segments_failed:
11610   {
11611     /* we posted an error already */
11612     /* free stbl sub-atoms */
11613     gst_qtdemux_stbl_free (stream);
11614     if (new_stream)
11615       gst_qtdemux_stream_free (qtdemux, stream);
11616     return FALSE;
11617   }
11618 existing_stream:
11619   {
11620     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11621         track_id);
11622     if (new_stream)
11623       gst_qtdemux_stream_free (qtdemux, stream);
11624     return TRUE;
11625   }
11626 unknown_stream:
11627   {
11628     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11629         GST_FOURCC_ARGS (stream->subtype));
11630     if (new_stream)
11631       gst_qtdemux_stream_free (qtdemux, stream);
11632     return TRUE;
11633   }
11634 too_many_streams:
11635   {
11636     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11637         (_("This file contains too many streams. Only playing first %d"),
11638             GST_QTDEMUX_MAX_STREAMS), (NULL));
11639     return TRUE;
11640   }
11641 }
11642
11643 /* If we can estimate the overall bitrate, and don't have information about the
11644  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11645  * the overall bitrate minus the sum of the bitrates of all other streams. This
11646  * should be useful for the common case where we have one audio and one video
11647  * stream and can estimate the bitrate of one, but not the other. */
11648 static void
11649 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11650 {
11651   QtDemuxStream *stream = NULL;
11652   gint64 size, sys_bitrate, sum_bitrate = 0;
11653   GstClockTime duration;
11654   gint i;
11655   guint bitrate;
11656
11657   if (qtdemux->fragmented)
11658     return;
11659
11660   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11661
11662   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11663       || size <= 0) {
11664     GST_DEBUG_OBJECT (qtdemux,
11665         "Size in bytes of the stream not known - bailing");
11666     return;
11667   }
11668
11669   /* Subtract the header size */
11670   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11671       size, qtdemux->header_size);
11672
11673   if (size < qtdemux->header_size)
11674     return;
11675
11676   size = size - qtdemux->header_size;
11677
11678   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11679     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11680     return;
11681   }
11682
11683   for (i = 0; i < qtdemux->n_streams; i++) {
11684     switch (qtdemux->streams[i]->subtype) {
11685       case FOURCC_soun:
11686       case FOURCC_vide:
11687         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11688             CUR_STREAM (qtdemux->streams[i])->caps);
11689         /* retrieve bitrate, prefer avg then max */
11690         bitrate = 0;
11691         if (qtdemux->streams[i]->stream_tags) {
11692           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11693               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11694           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11695           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11696               GST_TAG_NOMINAL_BITRATE, &bitrate);
11697           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11698           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11699               GST_TAG_BITRATE, &bitrate);
11700           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11701         }
11702         if (bitrate)
11703           sum_bitrate += bitrate;
11704         else {
11705           if (stream) {
11706             GST_DEBUG_OBJECT (qtdemux,
11707                 ">1 stream with unknown bitrate - bailing");
11708             return;
11709           } else
11710             stream = qtdemux->streams[i];
11711         }
11712
11713       default:
11714         /* For other subtypes, we assume no significant impact on bitrate */
11715         break;
11716     }
11717   }
11718
11719   if (!stream) {
11720     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11721     return;
11722   }
11723
11724   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11725
11726   if (sys_bitrate < sum_bitrate) {
11727     /* This can happen, since sum_bitrate might be derived from maximum
11728      * bitrates and not average bitrates */
11729     GST_DEBUG_OBJECT (qtdemux,
11730         "System bitrate less than sum bitrate - bailing");
11731     return;
11732   }
11733
11734   bitrate = sys_bitrate - sum_bitrate;
11735   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11736       ", Stream bitrate = %u", sys_bitrate, bitrate);
11737
11738   if (!stream->stream_tags)
11739     stream->stream_tags = gst_tag_list_new_empty ();
11740   else
11741     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11742
11743   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11744       GST_TAG_BITRATE, bitrate, NULL);
11745 }
11746
11747 static GstFlowReturn
11748 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11749 {
11750   gint i;
11751   GstFlowReturn ret = GST_FLOW_OK;
11752
11753   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11754
11755   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11756     QtDemuxStream *stream = qtdemux->streams[i];
11757     guint32 sample_num = 0;
11758
11759     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11760         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11761
11762     if (qtdemux->fragmented) {
11763       /* need all moov samples first */
11764       GST_OBJECT_LOCK (qtdemux);
11765       while (stream->n_samples == 0)
11766         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11767           break;
11768       GST_OBJECT_UNLOCK (qtdemux);
11769     } else {
11770       /* discard any stray moof */
11771       qtdemux->moof_offset = 0;
11772     }
11773
11774     /* prepare braking */
11775     if (ret != GST_FLOW_ERROR)
11776       ret = GST_FLOW_OK;
11777
11778     /* in pull mode, we should have parsed some sample info by now;
11779      * and quite some code will not handle no samples.
11780      * in push mode, we'll just have to deal with it */
11781     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11782       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11783       gst_qtdemux_remove_stream (qtdemux, i);
11784       i--;
11785       continue;
11786     }
11787
11788     /* parse the initial sample for use in setting the frame rate cap */
11789     while (sample_num == 0 && sample_num < stream->n_samples) {
11790       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11791         break;
11792       ++sample_num;
11793     }
11794     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11795       stream->first_duration = stream->samples[0].duration;
11796       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11797           stream->track_id, stream->first_duration);
11798     }
11799   }
11800
11801   return ret;
11802 }
11803
11804 static GstFlowReturn
11805 qtdemux_expose_streams (GstQTDemux * qtdemux)
11806 {
11807   gint i;
11808   GSList *oldpads = NULL;
11809   GSList *iter;
11810
11811   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11812
11813   for (i = 0; i < qtdemux->n_streams; i++) {
11814     QtDemuxStream *stream = qtdemux->streams[i];
11815     GstPad *oldpad = stream->pad;
11816     GstTagList *list;
11817
11818     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11819         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11820
11821     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11822         stream->track_id == qtdemux->chapters_track_id) {
11823       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11824          so that it doesn't look like a subtitle track */
11825       gst_qtdemux_remove_stream (qtdemux, i);
11826       i--;
11827       continue;
11828     }
11829
11830     /* now we have all info and can expose */
11831     list = stream->stream_tags;
11832     stream->stream_tags = NULL;
11833     if (oldpad)
11834       oldpads = g_slist_prepend (oldpads, oldpad);
11835     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11836       return GST_FLOW_ERROR;
11837   }
11838
11839   gst_qtdemux_guess_bitrate (qtdemux);
11840
11841   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11842
11843   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11844     GstPad *oldpad = iter->data;
11845     GstEvent *event;
11846
11847     event = gst_event_new_eos ();
11848     if (qtdemux->segment_seqnum)
11849       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11850
11851     gst_pad_push_event (oldpad, event);
11852     gst_pad_set_active (oldpad, FALSE);
11853     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11854     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11855     gst_object_unref (oldpad);
11856   }
11857
11858   /* check if we should post a redirect in case there is a single trak
11859    * and it is a redirecting trak */
11860   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11861     GstMessage *m;
11862
11863     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11864         "an external content");
11865     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11866         gst_structure_new ("redirect",
11867             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11868             NULL));
11869     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11870     qtdemux->posted_redirect = TRUE;
11871   }
11872
11873   for (i = 0; i < qtdemux->n_streams; i++) {
11874     QtDemuxStream *stream = qtdemux->streams[i];
11875
11876     qtdemux_do_allocation (qtdemux, stream);
11877   }
11878
11879   qtdemux->exposed = TRUE;
11880   return GST_FLOW_OK;
11881 }
11882
11883 /* check if major or compatible brand is 3GP */
11884 static inline gboolean
11885 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11886 {
11887   if (major) {
11888     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11889         FOURCC_3g__);
11890   } else if (qtdemux->comp_brands != NULL) {
11891     GstMapInfo map;
11892     guint8 *data;
11893     gsize size;
11894     gboolean res = FALSE;
11895
11896     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11897     data = map.data;
11898     size = map.size;
11899     while (size >= 4) {
11900       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11901           FOURCC_3g__);
11902       data += 4;
11903       size -= 4;
11904     }
11905     gst_buffer_unmap (qtdemux->comp_brands, &map);
11906     return res;
11907   } else {
11908     return FALSE;
11909   }
11910 }
11911
11912 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11913 static inline gboolean
11914 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11915 {
11916   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11917       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11918       || fourcc == FOURCC_albm;
11919 }
11920
11921 static void
11922 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11923     const char *tag, const char *dummy, GNode * node)
11924 {
11925   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11926   int offset;
11927   char *name;
11928   gchar *data;
11929   gdouble longitude, latitude, altitude;
11930   gint len;
11931
11932   len = QT_UINT32 (node->data);
11933   if (len <= 14)
11934     goto short_read;
11935
11936   data = node->data;
11937   offset = 14;
11938
11939   /* TODO: language code skipped */
11940
11941   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11942
11943   if (!name) {
11944     /* do not alarm in trivial case, but bail out otherwise */
11945     if (*(data + offset) != 0) {
11946       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11947           "giving up", tag);
11948     }
11949   } else {
11950     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11951         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11952     offset += strlen (name);
11953     g_free (name);
11954   }
11955
11956   if (len < offset + 2 + 4 + 4 + 4)
11957     goto short_read;
11958
11959   /* +1 +1 = skip null-terminator and location role byte */
11960   offset += 1 + 1;
11961   /* table in spec says unsigned, semantics say negative has meaning ... */
11962   longitude = QT_SFP32 (data + offset);
11963
11964   offset += 4;
11965   latitude = QT_SFP32 (data + offset);
11966
11967   offset += 4;
11968   altitude = QT_SFP32 (data + offset);
11969
11970   /* one invalid means all are invalid */
11971   if (longitude >= -180.0 && longitude <= 180.0 &&
11972       latitude >= -90.0 && latitude <= 90.0) {
11973     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11974         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11975         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11976         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11977   }
11978
11979   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11980
11981   return;
11982
11983   /* ERRORS */
11984 short_read:
11985   {
11986     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11987     return;
11988   }
11989 }
11990
11991
11992 static void
11993 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11994     const char *tag, const char *dummy, GNode * node)
11995 {
11996   guint16 y;
11997   GDate *date;
11998   gint len;
11999
12000   len = QT_UINT32 (node->data);
12001   if (len < 14)
12002     return;
12003
12004   y = QT_UINT16 ((guint8 *) node->data + 12);
12005   if (y == 0) {
12006     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12007     return;
12008   }
12009   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12010
12011   date = g_date_new_dmy (1, 1, y);
12012   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12013   g_date_free (date);
12014 }
12015
12016 static void
12017 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12018     const char *tag, const char *dummy, GNode * node)
12019 {
12020   int offset;
12021   char *tag_str = NULL;
12022   guint8 *entity;
12023   guint16 table;
12024   gint len;
12025
12026   len = QT_UINT32 (node->data);
12027   if (len <= 20)
12028     goto short_read;
12029
12030   offset = 12;
12031   entity = (guint8 *) node->data + offset;
12032   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12033     GST_DEBUG_OBJECT (qtdemux,
12034         "classification info: %c%c%c%c invalid classification entity",
12035         entity[0], entity[1], entity[2], entity[3]);
12036     return;
12037   }
12038
12039   offset += 4;
12040   table = QT_UINT16 ((guint8 *) node->data + offset);
12041
12042   /* Language code skipped */
12043
12044   offset += 4;
12045
12046   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12047    * XXXX: classification entity, fixed length 4 chars.
12048    * Y[YYYY]: classification table, max 5 chars.
12049    */
12050   tag_str = g_strdup_printf ("----://%u/%s",
12051       table, (char *) node->data + offset);
12052
12053   /* memcpy To be sure we're preserving byte order */
12054   memcpy (tag_str, entity, 4);
12055   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12056
12057   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12058
12059   g_free (tag_str);
12060
12061   return;
12062
12063   /* ERRORS */
12064 short_read:
12065   {
12066     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12067     return;
12068   }
12069 }
12070
12071 static gboolean
12072 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12073     const char *tag, const char *dummy, GNode * node)
12074 {
12075   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12076   GNode *data;
12077   char *s;
12078   int len;
12079   guint32 type;
12080   int offset;
12081   gboolean ret = TRUE;
12082   const gchar *charset = NULL;
12083
12084   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12085   if (data) {
12086     len = QT_UINT32 (data->data);
12087     type = QT_UINT32 ((guint8 *) data->data + 8);
12088     if (type == 0x00000001 && len > 16) {
12089       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12090           env_vars);
12091       if (s) {
12092         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12093         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12094         g_free (s);
12095       } else {
12096         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12097       }
12098     }
12099   } else {
12100     len = QT_UINT32 (node->data);
12101     type = QT_UINT32 ((guint8 *) node->data + 4);
12102     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12103       gint str_len;
12104       gint lang_code;
12105
12106       /* Type starts with the (C) symbol, so the next data is a list
12107        * of (string size(16), language code(16), string) */
12108
12109       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12110       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12111
12112       /* the string + fourcc + size + 2 16bit fields,
12113        * means that there are more tags in this atom */
12114       if (len > str_len + 8 + 4) {
12115         /* TODO how to represent the same tag in different languages? */
12116         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12117             "text alternatives, reading only first one");
12118       }
12119
12120       offset = 12;
12121       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12122       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12123
12124       if (lang_code < 0x800) {  /* MAC encoded string */
12125         charset = "mac";
12126       }
12127     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12128             QT_FOURCC ((guint8 *) node->data + 4))) {
12129       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12130
12131       /* we go for 3GP style encoding if major brands claims so,
12132        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12133       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12134           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12135               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12136         offset = 14;
12137         /* 16-bit Language code is ignored here as well */
12138         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12139       } else {
12140         goto normal;
12141       }
12142     } else {
12143     normal:
12144       offset = 8;
12145       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12146       ret = FALSE;              /* may have to fallback */
12147     }
12148     if (charset) {
12149       GError *err = NULL;
12150
12151       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12152           charset, NULL, NULL, &err);
12153       if (err) {
12154         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12155             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12156             err->message);
12157         g_error_free (err);
12158       }
12159     } else {
12160       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12161           len - offset, env_vars);
12162     }
12163     if (s) {
12164       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12165       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12166       g_free (s);
12167       ret = TRUE;
12168     } else {
12169       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12170     }
12171   }
12172   return ret;
12173 }
12174
12175 static void
12176 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12177     const char *tag, const char *dummy, GNode * node)
12178 {
12179   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12180 }
12181
12182 static void
12183 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12184     const char *tag, const char *dummy, GNode * node)
12185 {
12186   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12187   guint8 *data;
12188   char *s, *t, *k = NULL;
12189   int len;
12190   int offset;
12191   int count;
12192
12193   /* first try normal string tag if major brand not 3GP */
12194   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12195     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12196       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12197        * let's try it 3gpp way after minor safety check */
12198       data = node->data;
12199       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12200         return;
12201     } else
12202       return;
12203   }
12204
12205   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12206
12207   data = node->data;
12208
12209   len = QT_UINT32 (data);
12210   if (len < 15)
12211     goto short_read;
12212
12213   count = QT_UINT8 (data + 14);
12214   offset = 15;
12215   for (; count; count--) {
12216     gint slen;
12217
12218     if (offset + 1 > len)
12219       goto short_read;
12220     slen = QT_UINT8 (data + offset);
12221     offset += 1;
12222     if (offset + slen > len)
12223       goto short_read;
12224     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12225         slen, env_vars);
12226     if (s) {
12227       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12228       if (k) {
12229         t = g_strjoin (",", k, s, NULL);
12230         g_free (s);
12231         g_free (k);
12232         k = t;
12233       } else {
12234         k = s;
12235       }
12236     } else {
12237       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12238     }
12239     offset += slen;
12240   }
12241
12242 done:
12243   if (k) {
12244     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12245     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12246   }
12247   g_free (k);
12248
12249   return;
12250
12251   /* ERRORS */
12252 short_read:
12253   {
12254     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12255     goto done;
12256   }
12257 }
12258
12259 static void
12260 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12261     const char *tag1, const char *tag2, GNode * node)
12262 {
12263   GNode *data;
12264   int len;
12265   int type;
12266   int n1, n2;
12267
12268   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12269   if (data) {
12270     len = QT_UINT32 (data->data);
12271     type = QT_UINT32 ((guint8 *) data->data + 8);
12272     if (type == 0x00000000 && len >= 22) {
12273       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12274       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12275       if (n1 > 0) {
12276         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12277         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12278       }
12279       if (n2 > 0) {
12280         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12281         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12282       }
12283     }
12284   }
12285 }
12286
12287 static void
12288 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12289     const char *tag1, const char *dummy, GNode * node)
12290 {
12291   GNode *data;
12292   int len;
12293   int type;
12294   int n1;
12295
12296   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12297   if (data) {
12298     len = QT_UINT32 (data->data);
12299     type = QT_UINT32 ((guint8 *) data->data + 8);
12300     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12301     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12302     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12303       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12304       if (n1) {
12305         /* do not add bpm=0 */
12306         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12307         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12308             NULL);
12309       }
12310     }
12311   }
12312 }
12313
12314 static void
12315 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12316     const char *tag1, const char *dummy, GNode * node)
12317 {
12318   GNode *data;
12319   int len;
12320   int type;
12321   guint32 num;
12322
12323   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12324   if (data) {
12325     len = QT_UINT32 (data->data);
12326     type = QT_UINT32 ((guint8 *) data->data + 8);
12327     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12328     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12329     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12330       num = QT_UINT32 ((guint8 *) data->data + 16);
12331       if (num) {
12332         /* do not add num=0 */
12333         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12334         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12335       }
12336     }
12337   }
12338 }
12339
12340 static void
12341 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12342     const char *tag1, const char *dummy, GNode * node)
12343 {
12344   GNode *data;
12345   int len;
12346   int type;
12347   GstSample *sample;
12348
12349   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12350   if (data) {
12351     len = QT_UINT32 (data->data);
12352     type = QT_UINT32 ((guint8 *) data->data + 8);
12353     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12354     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12355       GstTagImageType image_type;
12356
12357       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12358         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12359       else
12360         image_type = GST_TAG_IMAGE_TYPE_NONE;
12361
12362       if ((sample =
12363               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12364                   len - 16, image_type))) {
12365         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12366         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12367         gst_sample_unref (sample);
12368       }
12369     }
12370   }
12371 }
12372
12373 static void
12374 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12375     const char *tag, const char *dummy, GNode * node)
12376 {
12377   GNode *data;
12378   char *s;
12379   int len;
12380   int type;
12381
12382   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12383   if (data) {
12384     len = QT_UINT32 (data->data);
12385     type = QT_UINT32 ((guint8 *) data->data + 8);
12386     if (type == 0x00000001 && len > 16) {
12387       guint y, m = 1, d = 1;
12388       gint ret;
12389
12390       s = g_strndup ((char *) data->data + 16, len - 16);
12391       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12392       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12393       if (ret >= 1 && y > 1500 && y < 3000) {
12394         GDate *date;
12395
12396         date = g_date_new_dmy (d, m, y);
12397         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12398         g_date_free (date);
12399       } else {
12400         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12401       }
12402       g_free (s);
12403     }
12404   }
12405 }
12406
12407 static void
12408 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12409     const char *tag, const char *dummy, GNode * node)
12410 {
12411   GNode *data;
12412
12413   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12414
12415   /* re-route to normal string tag if major brand says so
12416    * or no data atom and compatible brand suggests so */
12417   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12418       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12419     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12420     return;
12421   }
12422
12423   if (data) {
12424     guint len, type, n;
12425
12426     len = QT_UINT32 (data->data);
12427     type = QT_UINT32 ((guint8 *) data->data + 8);
12428     if (type == 0x00000000 && len >= 18) {
12429       n = QT_UINT16 ((guint8 *) data->data + 16);
12430       if (n > 0) {
12431         const gchar *genre;
12432
12433         genre = gst_tag_id3_genre_get (n - 1);
12434         if (genre != NULL) {
12435           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12436           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12437         }
12438       }
12439     }
12440   }
12441 }
12442
12443 static void
12444 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12445     const gchar * tag, guint8 * data, guint32 datasize)
12446 {
12447   gdouble value;
12448   gchar *datacopy;
12449
12450   /* make a copy to have \0 at the end */
12451   datacopy = g_strndup ((gchar *) data, datasize);
12452
12453   /* convert the str to double */
12454   if (sscanf (datacopy, "%lf", &value) == 1) {
12455     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12456     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12457   } else {
12458     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12459         datacopy);
12460   }
12461   g_free (datacopy);
12462 }
12463
12464
12465 static void
12466 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12467     const char *tag, const char *tag_bis, GNode * node)
12468 {
12469   GNode *mean;
12470   GNode *name;
12471   GNode *data;
12472   guint32 meansize;
12473   guint32 namesize;
12474   guint32 datatype;
12475   guint32 datasize;
12476   const gchar *meanstr;
12477   const gchar *namestr;
12478
12479   /* checking the whole ---- atom size for consistency */
12480   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12481     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12482     return;
12483   }
12484
12485   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12486   if (!mean) {
12487     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12488     return;
12489   }
12490
12491   meansize = QT_UINT32 (mean->data);
12492   if (meansize <= 12) {
12493     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12494     return;
12495   }
12496   meanstr = ((gchar *) mean->data) + 12;
12497   meansize -= 12;
12498
12499   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12500   if (!name) {
12501     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12502     return;
12503   }
12504
12505   namesize = QT_UINT32 (name->data);
12506   if (namesize <= 12) {
12507     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12508     return;
12509   }
12510   namestr = ((gchar *) name->data) + 12;
12511   namesize -= 12;
12512
12513   /*
12514    * Data atom is:
12515    * uint32 - size
12516    * uint32 - name
12517    * uint8  - version
12518    * uint24 - data type
12519    * uint32 - all 0
12520    * rest   - the data
12521    */
12522   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12523   if (!data) {
12524     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12525     return;
12526   }
12527   datasize = QT_UINT32 (data->data);
12528   if (datasize <= 16) {
12529     GST_WARNING_OBJECT (demux, "Data atom too small");
12530     return;
12531   }
12532   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12533
12534   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12535       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12536     static const struct
12537     {
12538       const gchar name[28];
12539       const gchar tag[28];
12540     } tags[] = {
12541       {
12542       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12543       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12544       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12545       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12546       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12547       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12548       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12549       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12550     };
12551     int i;
12552
12553     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12554       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12555         switch (gst_tag_get_type (tags[i].tag)) {
12556           case G_TYPE_DOUBLE:
12557             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12558                 ((guint8 *) data->data) + 16, datasize - 16);
12559             break;
12560           case G_TYPE_STRING:
12561             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12562             break;
12563           default:
12564             /* not reached */
12565             break;
12566         }
12567         break;
12568       }
12569     }
12570     if (i == G_N_ELEMENTS (tags))
12571       goto unknown_tag;
12572   } else {
12573     goto unknown_tag;
12574   }
12575
12576   return;
12577
12578 /* errors */
12579 unknown_tag:
12580 #ifndef GST_DISABLE_GST_DEBUG
12581   {
12582     gchar *namestr_dbg;
12583     gchar *meanstr_dbg;
12584
12585     meanstr_dbg = g_strndup (meanstr, meansize);
12586     namestr_dbg = g_strndup (namestr, namesize);
12587
12588     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12589         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12590
12591     g_free (namestr_dbg);
12592     g_free (meanstr_dbg);
12593   }
12594 #endif
12595   return;
12596 }
12597
12598 static void
12599 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12600     const char *tag_bis, GNode * node)
12601 {
12602   guint8 *data;
12603   GstBuffer *buf;
12604   guint len;
12605   GstTagList *id32_taglist = NULL;
12606
12607   GST_LOG_OBJECT (demux, "parsing ID32");
12608
12609   data = node->data;
12610   len = GST_READ_UINT32_BE (data);
12611
12612   /* need at least full box and language tag */
12613   if (len < 12 + 2)
12614     return;
12615
12616   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12617   gst_buffer_fill (buf, 0, data + 14, len - 14);
12618
12619   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12620   if (id32_taglist) {
12621     GST_LOG_OBJECT (demux, "parsing ok");
12622     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12623     gst_tag_list_unref (id32_taglist);
12624   } else {
12625     GST_LOG_OBJECT (demux, "parsing failed");
12626   }
12627
12628   gst_buffer_unref (buf);
12629 }
12630
12631 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12632     const char *tag, const char *tag_bis, GNode * node);
12633
12634 /* unmapped tags
12635 FOURCC_pcst -> if media is a podcast -> bool
12636 FOURCC_cpil -> if media is part of a compilation -> bool
12637 FOURCC_pgap -> if media is part of a gapless context -> bool
12638 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12639 */
12640
12641 static const struct
12642 {
12643   guint32 fourcc;
12644   const gchar *gst_tag;
12645   const gchar *gst_tag_bis;
12646   const GstQTDemuxAddTagFunc func;
12647 } add_funcs[] = {
12648   {
12649   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12650   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12651   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12652   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12653   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12654   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12655   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12656   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12657   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12658   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12659   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12660   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12661   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12662   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12663   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12664   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12665   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12666   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12667   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12668   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12669   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12670   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12671   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12672         qtdemux_tag_add_num}, {
12673   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12674         qtdemux_tag_add_num}, {
12675   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12676   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12677   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12678   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12679   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12680   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12681   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12682   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12683   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12684   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12685   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12686   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12687   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12688   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12689   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12690   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12691   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12692   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12693         qtdemux_tag_add_classification}, {
12694   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12695   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12696   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12697
12698     /* This is a special case, some tags are stored in this
12699      * 'reverse dns naming', according to:
12700      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12701      * bug #614471
12702      */
12703   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12704     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12705   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12706 };
12707
12708 struct _GstQtDemuxTagList
12709 {
12710   GstQTDemux *demux;
12711   GstTagList *taglist;
12712 };
12713 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12714
12715 static void
12716 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12717 {
12718   gint len;
12719   guint8 *data;
12720   GstBuffer *buf;
12721   gchar *media_type;
12722   const gchar *style;
12723   GstSample *sample;
12724   GstStructure *s;
12725   guint i;
12726   guint8 ndata[4];
12727   GstQTDemux *demux = qtdemuxtaglist->demux;
12728   GstTagList *taglist = qtdemuxtaglist->taglist;
12729
12730   data = node->data;
12731   len = QT_UINT32 (data);
12732   buf = gst_buffer_new_and_alloc (len);
12733   gst_buffer_fill (buf, 0, data, len);
12734
12735   /* heuristic to determine style of tag */
12736   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12737       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12738     style = "itunes";
12739   else if (demux->major_brand == FOURCC_qt__)
12740     style = "quicktime";
12741   /* fall back to assuming iso/3gp tag style */
12742   else
12743     style = "iso";
12744
12745   /* santize the name for the caps. */
12746   for (i = 0; i < 4; i++) {
12747     guint8 d = data[4 + i];
12748     if (g_ascii_isalnum (d))
12749       ndata[i] = g_ascii_tolower (d);
12750     else
12751       ndata[i] = '_';
12752   }
12753
12754   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12755       ndata[0], ndata[1], ndata[2], ndata[3]);
12756   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12757
12758   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12759   sample = gst_sample_new (buf, NULL, NULL, s);
12760   gst_buffer_unref (buf);
12761   g_free (media_type);
12762
12763   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12764       len, s);
12765
12766   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12767       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12768
12769   gst_sample_unref (sample);
12770 }
12771
12772 static void
12773 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12774 {
12775   GNode *meta;
12776   GNode *ilst;
12777   GNode *xmp_;
12778   GNode *node;
12779   gint i;
12780   GstQtDemuxTagList demuxtaglist;
12781
12782   demuxtaglist.demux = qtdemux;
12783   demuxtaglist.taglist = taglist;
12784
12785   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12786   if (meta != NULL) {
12787     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12788     if (ilst == NULL) {
12789       GST_LOG_OBJECT (qtdemux, "no ilst");
12790       return;
12791     }
12792   } else {
12793     ilst = udta;
12794     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12795   }
12796
12797   i = 0;
12798   while (i < G_N_ELEMENTS (add_funcs)) {
12799     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12800     if (node) {
12801       gint len;
12802
12803       len = QT_UINT32 (node->data);
12804       if (len < 12) {
12805         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12806             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12807       } else {
12808         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12809             add_funcs[i].gst_tag_bis, node);
12810       }
12811       g_node_destroy (node);
12812     } else {
12813       i++;
12814     }
12815   }
12816
12817   /* parsed nodes have been removed, pass along remainder as blob */
12818   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12819       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12820
12821   /* parse up XMP_ node if existing */
12822   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12823   if (xmp_ != NULL) {
12824     GstBuffer *buf;
12825     GstTagList *xmptaglist;
12826
12827     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12828         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12829     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12830     gst_buffer_unref (buf);
12831
12832     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12833   } else {
12834     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12835   }
12836 }
12837
12838 typedef struct
12839 {
12840   GstStructure *structure;      /* helper for sort function */
12841   gchar *location;
12842   guint min_req_bitrate;
12843   guint min_req_qt_version;
12844 } GstQtReference;
12845
12846 static gint
12847 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12848 {
12849   GstQtReference *ref_a = (GstQtReference *) a;
12850   GstQtReference *ref_b = (GstQtReference *) b;
12851
12852   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12853     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12854
12855   /* known bitrates go before unknown; higher bitrates go first */
12856   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12857 }
12858
12859 /* sort the redirects and post a message for the application.
12860  */
12861 static void
12862 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12863 {
12864   GstQtReference *best;
12865   GstStructure *s;
12866   GstMessage *msg;
12867   GValue list_val = { 0, };
12868   GList *l;
12869
12870   g_assert (references != NULL);
12871
12872   references = g_list_sort (references, qtdemux_redirects_sort_func);
12873
12874   best = (GstQtReference *) references->data;
12875
12876   g_value_init (&list_val, GST_TYPE_LIST);
12877
12878   for (l = references; l != NULL; l = l->next) {
12879     GstQtReference *ref = (GstQtReference *) l->data;
12880     GValue struct_val = { 0, };
12881
12882     ref->structure = gst_structure_new ("redirect",
12883         "new-location", G_TYPE_STRING, ref->location, NULL);
12884
12885     if (ref->min_req_bitrate > 0) {
12886       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12887           ref->min_req_bitrate, NULL);
12888     }
12889
12890     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12891     g_value_set_boxed (&struct_val, ref->structure);
12892     gst_value_list_append_value (&list_val, &struct_val);
12893     g_value_unset (&struct_val);
12894     /* don't free anything here yet, since we need best->structure below */
12895   }
12896
12897   g_assert (best != NULL);
12898   s = gst_structure_copy (best->structure);
12899
12900   if (g_list_length (references) > 1) {
12901     gst_structure_set_value (s, "locations", &list_val);
12902   }
12903
12904   g_value_unset (&list_val);
12905
12906   for (l = references; l != NULL; l = l->next) {
12907     GstQtReference *ref = (GstQtReference *) l->data;
12908
12909     gst_structure_free (ref->structure);
12910     g_free (ref->location);
12911     g_free (ref);
12912   }
12913   g_list_free (references);
12914
12915   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12916   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12917   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12918   qtdemux->posted_redirect = TRUE;
12919 }
12920
12921 /* look for redirect nodes, collect all redirect information and
12922  * process it.
12923  */
12924 static gboolean
12925 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12926 {
12927   GNode *rmra, *rmda, *rdrf;
12928
12929   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12930   if (rmra) {
12931     GList *redirects = NULL;
12932
12933     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12934     while (rmda) {
12935       GstQtReference ref = { NULL, NULL, 0, 0 };
12936       GNode *rmdr, *rmvc;
12937
12938       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12939         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12940         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12941             ref.min_req_bitrate);
12942       }
12943
12944       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12945         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12946         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12947
12948 #ifndef GST_DISABLE_GST_DEBUG
12949         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12950 #endif
12951         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12952
12953         GST_LOG_OBJECT (qtdemux,
12954             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12955             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12956             bitmask, check_type);
12957         if (package == FOURCC_qtim && check_type == 0) {
12958           ref.min_req_qt_version = version;
12959         }
12960       }
12961
12962       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12963       if (rdrf) {
12964         guint32 ref_type;
12965         guint8 *ref_data;
12966         guint ref_len;
12967
12968         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12969         if (ref_len > 20) {
12970           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12971           ref_data = (guint8 *) rdrf->data + 20;
12972           if (ref_type == FOURCC_alis) {
12973             guint record_len, record_version, fn_len;
12974
12975             if (ref_len > 70) {
12976               /* MacOSX alias record, google for alias-layout.txt */
12977               record_len = QT_UINT16 (ref_data + 4);
12978               record_version = QT_UINT16 (ref_data + 4 + 2);
12979               fn_len = QT_UINT8 (ref_data + 50);
12980               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12981                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12982               }
12983             } else {
12984               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12985                   ref_len);
12986             }
12987           } else if (ref_type == FOURCC_url_) {
12988             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12989           } else {
12990             GST_DEBUG_OBJECT (qtdemux,
12991                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12992                 GST_FOURCC_ARGS (ref_type));
12993           }
12994           if (ref.location != NULL) {
12995             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12996             redirects =
12997                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12998           } else {
12999             GST_WARNING_OBJECT (qtdemux,
13000                 "Failed to extract redirect location from rdrf atom");
13001           }
13002         } else {
13003           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13004         }
13005       }
13006
13007       /* look for others */
13008       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13009     }
13010
13011     if (redirects != NULL) {
13012       qtdemux_process_redirects (qtdemux, redirects);
13013     }
13014   }
13015   return TRUE;
13016 }
13017
13018 static GstTagList *
13019 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13020 {
13021   const gchar *fmt;
13022
13023   if (tags == NULL) {
13024     tags = gst_tag_list_new_empty ();
13025     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13026   }
13027
13028   if (qtdemux->major_brand == FOURCC_mjp2)
13029     fmt = "Motion JPEG 2000";
13030   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13031     fmt = "3GP";
13032   else if (qtdemux->major_brand == FOURCC_qt__)
13033     fmt = "Quicktime";
13034   else if (qtdemux->fragmented)
13035     fmt = "ISO fMP4";
13036   else
13037     fmt = "ISO MP4/M4A";
13038
13039   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13040       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13041
13042   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13043       fmt, NULL);
13044
13045   return tags;
13046 }
13047
13048 /* we have read the complete moov node now.
13049  * This function parses all of the relevant info, creates the traks and
13050  * prepares all data structures for playback
13051  */
13052 static gboolean
13053 qtdemux_parse_tree (GstQTDemux * qtdemux)
13054 {
13055   GNode *mvhd;
13056   GNode *trak;
13057   GNode *udta;
13058   GNode *mvex;
13059   GstClockTime duration;
13060   GNode *pssh;
13061   guint64 creation_time;
13062   GstDateTime *datetime = NULL;
13063   gint version;
13064
13065   /* make sure we have a usable taglist */
13066   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13067
13068   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13069   if (mvhd == NULL) {
13070     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13071     return qtdemux_parse_redirects (qtdemux);
13072   }
13073
13074   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13075   if (version == 1) {
13076     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13077     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13078     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13079   } else if (version == 0) {
13080     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13081     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13082     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13083   } else {
13084     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13085     return FALSE;
13086   }
13087
13088   /* Moving qt creation time (secs since 1904) to unix time */
13089   if (creation_time != 0) {
13090     /* Try to use epoch first as it should be faster and more commonly found */
13091     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13092       GTimeVal now;
13093
13094       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13095       /* some data cleansing sanity */
13096       g_get_current_time (&now);
13097       if (now.tv_sec + 24 * 3600 < creation_time) {
13098         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13099       } else {
13100         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13101       }
13102     } else {
13103       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13104       GDateTime *dt, *dt_local;
13105
13106       dt = g_date_time_add_seconds (base_dt, creation_time);
13107       dt_local = g_date_time_to_local (dt);
13108       datetime = gst_date_time_new_from_g_date_time (dt_local);
13109
13110       g_date_time_unref (base_dt);
13111       g_date_time_unref (dt);
13112     }
13113   }
13114   if (datetime) {
13115     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13116     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13117         datetime, NULL);
13118     gst_date_time_unref (datetime);
13119   }
13120
13121   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13122   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13123
13124   /* check for fragmented file and get some (default) data */
13125   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13126   if (mvex) {
13127     GNode *mehd;
13128     GstByteReader mehd_data;
13129
13130     /* let track parsing or anyone know weird stuff might happen ... */
13131     qtdemux->fragmented = TRUE;
13132
13133     /* compensate for total duration */
13134     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13135     if (mehd)
13136       qtdemux_parse_mehd (qtdemux, &mehd_data);
13137   }
13138
13139   /* set duration in the segment info */
13140   gst_qtdemux_get_duration (qtdemux, &duration);
13141   if (duration) {
13142     qtdemux->segment.duration = duration;
13143     /* also do not exceed duration; stop is set that way post seek anyway,
13144      * and segment activation falls back to duration,
13145      * whereas loop only checks stop, so let's align this here as well */
13146     qtdemux->segment.stop = duration;
13147   }
13148
13149   /* parse all traks */
13150   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13151   while (trak) {
13152     qtdemux_parse_trak (qtdemux, trak);
13153     /* iterate all siblings */
13154     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13155   }
13156
13157   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13158
13159   /* find tags */
13160   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13161   if (udta) {
13162     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13163   } else {
13164     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13165   }
13166
13167   /* maybe also some tags in meta box */
13168   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13169   if (udta) {
13170     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13171     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13172   } else {
13173     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13174   }
13175
13176   /* parse any protection system info */
13177   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13178   while (pssh) {
13179     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13180     qtdemux_parse_pssh (qtdemux, pssh);
13181     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13182   }
13183
13184   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13185
13186   return TRUE;
13187 }
13188
13189 /* taken from ffmpeg */
13190 static int
13191 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13192 {
13193   int count = 4;
13194   int len = 0;
13195
13196   while (count--) {
13197     int c;
13198
13199     if (ptr >= end)
13200       return -1;
13201
13202     c = *ptr++;
13203     len = (len << 7) | (c & 0x7f);
13204     if (!(c & 0x80))
13205       break;
13206   }
13207   *end_out = ptr;
13208   return len;
13209 }
13210
13211 /* this can change the codec originally present in @list */
13212 static void
13213 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13214     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13215 {
13216   int len = QT_UINT32 (esds->data);
13217   guint8 *ptr = esds->data;
13218   guint8 *end = ptr + len;
13219   int tag;
13220   guint8 *data_ptr = NULL;
13221   int data_len = 0;
13222   guint8 object_type_id = 0;
13223   const char *codec_name = NULL;
13224   GstCaps *caps = NULL;
13225
13226   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13227   ptr += 8;
13228   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13229   ptr += 4;
13230   while (ptr + 1 < end) {
13231     tag = QT_UINT8 (ptr);
13232     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13233     ptr++;
13234     len = read_descr_size (ptr, end, &ptr);
13235     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13236
13237     /* Check the stated amount of data is available for reading */
13238     if (len < 0 || ptr + len > end)
13239       break;
13240
13241     switch (tag) {
13242       case ES_DESCRIPTOR_TAG:
13243         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13244         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13245         ptr += 3;
13246         break;
13247       case DECODER_CONFIG_DESC_TAG:{
13248         guint max_bitrate, avg_bitrate;
13249
13250         object_type_id = QT_UINT8 (ptr);
13251         max_bitrate = QT_UINT32 (ptr + 5);
13252         avg_bitrate = QT_UINT32 (ptr + 9);
13253         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13254         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13255         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13256         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13257         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13258         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13259           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13260               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13261         }
13262         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13263           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13264               avg_bitrate, NULL);
13265         }
13266         ptr += 13;
13267         break;
13268       }
13269       case DECODER_SPECIFIC_INFO_TAG:
13270         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13271         if (object_type_id == 0xe0 && len == 0x40) {
13272           guint8 *data;
13273           GstStructure *s;
13274           guint32 clut[16];
13275           gint i;
13276
13277           GST_DEBUG_OBJECT (qtdemux,
13278               "Have VOBSUB palette. Creating palette event");
13279           /* move to decConfigDescr data and read palette */
13280           data = ptr;
13281           for (i = 0; i < 16; i++) {
13282             clut[i] = QT_UINT32 (data);
13283             data += 4;
13284           }
13285
13286           s = gst_structure_new ("application/x-gst-dvd", "event",
13287               G_TYPE_STRING, "dvd-spu-clut-change",
13288               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13289               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13290               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13291               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13292               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13293               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13294               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13295               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13296               NULL);
13297
13298           /* store event and trigger custom processing */
13299           stream->pending_event =
13300               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13301         } else {
13302           /* Generic codec_data handler puts it on the caps */
13303           data_ptr = ptr;
13304           data_len = len;
13305         }
13306
13307         ptr += len;
13308         break;
13309       case SL_CONFIG_DESC_TAG:
13310         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13311         ptr += 1;
13312         break;
13313       default:
13314         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13315             tag);
13316         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13317         ptr += len;
13318         break;
13319     }
13320   }
13321
13322   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13323    * in use, and should also be used to override some other parameters for some
13324    * codecs. */
13325   switch (object_type_id) {
13326     case 0x20:                 /* MPEG-4 */
13327       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13328        * profile_and_level_indication */
13329       if (data_ptr != NULL && data_len >= 5 &&
13330           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13331         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13332             data_ptr + 4, data_len - 4);
13333       }
13334       break;                    /* Nothing special needed here */
13335     case 0x21:                 /* H.264 */
13336       codec_name = "H.264 / AVC";
13337       caps = gst_caps_new_simple ("video/x-h264",
13338           "stream-format", G_TYPE_STRING, "avc",
13339           "alignment", G_TYPE_STRING, "au", NULL);
13340       break;
13341     case 0x40:                 /* AAC (any) */
13342     case 0x66:                 /* AAC Main */
13343     case 0x67:                 /* AAC LC */
13344     case 0x68:                 /* AAC SSR */
13345       /* Override channels and rate based on the codec_data, as it's often
13346        * wrong. */
13347       /* Only do so for basic setup without HE-AAC extension */
13348       if (data_ptr && data_len == 2) {
13349         guint channels, rate;
13350
13351         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13352         if (channels > 0)
13353           entry->n_channels = channels;
13354
13355         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13356         if (rate > 0)
13357           entry->rate = rate;
13358       }
13359
13360       /* Set level and profile if possible */
13361       if (data_ptr != NULL && data_len >= 2) {
13362         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13363             data_ptr, data_len);
13364       } else {
13365         const gchar *profile_str = NULL;
13366         GstBuffer *buffer;
13367         GstMapInfo map;
13368         guint8 *codec_data;
13369         gint rate_idx, profile;
13370
13371         /* No codec_data, let's invent something.
13372          * FIXME: This is wrong for SBR! */
13373
13374         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13375
13376         buffer = gst_buffer_new_and_alloc (2);
13377         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13378         codec_data = map.data;
13379
13380         rate_idx =
13381             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13382             (stream)->rate);
13383
13384         switch (object_type_id) {
13385           case 0x66:
13386             profile_str = "main";
13387             profile = 0;
13388             break;
13389           case 0x67:
13390             profile_str = "lc";
13391             profile = 1;
13392             break;
13393           case 0x68:
13394             profile_str = "ssr";
13395             profile = 2;
13396             break;
13397           default:
13398             profile = 3;
13399             break;
13400         }
13401
13402         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13403         codec_data[1] =
13404             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13405
13406         gst_buffer_unmap (buffer, &map);
13407         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13408             GST_TYPE_BUFFER, buffer, NULL);
13409         gst_buffer_unref (buffer);
13410
13411         if (profile_str) {
13412           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13413               G_TYPE_STRING, profile_str, NULL);
13414         }
13415       }
13416       break;
13417     case 0x60:                 /* MPEG-2, various profiles */
13418     case 0x61:
13419     case 0x62:
13420     case 0x63:
13421     case 0x64:
13422     case 0x65:
13423       codec_name = "MPEG-2 video";
13424       caps = gst_caps_new_simple ("video/mpeg",
13425           "mpegversion", G_TYPE_INT, 2,
13426           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13427       break;
13428     case 0x69:                 /* MPEG-2 BC audio */
13429     case 0x6B:                 /* MPEG-1 audio */
13430       caps = gst_caps_new_simple ("audio/mpeg",
13431           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13432       codec_name = "MPEG-1 audio";
13433       break;
13434     case 0x6A:                 /* MPEG-1 */
13435       codec_name = "MPEG-1 video";
13436       caps = gst_caps_new_simple ("video/mpeg",
13437           "mpegversion", G_TYPE_INT, 1,
13438           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13439       break;
13440     case 0x6C:                 /* MJPEG */
13441       caps =
13442           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13443           NULL);
13444       codec_name = "Motion-JPEG";
13445       break;
13446     case 0x6D:                 /* PNG */
13447       caps =
13448           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13449           NULL);
13450       codec_name = "PNG still images";
13451       break;
13452     case 0x6E:                 /* JPEG2000 */
13453       codec_name = "JPEG-2000";
13454       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13455       break;
13456     case 0xA4:                 /* Dirac */
13457       codec_name = "Dirac";
13458       caps = gst_caps_new_empty_simple ("video/x-dirac");
13459       break;
13460     case 0xA5:                 /* AC3 */
13461       codec_name = "AC-3 audio";
13462       caps = gst_caps_new_simple ("audio/x-ac3",
13463           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13464       break;
13465     case 0xA9:                 /* AC3 */
13466       codec_name = "DTS audio";
13467       caps = gst_caps_new_simple ("audio/x-dts",
13468           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13469       break;
13470     case 0xE1:                 /* QCELP */
13471       /* QCELP, the codec_data is a riff tag (little endian) with
13472        * 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). */
13473       caps = gst_caps_new_empty_simple ("audio/qcelp");
13474       codec_name = "QCELP";
13475       break;
13476     default:
13477       break;
13478   }
13479
13480   /* If we have a replacement caps, then change our caps for this stream */
13481   if (caps) {
13482     gst_caps_unref (entry->caps);
13483     entry->caps = caps;
13484   }
13485
13486   if (codec_name && list)
13487     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13488         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13489
13490   /* Add the codec_data attribute to caps, if we have it */
13491   if (data_ptr) {
13492     GstBuffer *buffer;
13493
13494     buffer = gst_buffer_new_and_alloc (data_len);
13495     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13496
13497     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13498     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13499
13500     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13501         buffer, NULL);
13502     gst_buffer_unref (buffer);
13503   }
13504
13505 }
13506
13507 static inline GstCaps *
13508 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13509 {
13510   GstCaps *caps;
13511   guint i;
13512   char *s, fourstr[5];
13513
13514   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13515   for (i = 0; i < 4; i++) {
13516     if (!g_ascii_isalnum (fourstr[i]))
13517       fourstr[i] = '_';
13518   }
13519   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13520   caps = gst_caps_new_empty_simple (s);
13521   g_free (s);
13522   return caps;
13523 }
13524
13525 #define _codec(name) \
13526   do { \
13527     if (codec_name) { \
13528       *codec_name = g_strdup (name); \
13529     } \
13530   } while (0)
13531
13532 static GstCaps *
13533 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13534     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13535     const guint8 * stsd_entry_data, gchar ** codec_name)
13536 {
13537   GstCaps *caps = NULL;
13538   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13539
13540   switch (fourcc) {
13541     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
13542       _codec ("PNG still images");
13543       caps = gst_caps_new_empty_simple ("image/png");
13544       break;
13545     case FOURCC_jpeg:
13546       _codec ("JPEG still images");
13547       caps =
13548           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13549           NULL);
13550       break;
13551     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13552     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13553     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13554     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13555       _codec ("Motion-JPEG");
13556       caps =
13557           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13558           NULL);
13559       break;
13560     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13561       _codec ("Motion-JPEG format B");
13562       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13563       break;
13564     case FOURCC_mjp2:
13565       _codec ("JPEG-2000");
13566       /* override to what it should be according to spec, avoid palette_data */
13567       entry->bits_per_sample = 24;
13568       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13569       break;
13570     case FOURCC_SVQ3:
13571       _codec ("Sorensen video v.3");
13572       caps = gst_caps_new_simple ("video/x-svq",
13573           "svqversion", G_TYPE_INT, 3, NULL);
13574       break;
13575     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13576     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13577       _codec ("Sorensen video v.1");
13578       caps = gst_caps_new_simple ("video/x-svq",
13579           "svqversion", G_TYPE_INT, 1, NULL);
13580       break;
13581     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13582       caps = gst_caps_new_empty_simple ("video/x-raw");
13583       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13584       _codec ("Windows Raw RGB");
13585       stream->alignment = 32;
13586       break;
13587     case FOURCC_raw_:
13588     {
13589       guint16 bps;
13590
13591       bps = QT_UINT16 (stsd_entry_data + 82);
13592       switch (bps) {
13593         case 15:
13594           format = GST_VIDEO_FORMAT_RGB15;
13595           break;
13596         case 16:
13597           format = GST_VIDEO_FORMAT_RGB16;
13598           break;
13599         case 24:
13600           format = GST_VIDEO_FORMAT_RGB;
13601           break;
13602         case 32:
13603           format = GST_VIDEO_FORMAT_ARGB;
13604           break;
13605         default:
13606           /* unknown */
13607           break;
13608       }
13609       break;
13610     }
13611     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13612       format = GST_VIDEO_FORMAT_I420;
13613       break;
13614     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13615     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13616       format = GST_VIDEO_FORMAT_I420;
13617       break;
13618     case FOURCC_2vuy:
13619     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13620       format = GST_VIDEO_FORMAT_UYVY;
13621       break;
13622     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13623       format = GST_VIDEO_FORMAT_v308;
13624       break;
13625     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13626       format = GST_VIDEO_FORMAT_v216;
13627       break;
13628     case FOURCC_v210:
13629       format = GST_VIDEO_FORMAT_v210;
13630       break;
13631     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13632       format = GST_VIDEO_FORMAT_r210;
13633       break;
13634       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13635          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13636          format = GST_VIDEO_FORMAT_v410;
13637          break;
13638        */
13639       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13640        * but different order than AYUV
13641        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13642        format = GST_VIDEO_FORMAT_v408;
13643        break;
13644        */
13645     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13646     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13647       _codec ("MPEG-1 video");
13648       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13649           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13650       break;
13651     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13652     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13653     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13654     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13655     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13656     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13657     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13658     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13659     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13660     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13661     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13662     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13663     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13664     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13665     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13666     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13667     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13668     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13669     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13670     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13671     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13672     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13673     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13674     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13675     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13676     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13677     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13678     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13679     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13680     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13681     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13682     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13683     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13684     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13685     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13686     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13687     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13688     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13689     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13690     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13691     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13692     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13693     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13694     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13695     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13696     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13697     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13698       _codec ("MPEG-2 video");
13699       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13700           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13701       break;
13702     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13703       _codec ("GIF still images");
13704       caps = gst_caps_new_empty_simple ("image/gif");
13705       break;
13706     case FOURCC_h263:
13707     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13708     case FOURCC_s263:
13709     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13710       _codec ("H.263");
13711       /* ffmpeg uses the height/width props, don't know why */
13712       caps = gst_caps_new_simple ("video/x-h263",
13713           "variant", G_TYPE_STRING, "itu", NULL);
13714       break;
13715     case FOURCC_mp4v:
13716     case FOURCC_MP4V:
13717       _codec ("MPEG-4 video");
13718       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13719           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13720       break;
13721     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13722     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13723       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13724       caps = gst_caps_new_simple ("video/x-msmpeg",
13725           "msmpegversion", G_TYPE_INT, 43, NULL);
13726       break;
13727     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13728       _codec ("DivX 3");
13729       caps = gst_caps_new_simple ("video/x-divx",
13730           "divxversion", G_TYPE_INT, 3, NULL);
13731       break;
13732     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13733     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13734       _codec ("DivX 4");
13735       caps = gst_caps_new_simple ("video/x-divx",
13736           "divxversion", G_TYPE_INT, 4, NULL);
13737       break;
13738     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13739       _codec ("DivX 5");
13740       caps = gst_caps_new_simple ("video/x-divx",
13741           "divxversion", G_TYPE_INT, 5, NULL);
13742       break;
13743
13744     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13745       _codec ("FFV1");
13746       caps = gst_caps_new_simple ("video/x-ffv",
13747           "ffvversion", G_TYPE_INT, 1, NULL);
13748       break;
13749
13750     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13751     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13752     case FOURCC_XVID:
13753     case FOURCC_xvid:
13754     case FOURCC_FMP4:
13755     case FOURCC_fmp4:
13756     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13757       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13758           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13759       _codec ("MPEG-4");
13760       break;
13761
13762     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13763       _codec ("Cinepak");
13764       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13765       break;
13766     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13767       _codec ("Apple QuickDraw");
13768       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13769       break;
13770     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13771       _codec ("Apple video");
13772       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13773       break;
13774     case FOURCC_H264:
13775     case FOURCC_avc1:
13776       _codec ("H.264 / AVC");
13777       caps = gst_caps_new_simple ("video/x-h264",
13778           "stream-format", G_TYPE_STRING, "avc",
13779           "alignment", G_TYPE_STRING, "au", NULL);
13780       break;
13781     case FOURCC_avc3:
13782       _codec ("H.264 / AVC");
13783       caps = gst_caps_new_simple ("video/x-h264",
13784           "stream-format", G_TYPE_STRING, "avc3",
13785           "alignment", G_TYPE_STRING, "au", NULL);
13786       break;
13787     case FOURCC_H265:
13788     case FOURCC_hvc1:
13789       _codec ("H.265 / HEVC");
13790       caps = gst_caps_new_simple ("video/x-h265",
13791           "stream-format", G_TYPE_STRING, "hvc1",
13792           "alignment", G_TYPE_STRING, "au", NULL);
13793       break;
13794     case FOURCC_hev1:
13795       _codec ("H.265 / HEVC");
13796       caps = gst_caps_new_simple ("video/x-h265",
13797           "stream-format", G_TYPE_STRING, "hev1",
13798           "alignment", G_TYPE_STRING, "au", NULL);
13799       break;
13800     case FOURCC_rle_:
13801       _codec ("Run-length encoding");
13802       caps = gst_caps_new_simple ("video/x-rle",
13803           "layout", G_TYPE_STRING, "quicktime", NULL);
13804       break;
13805     case FOURCC_WRLE:
13806       _codec ("Run-length encoding");
13807       caps = gst_caps_new_simple ("video/x-rle",
13808           "layout", G_TYPE_STRING, "microsoft", NULL);
13809       break;
13810     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13811     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13812       _codec ("Indeo Video 3");
13813       caps = gst_caps_new_simple ("video/x-indeo",
13814           "indeoversion", G_TYPE_INT, 3, NULL);
13815       break;
13816     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13817     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13818       _codec ("Intel Video 4");
13819       caps = gst_caps_new_simple ("video/x-indeo",
13820           "indeoversion", G_TYPE_INT, 4, NULL);
13821       break;
13822     case FOURCC_dvcp:
13823     case FOURCC_dvc_:
13824     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13825     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13826     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13827     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13828     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13829     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13830       _codec ("DV Video");
13831       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13832           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13833       break;
13834     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13835     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13836       _codec ("DVCPro50 Video");
13837       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13838           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13839       break;
13840     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13841     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13842       _codec ("DVCProHD Video");
13843       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13844           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13845       break;
13846     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13847       _codec ("Apple Graphics (SMC)");
13848       caps = gst_caps_new_empty_simple ("video/x-smc");
13849       break;
13850     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13851       _codec ("VP3");
13852       caps = gst_caps_new_empty_simple ("video/x-vp3");
13853       break;
13854     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13855       _codec ("VP6 Flash");
13856       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13857       break;
13858     case FOURCC_XiTh:
13859       _codec ("Theora");
13860       caps = gst_caps_new_empty_simple ("video/x-theora");
13861       /* theora uses one byte of padding in the data stream because it does not
13862        * allow 0 sized packets while theora does */
13863       entry->padding = 1;
13864       break;
13865     case FOURCC_drac:
13866       _codec ("Dirac");
13867       caps = gst_caps_new_empty_simple ("video/x-dirac");
13868       break;
13869     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13870       _codec ("TIFF still images");
13871       caps = gst_caps_new_empty_simple ("image/tiff");
13872       break;
13873     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13874       _codec ("Apple Intermediate Codec");
13875       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13876       break;
13877     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13878       _codec ("AVID DNxHD");
13879       caps = gst_caps_from_string ("video/x-dnxhd");
13880       break;
13881     case FOURCC_VP80:
13882       _codec ("On2 VP8");
13883       caps = gst_caps_from_string ("video/x-vp8");
13884       break;
13885     case FOURCC_apcs:
13886       _codec ("Apple ProRes LT");
13887       caps =
13888           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13889           NULL);
13890       break;
13891     case FOURCC_apch:
13892       _codec ("Apple ProRes HQ");
13893       caps =
13894           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13895           NULL);
13896       break;
13897     case FOURCC_apcn:
13898       _codec ("Apple ProRes");
13899       caps =
13900           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13901           "standard", NULL);
13902       break;
13903     case FOURCC_apco:
13904       _codec ("Apple ProRes Proxy");
13905       caps =
13906           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13907           "proxy", NULL);
13908       break;
13909     case FOURCC_ap4h:
13910       _codec ("Apple ProRes 4444");
13911       caps =
13912           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13913           "4444", NULL);
13914       break;
13915     case FOURCC_ap4x:
13916       _codec ("Apple ProRes 4444 XQ");
13917       caps =
13918           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13919           "4444xq", NULL);
13920       break;
13921     case FOURCC_cfhd:
13922       _codec ("GoPro CineForm");
13923       caps = gst_caps_from_string ("video/x-cineform");
13924       break;
13925     case FOURCC_vc_1:
13926     case FOURCC_ovc1:
13927       _codec ("VC-1");
13928       caps = gst_caps_new_simple ("video/x-wmv",
13929           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13930       break;
13931     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13932     default:
13933     {
13934       caps = _get_unknown_codec_name ("video", fourcc);
13935       break;
13936     }
13937   }
13938
13939   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13940     GstVideoInfo info;
13941
13942     gst_video_info_init (&info);
13943     gst_video_info_set_format (&info, format, entry->width, entry->height);
13944
13945     caps = gst_video_info_to_caps (&info);
13946     *codec_name = gst_pb_utils_get_codec_description (caps);
13947
13948     /* enable clipping for raw video streams */
13949     stream->need_clip = TRUE;
13950     stream->alignment = 32;
13951   }
13952
13953   return caps;
13954 }
13955
13956 static guint
13957 round_up_pow2 (guint n)
13958 {
13959   n = n - 1;
13960   n = n | (n >> 1);
13961   n = n | (n >> 2);
13962   n = n | (n >> 4);
13963   n = n | (n >> 8);
13964   n = n | (n >> 16);
13965   return n + 1;
13966 }
13967
13968 static GstCaps *
13969 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13970     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
13971     int len, gchar ** codec_name)
13972 {
13973   GstCaps *caps;
13974   const GstStructure *s;
13975   const gchar *name;
13976   gint endian = 0;
13977   GstAudioFormat format = 0;
13978   gint depth;
13979
13980   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13981
13982   depth = entry->bytes_per_packet * 8;
13983
13984   switch (fourcc) {
13985     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13986     case FOURCC_raw_:
13987       /* 8-bit audio is unsigned */
13988       if (depth == 8)
13989         format = GST_AUDIO_FORMAT_U8;
13990       /* otherwise it's signed and big-endian just like 'twos' */
13991     case FOURCC_twos:
13992       endian = G_BIG_ENDIAN;
13993       /* fall-through */
13994     case FOURCC_sowt:
13995     {
13996       gchar *str;
13997
13998       if (!endian)
13999         endian = G_LITTLE_ENDIAN;
14000
14001       if (!format)
14002         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14003
14004       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14005       _codec (str);
14006       g_free (str);
14007
14008       caps = gst_caps_new_simple ("audio/x-raw",
14009           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14010           "layout", G_TYPE_STRING, "interleaved", NULL);
14011       stream->alignment = GST_ROUND_UP_8 (depth);
14012       stream->alignment = round_up_pow2 (stream->alignment);
14013       break;
14014     }
14015     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14016       _codec ("Raw 64-bit floating-point audio");
14017       caps = gst_caps_new_simple ("audio/x-raw",
14018           "format", G_TYPE_STRING, "F64BE",
14019           "layout", G_TYPE_STRING, "interleaved", NULL);
14020       stream->alignment = 8;
14021       break;
14022     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14023       _codec ("Raw 32-bit floating-point audio");
14024       caps = gst_caps_new_simple ("audio/x-raw",
14025           "format", G_TYPE_STRING, "F32BE",
14026           "layout", G_TYPE_STRING, "interleaved", NULL);
14027       stream->alignment = 4;
14028       break;
14029     case FOURCC_in24:
14030       _codec ("Raw 24-bit PCM audio");
14031       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14032        * endian later */
14033       caps = gst_caps_new_simple ("audio/x-raw",
14034           "format", G_TYPE_STRING, "S24BE",
14035           "layout", G_TYPE_STRING, "interleaved", NULL);
14036       stream->alignment = 4;
14037       break;
14038     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14039       _codec ("Raw 32-bit PCM audio");
14040       caps = gst_caps_new_simple ("audio/x-raw",
14041           "format", G_TYPE_STRING, "S32BE",
14042           "layout", G_TYPE_STRING, "interleaved", NULL);
14043       stream->alignment = 4;
14044       break;
14045     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14046       _codec ("Raw 16-bit PCM audio");
14047       caps = gst_caps_new_simple ("audio/x-raw",
14048           "format", G_TYPE_STRING, "S16LE",
14049           "layout", G_TYPE_STRING, "interleaved", NULL);
14050       stream->alignment = 2;
14051       break;
14052     case FOURCC_ulaw:
14053       _codec ("Mu-law audio");
14054       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14055       break;
14056     case FOURCC_alaw:
14057       _codec ("A-law audio");
14058       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14059       break;
14060     case 0x0200736d:
14061     case 0x6d730002:
14062       _codec ("Microsoft ADPCM");
14063       /* Microsoft ADPCM-ACM code 2 */
14064       caps = gst_caps_new_simple ("audio/x-adpcm",
14065           "layout", G_TYPE_STRING, "microsoft", NULL);
14066       break;
14067     case 0x1100736d:
14068     case 0x6d730011:
14069       _codec ("DVI/IMA ADPCM");
14070       caps = gst_caps_new_simple ("audio/x-adpcm",
14071           "layout", G_TYPE_STRING, "dvi", NULL);
14072       break;
14073     case 0x1700736d:
14074     case 0x6d730017:
14075       _codec ("DVI/Intel IMA ADPCM");
14076       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14077       caps = gst_caps_new_simple ("audio/x-adpcm",
14078           "layout", G_TYPE_STRING, "quicktime", NULL);
14079       break;
14080     case 0x5500736d:
14081     case 0x6d730055:
14082       /* MPEG layer 3, CBR only (pre QT4.1) */
14083     case FOURCC__mp3:
14084       _codec ("MPEG-1 layer 3");
14085       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14086       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14087           "mpegversion", G_TYPE_INT, 1, NULL);
14088       break;
14089     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14090       _codec ("MPEG-1 layer 2");
14091       /* MPEG layer 2 */
14092       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14093           "mpegversion", G_TYPE_INT, 1, NULL);
14094       break;
14095     case 0x20736d:
14096     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14097       _codec ("EAC-3 audio");
14098       caps = gst_caps_new_simple ("audio/x-eac3",
14099           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14100       entry->sampled = TRUE;
14101       break;
14102     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14103     case FOURCC_ac_3:
14104       _codec ("AC-3 audio");
14105       caps = gst_caps_new_simple ("audio/x-ac3",
14106           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14107       entry->sampled = TRUE;
14108       break;
14109     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14110     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14111       _codec ("DTS audio");
14112       caps = gst_caps_new_simple ("audio/x-dts",
14113           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14114       entry->sampled = TRUE;
14115       break;
14116     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14117     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14118       _codec ("DTS-HD audio");
14119       caps = gst_caps_new_simple ("audio/x-dts",
14120           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14121       entry->sampled = TRUE;
14122       break;
14123     case FOURCC_MAC3:
14124       _codec ("MACE-3");
14125       caps = gst_caps_new_simple ("audio/x-mace",
14126           "maceversion", G_TYPE_INT, 3, NULL);
14127       break;
14128     case FOURCC_MAC6:
14129       _codec ("MACE-6");
14130       caps = gst_caps_new_simple ("audio/x-mace",
14131           "maceversion", G_TYPE_INT, 6, NULL);
14132       break;
14133     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14134       /* ogg/vorbis */
14135       caps = gst_caps_new_empty_simple ("application/ogg");
14136       break;
14137     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14138       _codec ("DV audio");
14139       caps = gst_caps_new_empty_simple ("audio/x-dv");
14140       break;
14141     case FOURCC_mp4a:
14142       _codec ("MPEG-4 AAC audio");
14143       caps = gst_caps_new_simple ("audio/mpeg",
14144           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14145           "stream-format", G_TYPE_STRING, "raw", NULL);
14146       break;
14147     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14148       _codec ("QDesign Music");
14149       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14150       break;
14151     case FOURCC_QDM2:
14152       _codec ("QDesign Music v.2");
14153       /* FIXME: QDesign music version 2 (no constant) */
14154       if (FALSE && data) {
14155         caps = gst_caps_new_simple ("audio/x-qdm2",
14156             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14157             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14158             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14159       } else {
14160         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14161       }
14162       break;
14163     case FOURCC_agsm:
14164       _codec ("GSM audio");
14165       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14166       break;
14167     case FOURCC_samr:
14168       _codec ("AMR audio");
14169       caps = gst_caps_new_empty_simple ("audio/AMR");
14170       break;
14171     case FOURCC_sawb:
14172       _codec ("AMR-WB audio");
14173       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14174       break;
14175     case FOURCC_ima4:
14176       _codec ("Quicktime IMA ADPCM");
14177       caps = gst_caps_new_simple ("audio/x-adpcm",
14178           "layout", G_TYPE_STRING, "quicktime", NULL);
14179       break;
14180     case FOURCC_alac:
14181       _codec ("Apple lossless audio");
14182       caps = gst_caps_new_empty_simple ("audio/x-alac");
14183       break;
14184     case FOURCC_fLaC:
14185       _codec ("Free Lossless Audio Codec");
14186       caps = gst_caps_new_simple ("audio/x-flac",
14187           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14188       break;
14189     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14190       _codec ("QualComm PureVoice");
14191       caps = gst_caps_from_string ("audio/qcelp");
14192       break;
14193     case FOURCC_wma_:
14194     case FOURCC_owma:
14195       _codec ("WMA");
14196       caps = gst_caps_new_empty_simple ("audio/x-wma");
14197       break;
14198     case FOURCC_opus:
14199       _codec ("Opus");
14200       caps = gst_caps_new_empty_simple ("audio/x-opus");
14201       break;
14202     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
14203     {
14204       guint32 flags = 0;
14205       guint32 depth = 0;
14206       guint32 width = 0;
14207       GstAudioFormat format;
14208       enum
14209       {
14210         FLAG_IS_FLOAT = 0x1,
14211         FLAG_IS_BIG_ENDIAN = 0x2,
14212         FLAG_IS_SIGNED = 0x4,
14213         FLAG_IS_PACKED = 0x8,
14214         FLAG_IS_ALIGNED_HIGH = 0x10,
14215         FLAG_IS_NON_INTERLEAVED = 0x20
14216       };
14217       _codec ("Raw LPCM audio");
14218
14219       if (data && len >= 56) {
14220         depth = QT_UINT32 (data + 40);
14221         flags = QT_UINT32 (data + 44);
14222         width = QT_UINT32 (data + 48) * 8 / entry->n_channels;
14223       }
14224       if ((flags & FLAG_IS_FLOAT) == 0) {
14225         if (depth == 0)
14226           depth = 16;
14227         if (width == 0)
14228           width = 16;
14229         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14230             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14231             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14232         caps = gst_caps_new_simple ("audio/x-raw",
14233             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14234             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14235             "non-interleaved" : "interleaved", NULL);
14236         stream->alignment = GST_ROUND_UP_8 (depth);
14237         stream->alignment = round_up_pow2 (stream->alignment);
14238       } else {
14239         if (width == 0)
14240           width = 32;
14241         if (width == 64) {
14242           if (flags & FLAG_IS_BIG_ENDIAN)
14243             format = GST_AUDIO_FORMAT_F64BE;
14244           else
14245             format = GST_AUDIO_FORMAT_F64LE;
14246         } else {
14247           if (flags & FLAG_IS_BIG_ENDIAN)
14248             format = GST_AUDIO_FORMAT_F32BE;
14249           else
14250             format = GST_AUDIO_FORMAT_F32LE;
14251         }
14252         caps = gst_caps_new_simple ("audio/x-raw",
14253             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14254             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14255             "non-interleaved" : "interleaved", NULL);
14256         stream->alignment = width / 8;
14257       }
14258       break;
14259     }
14260     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14261       /* ? */
14262     default:
14263     {
14264       caps = _get_unknown_codec_name ("audio", fourcc);
14265       break;
14266     }
14267   }
14268
14269   if (caps) {
14270     GstCaps *templ_caps =
14271         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14272     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14273     gst_caps_unref (caps);
14274     gst_caps_unref (templ_caps);
14275     caps = intersection;
14276   }
14277
14278   /* enable clipping for raw audio streams */
14279   s = gst_caps_get_structure (caps, 0);
14280   name = gst_structure_get_name (s);
14281   if (g_str_has_prefix (name, "audio/x-raw")) {
14282     stream->need_clip = TRUE;
14283     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14284     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14285   }
14286   return caps;
14287 }
14288
14289 static GstCaps *
14290 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14291     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14292     const guint8 * stsd_entry_data, gchar ** codec_name)
14293 {
14294   GstCaps *caps;
14295
14296   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14297
14298   switch (fourcc) {
14299     case FOURCC_mp4s:
14300       _codec ("DVD subtitle");
14301       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14302       stream->need_process = TRUE;
14303       break;
14304     case FOURCC_text:
14305       _codec ("Quicktime timed text");
14306       goto text;
14307     case FOURCC_tx3g:
14308       _codec ("3GPP timed text");
14309     text:
14310       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14311           "utf8", NULL);
14312       /* actual text piece needs to be extracted */
14313       stream->need_process = TRUE;
14314       break;
14315     case FOURCC_stpp:
14316       _codec ("XML subtitles");
14317       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14318       break;
14319     default:
14320     {
14321       caps = _get_unknown_codec_name ("text", fourcc);
14322       break;
14323     }
14324   }
14325   return caps;
14326 }
14327
14328 static GstCaps *
14329 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14330     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14331     const guint8 * stsd_entry_data, gchar ** codec_name)
14332 {
14333   GstCaps *caps;
14334
14335   switch (fourcc) {
14336     case FOURCC_m1v:
14337       _codec ("MPEG 1 video");
14338       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14339           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14340       break;
14341     default:
14342       caps = NULL;
14343       break;
14344   }
14345   return caps;
14346 }
14347
14348 static void
14349 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14350     const gchar * system_id)
14351 {
14352   gint i;
14353
14354   if (!qtdemux->protection_system_ids)
14355     qtdemux->protection_system_ids =
14356         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14357   /* Check whether we already have an entry for this system ID. */
14358   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14359     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14360     if (g_ascii_strcasecmp (system_id, id) == 0) {
14361       return;
14362     }
14363   }
14364   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14365   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14366           -1));
14367 }