qtdemux: fix seeking in fragmented file without mfra random access info
[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_description_index; /* index is 1-based */
418   guint32 def_sample_duration;
419   guint32 def_sample_size;
420   guint32 def_sample_flags;
421
422   gboolean disabled;
423
424   /* stereoscopic video streams */
425   GstVideoMultiviewMode multiview_mode;
426   GstVideoMultiviewFlags multiview_flags;
427
428   /* protected streams */
429   gboolean protected;
430   guint32 protection_scheme_type;
431   guint32 protection_scheme_version;
432   gpointer protection_scheme_info;      /* specific to the protection scheme */
433   GQueue protection_scheme_event_queue;
434 };
435
436 /* Contains properties and cryptographic info for a set of samples from a
437  * track protected using Common Encryption (cenc) */
438 struct _QtDemuxCencSampleSetInfo
439 {
440   GstStructure *default_properties;
441
442   /* @crypto_info holds one GstStructure per sample */
443   GPtrArray *crypto_info;
444 };
445
446 static const gchar *
447 qt_demux_state_string (enum QtDemuxState state)
448 {
449   switch (state) {
450     case QTDEMUX_STATE_INITIAL:
451       return "<INITIAL>";
452     case QTDEMUX_STATE_HEADER:
453       return "<HEADER>";
454     case QTDEMUX_STATE_MOVIE:
455       return "<MOVIE>";
456     case QTDEMUX_STATE_BUFFER_MDAT:
457       return "<BUFFER_MDAT>";
458     default:
459       return "<UNKNOWN>";
460   }
461 }
462
463 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
464 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
465     guint32 fourcc, GstByteReader * parser);
466 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
467 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
468     guint32 fourcc, GstByteReader * parser);
469
470 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
471
472 static GstStaticPadTemplate gst_qtdemux_sink_template =
473     GST_STATIC_PAD_TEMPLATE ("sink",
474     GST_PAD_SINK,
475     GST_PAD_ALWAYS,
476     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
477         "application/x-3gp")
478     );
479
480 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
481 GST_STATIC_PAD_TEMPLATE ("video_%u",
482     GST_PAD_SRC,
483     GST_PAD_SOMETIMES,
484     GST_STATIC_CAPS_ANY);
485
486 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
487 GST_STATIC_PAD_TEMPLATE ("audio_%u",
488     GST_PAD_SRC,
489     GST_PAD_SOMETIMES,
490     GST_STATIC_CAPS_ANY);
491
492 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
493 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
494     GST_PAD_SRC,
495     GST_PAD_SOMETIMES,
496     GST_STATIC_CAPS_ANY);
497
498 #define gst_qtdemux_parent_class parent_class
499 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
500
501 static void gst_qtdemux_dispose (GObject * object);
502
503 static guint32
504 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
505     GstClockTime media_time);
506 static guint32
507 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
508     QtDemuxStream * str, gint64 media_offset);
509
510 #if 0
511 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
512 static GstIndex *gst_qtdemux_get_index (GstElement * element);
513 #endif
514 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
515     GstStateChange transition);
516 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
517 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
518     GstObject * parent, GstPadMode mode, gboolean active);
519
520 static void gst_qtdemux_loop (GstPad * pad);
521 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
522     GstBuffer * inbuf);
523 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
524     GstEvent * event);
525 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
526 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
527     QtDemuxStream * stream);
528 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
529     QtDemuxStream * stream);
530 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
531     gboolean force);
532
533 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
534     const guint8 * buffer, guint length);
535 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
536     const guint8 * buffer, guint length);
537 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
538 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
539     GNode * udta);
540
541 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
542     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
543     GstTagList * list);
544 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
545     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
546     const guint8 * stsd_entry_data, gchar ** codec_name);
547 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
548     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
549     const guint8 * data, int len, gchar ** codec_name);
550 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
551     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
552     gchar ** codec_name);
553 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
554     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
555     const guint8 * stsd_entry_data, gchar ** codec_name);
556
557 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
558     QtDemuxStream * stream, guint32 n);
559 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
560 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
561     QtDemuxStream * stream);
562 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
563     QtDemuxStream * stream);
564 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
565 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
566 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
567     QtDemuxStream * stream);
568 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
569     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
570 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
571     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
572     GstClockTime * _start, GstClockTime * _stop);
573 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
574     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
575
576 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
577 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
578
579 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
580
581 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
582     QtDemuxStream * stream, guint sample_index);
583 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
584     const gchar * id);
585 static void qtdemux_gst_structure_free (GstStructure * gststructure);
586
587 static void
588 gst_qtdemux_class_init (GstQTDemuxClass * klass)
589 {
590   GObjectClass *gobject_class;
591   GstElementClass *gstelement_class;
592
593   gobject_class = (GObjectClass *) klass;
594   gstelement_class = (GstElementClass *) klass;
595
596   parent_class = g_type_class_peek_parent (klass);
597
598   gobject_class->dispose = gst_qtdemux_dispose;
599
600   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
601 #if 0
602   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
603   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
604 #endif
605
606   gst_tag_register_musicbrainz_tags ();
607
608   gst_element_class_add_static_pad_template (gstelement_class,
609       &gst_qtdemux_sink_template);
610   gst_element_class_add_static_pad_template (gstelement_class,
611       &gst_qtdemux_videosrc_template);
612   gst_element_class_add_static_pad_template (gstelement_class,
613       &gst_qtdemux_audiosrc_template);
614   gst_element_class_add_static_pad_template (gstelement_class,
615       &gst_qtdemux_subsrc_template);
616   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
617       "Codec/Demuxer",
618       "Demultiplex a QuickTime file into audio and video streams",
619       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
620
621   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
622
623 }
624
625 static void
626 gst_qtdemux_init (GstQTDemux * qtdemux)
627 {
628   qtdemux->sinkpad =
629       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
630   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
631   gst_pad_set_activatemode_function (qtdemux->sinkpad,
632       qtdemux_sink_activate_mode);
633   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
634   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
635   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
636
637   qtdemux->state = QTDEMUX_STATE_INITIAL;
638   qtdemux->pullbased = FALSE;
639   qtdemux->posted_redirect = FALSE;
640   qtdemux->neededbytes = 16;
641   qtdemux->todrop = 0;
642   qtdemux->adapter = gst_adapter_new ();
643   qtdemux->offset = 0;
644   qtdemux->first_mdat = -1;
645   qtdemux->got_moov = FALSE;
646   qtdemux->mdatoffset = -1;
647   qtdemux->mdatbuffer = NULL;
648   qtdemux->restoredata_buffer = NULL;
649   qtdemux->restoredata_offset = -1;
650   qtdemux->fragment_start = -1;
651   qtdemux->fragment_start_offset = -1;
652   qtdemux->media_caps = NULL;
653   qtdemux->exposed = FALSE;
654   qtdemux->mss_mode = FALSE;
655   qtdemux->pending_newsegment = NULL;
656   qtdemux->upstream_format_is_time = FALSE;
657   qtdemux->have_group_id = FALSE;
658   qtdemux->group_id = G_MAXUINT;
659   qtdemux->cenc_aux_info_offset = 0;
660   qtdemux->cenc_aux_info_sizes = NULL;
661   qtdemux->cenc_aux_sample_count = 0;
662   qtdemux->protection_system_ids = NULL;
663   g_queue_init (&qtdemux->protection_event_queue);
664   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
665   qtdemux->tag_list = gst_tag_list_new_empty ();
666   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
667   qtdemux->flowcombiner = gst_flow_combiner_new ();
668
669   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
670 }
671
672 static void
673 gst_qtdemux_dispose (GObject * object)
674 {
675   GstQTDemux *qtdemux = GST_QTDEMUX (object);
676
677   if (qtdemux->adapter) {
678     g_object_unref (G_OBJECT (qtdemux->adapter));
679     qtdemux->adapter = NULL;
680   }
681   gst_tag_list_unref (qtdemux->tag_list);
682   gst_flow_combiner_free (qtdemux->flowcombiner);
683   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
684       NULL);
685   g_queue_clear (&qtdemux->protection_event_queue);
686
687   g_free (qtdemux->cenc_aux_info_sizes);
688   qtdemux->cenc_aux_info_sizes = NULL;
689
690   G_OBJECT_CLASS (parent_class)->dispose (object);
691 }
692
693 static void
694 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
695 {
696   if (qtdemux->posted_redirect) {
697     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
698         (_("This file contains no playable streams.")),
699         ("no known streams found, a redirect message has been posted"));
700   } else {
701     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
702         (_("This file contains no playable streams.")),
703         ("no known streams found"));
704   }
705 }
706
707 static GstBuffer *
708 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
709 {
710   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
711       mem, size, 0, size, mem, free_func);
712 }
713
714 static GstFlowReturn
715 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
716     GstBuffer ** buf)
717 {
718   GstFlowReturn flow;
719   GstMapInfo map;
720   gsize bsize;
721
722   if (G_UNLIKELY (size == 0)) {
723     GstFlowReturn ret;
724     GstBuffer *tmp = NULL;
725
726     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
727     if (ret != GST_FLOW_OK)
728       return ret;
729
730     gst_buffer_map (tmp, &map, GST_MAP_READ);
731     size = QT_UINT32 (map.data);
732     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
733
734     gst_buffer_unmap (tmp, &map);
735     gst_buffer_unref (tmp);
736   }
737
738   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
739   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
740     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
741       /* we're pulling header but already got most interesting bits,
742        * so never mind the rest (e.g. tags) (that much) */
743       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
744           size);
745       return GST_FLOW_EOS;
746     } else {
747       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
748           (_("This file is invalid and cannot be played.")),
749           ("atom has bogus size %" G_GUINT64_FORMAT, size));
750       return GST_FLOW_ERROR;
751     }
752   }
753
754   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
755
756   if (G_UNLIKELY (flow != GST_FLOW_OK))
757     return flow;
758
759   bsize = gst_buffer_get_size (*buf);
760   /* Catch short reads - we don't want any partial atoms */
761   if (G_UNLIKELY (bsize < size)) {
762     GST_WARNING_OBJECT (qtdemux,
763         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
764     gst_buffer_unref (*buf);
765     *buf = NULL;
766     return GST_FLOW_EOS;
767   }
768
769   return flow;
770 }
771
772 #if 1
773 static gboolean
774 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
775     GstFormat src_format, gint64 src_value, GstFormat dest_format,
776     gint64 * dest_value)
777 {
778   gboolean res = TRUE;
779   QtDemuxStream *stream = gst_pad_get_element_private (pad);
780   gint32 index;
781
782   if (stream->subtype != FOURCC_vide) {
783     res = FALSE;
784     goto done;
785   }
786
787   switch (src_format) {
788     case GST_FORMAT_TIME:
789       switch (dest_format) {
790         case GST_FORMAT_BYTES:{
791           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
792           if (-1 == index) {
793             res = FALSE;
794             goto done;
795           }
796
797           *dest_value = stream->samples[index].offset;
798
799           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
800               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
801               GST_TIME_ARGS (src_value), *dest_value);
802           break;
803         }
804         default:
805           res = FALSE;
806           break;
807       }
808       break;
809     case GST_FORMAT_BYTES:
810       switch (dest_format) {
811         case GST_FORMAT_TIME:{
812           index =
813               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
814               stream, src_value);
815
816           if (-1 == index) {
817             res = FALSE;
818             goto done;
819           }
820
821           *dest_value =
822               QTSTREAMTIME_TO_GSTTIME (stream,
823               stream->samples[index].timestamp);
824           GST_DEBUG_OBJECT (qtdemux,
825               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
826               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
827           break;
828         }
829         default:
830           res = FALSE;
831           break;
832       }
833       break;
834     default:
835       res = FALSE;
836       break;
837   }
838
839 done:
840   return res;
841 }
842 #endif
843
844 static gboolean
845 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
846 {
847   gboolean res = FALSE;
848
849   *duration = GST_CLOCK_TIME_NONE;
850
851   if (qtdemux->duration != 0 &&
852       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
853     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
854     res = TRUE;
855   } else {
856     *duration = GST_CLOCK_TIME_NONE;
857   }
858
859   return res;
860 }
861
862 static gboolean
863 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
864     GstQuery * query)
865 {
866   gboolean res = FALSE;
867   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
868
869   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
870
871   switch (GST_QUERY_TYPE (query)) {
872     case GST_QUERY_POSITION:{
873       GstFormat fmt;
874
875       gst_query_parse_position (query, &fmt, NULL);
876       if (fmt == GST_FORMAT_TIME
877           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
878         gst_query_set_position (query, GST_FORMAT_TIME,
879             qtdemux->segment.position);
880         res = TRUE;
881       }
882     }
883       break;
884     case GST_QUERY_DURATION:{
885       GstFormat fmt;
886
887       gst_query_parse_duration (query, &fmt, NULL);
888       if (fmt == GST_FORMAT_TIME) {
889         /* First try to query upstream */
890         res = gst_pad_query_default (pad, parent, query);
891         if (!res) {
892           GstClockTime duration;
893           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
894             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
895             res = TRUE;
896           }
897         }
898       }
899       break;
900     }
901     case GST_QUERY_CONVERT:{
902       GstFormat src_fmt, dest_fmt;
903       gint64 src_value, dest_value = 0;
904
905       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
906
907       res = gst_qtdemux_src_convert (qtdemux, pad,
908           src_fmt, src_value, dest_fmt, &dest_value);
909       if (res)
910         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
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   gboolean ret;
1631
1632   if (event) {
1633     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1634
1635     gst_event_parse_seek (event, &rate, &format, &flags,
1636         &cur_type, &cur, &stop_type, &stop);
1637     seqnum = gst_event_get_seqnum (event);
1638
1639     /* we have to have a format as the segment format. Try to convert
1640      * if not. */
1641     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1642             stop_type, &stop))
1643       goto no_format;
1644
1645     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1646   } else {
1647     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1648     flags = 0;
1649   }
1650
1651   flush = flags & GST_SEEK_FLAG_FLUSH;
1652
1653   /* stop streaming, either by flushing or by pausing the task */
1654   if (flush) {
1655     flush_event = gst_event_new_flush_start ();
1656     if (seqnum)
1657       gst_event_set_seqnum (flush_event, seqnum);
1658     /* unlock upstream pull_range */
1659     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1660     /* make sure out loop function exits */
1661     gst_qtdemux_push_event (qtdemux, flush_event);
1662   } else {
1663     /* non flushing seek, pause the task */
1664     gst_pad_pause_task (qtdemux->sinkpad);
1665   }
1666
1667   /* wait for streaming to finish */
1668   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1669
1670   /* copy segment, we need this because we still need the old
1671    * segment when we close the current segment. */
1672   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1673
1674   if (event) {
1675     /* configure the segment with the seek variables */
1676     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1677     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1678             cur_type, cur, stop_type, stop, &update)) {
1679       ret = FALSE;
1680       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1681     } else {
1682       /* now do the seek */
1683       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1684     }
1685   } else {
1686     /* now do the seek */
1687     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1688   }
1689
1690   /* prepare for streaming again */
1691   if (flush) {
1692     flush_event = gst_event_new_flush_stop (TRUE);
1693     if (seqnum)
1694       gst_event_set_seqnum (flush_event, seqnum);
1695
1696     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1697     gst_qtdemux_push_event (qtdemux, flush_event);
1698   }
1699
1700   /* commit the new segment */
1701   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1702
1703   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1704     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1705         qtdemux->segment.format, qtdemux->segment.position);
1706     if (seqnum)
1707       gst_message_set_seqnum (msg, seqnum);
1708     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1709   }
1710
1711   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1712   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1713       qtdemux->sinkpad, NULL);
1714
1715   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1716
1717   return ret;
1718
1719   /* ERRORS */
1720 no_format:
1721   {
1722     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1723     return FALSE;
1724   }
1725 }
1726
1727 static gboolean
1728 qtdemux_ensure_index (GstQTDemux * qtdemux)
1729 {
1730   guint i;
1731
1732   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1733
1734   /* Build complete index */
1735   for (i = 0; i < qtdemux->n_streams; i++) {
1736     QtDemuxStream *stream = qtdemux->streams[i];
1737
1738     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1739       goto parse_error;
1740   }
1741   return TRUE;
1742
1743   /* ERRORS */
1744 parse_error:
1745   {
1746     GST_LOG_OBJECT (qtdemux,
1747         "Building complete index of stream %u for seeking failed!", i);
1748     return FALSE;
1749   }
1750 }
1751
1752 static gboolean
1753 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1754     GstEvent * event)
1755 {
1756   gboolean res = TRUE;
1757   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1758
1759   switch (GST_EVENT_TYPE (event)) {
1760     case GST_EVENT_SEEK:
1761     {
1762 #ifndef GST_DISABLE_GST_DEBUG
1763       GstClockTime ts = gst_util_get_timestamp ();
1764 #endif
1765       guint32 seqnum = gst_event_get_seqnum (event);
1766
1767       if (seqnum == qtdemux->segment_seqnum) {
1768         GST_LOG_OBJECT (pad,
1769             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1770         gst_event_unref (event);
1771         return TRUE;
1772       }
1773
1774       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1775         /* seek should be handled by upstream, we might need to re-download fragments */
1776         GST_DEBUG_OBJECT (qtdemux,
1777             "let upstream handle seek for fragmented playback");
1778         goto upstream;
1779       }
1780
1781       /* Build complete index for seeking;
1782        * if not a fragmented file at least */
1783       if (!qtdemux->fragmented)
1784         if (!qtdemux_ensure_index (qtdemux))
1785           goto index_failed;
1786 #ifndef GST_DISABLE_GST_DEBUG
1787       ts = gst_util_get_timestamp () - ts;
1788       GST_INFO_OBJECT (qtdemux,
1789           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1790 #endif
1791     }
1792       if (qtdemux->pullbased) {
1793         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1794       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1795         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1796         res = TRUE;
1797       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1798           && !qtdemux->fragmented) {
1799         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1800       } else {
1801         GST_DEBUG_OBJECT (qtdemux,
1802             "ignoring seek in push mode in current state");
1803         res = FALSE;
1804       }
1805       gst_event_unref (event);
1806       break;
1807     default:
1808     upstream:
1809       res = gst_pad_event_default (pad, parent, event);
1810       break;
1811   }
1812
1813 done:
1814   return res;
1815
1816   /* ERRORS */
1817 index_failed:
1818   {
1819     GST_ERROR_OBJECT (qtdemux, "Index failed");
1820     gst_event_unref (event);
1821     res = FALSE;
1822     goto done;
1823   }
1824 }
1825
1826 /* stream/index return sample that is min/max w.r.t. byte position,
1827  * time is min/max w.r.t. time of samples,
1828  * the latter need not be time of the former sample */
1829 static void
1830 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1831     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1832 {
1833   gint i, n, index;
1834   gint64 time, min_time;
1835   QtDemuxStream *stream;
1836
1837   min_time = -1;
1838   stream = NULL;
1839   index = -1;
1840
1841   for (n = 0; n < qtdemux->n_streams; ++n) {
1842     QtDemuxStream *str;
1843     gint inc;
1844     gboolean set_sample;
1845
1846     str = qtdemux->streams[n];
1847     set_sample = !set;
1848
1849     if (fw) {
1850       i = 0;
1851       inc = 1;
1852     } else {
1853       i = str->n_samples - 1;
1854       inc = -1;
1855     }
1856
1857     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1858       if (str->samples[i].size == 0)
1859         continue;
1860
1861       if (fw && (str->samples[i].offset < byte_pos))
1862         continue;
1863
1864       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1865         continue;
1866
1867       /* move stream to first available sample */
1868       if (set) {
1869         gst_qtdemux_move_stream (qtdemux, str, i);
1870         set_sample = TRUE;
1871       }
1872
1873       /* avoid index from sparse streams since they might be far away */
1874       if (!CUR_STREAM (str)->sparse) {
1875         /* determine min/max time */
1876         time = QTSAMPLE_PTS (str, &str->samples[i]);
1877         if (min_time == -1 || (!fw && time > min_time) ||
1878             (fw && time < min_time)) {
1879           min_time = time;
1880         }
1881
1882         /* determine stream with leading sample, to get its position */
1883         if (!stream ||
1884             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1885             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1886           stream = str;
1887           index = i;
1888         }
1889       }
1890       break;
1891     }
1892
1893     /* no sample for this stream, mark eos */
1894     if (!set_sample)
1895       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1896   }
1897
1898   if (_time)
1899     *_time = min_time;
1900   if (_stream)
1901     *_stream = stream;
1902   if (_index)
1903     *_index = index;
1904 }
1905
1906 static QtDemuxStream *
1907 _create_stream (void)
1908 {
1909   QtDemuxStream *stream;
1910
1911   stream = g_new0 (QtDemuxStream, 1);
1912   /* new streams always need a discont */
1913   stream->discont = TRUE;
1914   /* we enable clipping for raw audio/video streams */
1915   stream->need_clip = FALSE;
1916   stream->need_process = FALSE;
1917   stream->segment_index = -1;
1918   stream->time_position = 0;
1919   stream->sample_index = -1;
1920   stream->offset_in_sample = 0;
1921   stream->new_stream = TRUE;
1922   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1923   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1924   stream->protected = FALSE;
1925   stream->protection_scheme_type = 0;
1926   stream->protection_scheme_version = 0;
1927   stream->protection_scheme_info = NULL;
1928   stream->n_samples_moof = 0;
1929   stream->duration_moof = 0;
1930   stream->duration_last_moof = 0;
1931   stream->alignment = 1;
1932   stream->stream_tags = gst_tag_list_new_empty ();
1933   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1934   g_queue_init (&stream->protection_scheme_event_queue);
1935   return stream;
1936 }
1937
1938 static gboolean
1939 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1940 {
1941   GstStructure *structure;
1942   const gchar *variant;
1943   const GstCaps *mediacaps = NULL;
1944
1945   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1946
1947   structure = gst_caps_get_structure (caps, 0);
1948   variant = gst_structure_get_string (structure, "variant");
1949
1950   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1951     QtDemuxStream *stream;
1952     const GValue *value;
1953
1954     demux->fragmented = TRUE;
1955     demux->mss_mode = TRUE;
1956
1957     if (demux->n_streams > 1) {
1958       /* can't do this, we can only renegotiate for another mss format */
1959       return FALSE;
1960     }
1961
1962     value = gst_structure_get_value (structure, "media-caps");
1963     /* create stream */
1964     if (value) {
1965       const GValue *timescale_v;
1966
1967       /* TODO update when stream changes during playback */
1968
1969       if (demux->n_streams == 0) {
1970         stream = _create_stream ();
1971         demux->streams[demux->n_streams] = stream;
1972         demux->n_streams = 1;
1973         /* mss has no stsd/stsd entry, use id 0 as default */
1974         stream->stsd_entries_length = 1;
1975         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1976         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1977       } else {
1978         stream = demux->streams[0];
1979       }
1980
1981       timescale_v = gst_structure_get_value (structure, "timescale");
1982       if (timescale_v) {
1983         stream->timescale = g_value_get_uint64 (timescale_v);
1984       } else {
1985         /* default mss timescale */
1986         stream->timescale = 10000000;
1987       }
1988       demux->timescale = stream->timescale;
1989
1990       mediacaps = gst_value_get_caps (value);
1991       if (!CUR_STREAM (stream)->caps
1992           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1993         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1994             mediacaps);
1995         stream->new_caps = TRUE;
1996       }
1997       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1998       structure = gst_caps_get_structure (mediacaps, 0);
1999       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2000         stream->subtype = FOURCC_vide;
2001
2002         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2003         gst_structure_get_int (structure, "height",
2004             &CUR_STREAM (stream)->height);
2005         gst_structure_get_fraction (structure, "framerate",
2006             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2007       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2008         gint rate = 0;
2009         stream->subtype = FOURCC_soun;
2010         gst_structure_get_int (structure, "channels",
2011             &CUR_STREAM (stream)->n_channels);
2012         gst_structure_get_int (structure, "rate", &rate);
2013         CUR_STREAM (stream)->rate = rate;
2014       }
2015     }
2016     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2017   } else {
2018     demux->mss_mode = FALSE;
2019   }
2020
2021   return TRUE;
2022 }
2023
2024 static void
2025 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2026 {
2027   gint n;
2028
2029   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2030   gst_pad_stop_task (qtdemux->sinkpad);
2031
2032   if (hard || qtdemux->upstream_format_is_time) {
2033     qtdemux->state = QTDEMUX_STATE_INITIAL;
2034     qtdemux->neededbytes = 16;
2035     qtdemux->todrop = 0;
2036     qtdemux->pullbased = FALSE;
2037     qtdemux->posted_redirect = FALSE;
2038     qtdemux->first_mdat = -1;
2039     qtdemux->header_size = 0;
2040     qtdemux->mdatoffset = -1;
2041     qtdemux->restoredata_offset = -1;
2042     if (qtdemux->mdatbuffer)
2043       gst_buffer_unref (qtdemux->mdatbuffer);
2044     if (qtdemux->restoredata_buffer)
2045       gst_buffer_unref (qtdemux->restoredata_buffer);
2046     qtdemux->mdatbuffer = NULL;
2047     qtdemux->restoredata_buffer = NULL;
2048     qtdemux->mdatleft = 0;
2049     qtdemux->mdatsize = 0;
2050     if (qtdemux->comp_brands)
2051       gst_buffer_unref (qtdemux->comp_brands);
2052     qtdemux->comp_brands = NULL;
2053     qtdemux->last_moov_offset = -1;
2054     if (qtdemux->moov_node_compressed) {
2055       g_node_destroy (qtdemux->moov_node_compressed);
2056       if (qtdemux->moov_node)
2057         g_free (qtdemux->moov_node->data);
2058     }
2059     qtdemux->moov_node_compressed = NULL;
2060     if (qtdemux->moov_node)
2061       g_node_destroy (qtdemux->moov_node);
2062     qtdemux->moov_node = NULL;
2063     if (qtdemux->tag_list)
2064       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2065     qtdemux->tag_list = gst_tag_list_new_empty ();
2066     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2067 #if 0
2068     if (qtdemux->element_index)
2069       gst_object_unref (qtdemux->element_index);
2070     qtdemux->element_index = NULL;
2071 #endif
2072     qtdemux->major_brand = 0;
2073     if (qtdemux->pending_newsegment)
2074       gst_event_unref (qtdemux->pending_newsegment);
2075     qtdemux->pending_newsegment = NULL;
2076     qtdemux->upstream_format_is_time = FALSE;
2077     qtdemux->upstream_seekable = FALSE;
2078     qtdemux->upstream_size = 0;
2079
2080     qtdemux->fragment_start = -1;
2081     qtdemux->fragment_start_offset = -1;
2082     qtdemux->duration = 0;
2083     qtdemux->moof_offset = 0;
2084     qtdemux->chapters_track_id = 0;
2085     qtdemux->have_group_id = FALSE;
2086     qtdemux->group_id = G_MAXUINT;
2087
2088     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2089         NULL);
2090     g_queue_clear (&qtdemux->protection_event_queue);
2091   }
2092   qtdemux->offset = 0;
2093   gst_adapter_clear (qtdemux->adapter);
2094   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2095   qtdemux->segment_seqnum = 0;
2096
2097   if (hard) {
2098     for (n = 0; n < qtdemux->n_streams; n++) {
2099       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2100       qtdemux->streams[n] = NULL;
2101     }
2102     qtdemux->n_streams = 0;
2103     qtdemux->n_video_streams = 0;
2104     qtdemux->n_audio_streams = 0;
2105     qtdemux->n_sub_streams = 0;
2106     qtdemux->exposed = FALSE;
2107     qtdemux->fragmented = FALSE;
2108     qtdemux->mss_mode = FALSE;
2109     gst_caps_replace (&qtdemux->media_caps, NULL);
2110     qtdemux->timescale = 0;
2111     qtdemux->got_moov = FALSE;
2112     if (qtdemux->protection_system_ids) {
2113       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2114       qtdemux->protection_system_ids = NULL;
2115     }
2116   } else if (qtdemux->mss_mode) {
2117     gst_flow_combiner_reset (qtdemux->flowcombiner);
2118     for (n = 0; n < qtdemux->n_streams; n++)
2119       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2120   } else {
2121     gst_flow_combiner_reset (qtdemux->flowcombiner);
2122     for (n = 0; n < qtdemux->n_streams; n++) {
2123       qtdemux->streams[n]->sent_eos = FALSE;
2124       qtdemux->streams[n]->time_position = 0;
2125       qtdemux->streams[n]->accumulated_base = 0;
2126     }
2127     if (!qtdemux->pending_newsegment) {
2128       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2129       if (qtdemux->segment_seqnum)
2130         gst_event_set_seqnum (qtdemux->pending_newsegment,
2131             qtdemux->segment_seqnum);
2132     }
2133   }
2134 }
2135
2136
2137 /* Maps the @segment to the qt edts internal segments and pushes
2138  * the correspnding segment event.
2139  *
2140  * If it ends up being at a empty segment, a gap will be pushed and the next
2141  * edts segment will be activated in sequence.
2142  *
2143  * To be used in push-mode only */
2144 static void
2145 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2146 {
2147   gint n, i;
2148
2149   for (n = 0; n < qtdemux->n_streams; n++) {
2150     QtDemuxStream *stream = qtdemux->streams[n];
2151
2152     stream->time_position = segment->start;
2153
2154     /* in push mode we should be guaranteed that we will have empty segments
2155      * at the beginning and then one segment after, other scenarios are not
2156      * supported and are discarded when parsing the edts */
2157     for (i = 0; i < stream->n_segments; i++) {
2158       if (stream->segments[i].stop_time > segment->start) {
2159         gst_qtdemux_activate_segment (qtdemux, stream, i,
2160             stream->time_position);
2161         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2162           /* push the empty segment and move to the next one */
2163           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2164               stream->time_position);
2165           continue;
2166         }
2167
2168         g_assert (i == stream->n_segments - 1);
2169       }
2170     }
2171   }
2172 }
2173
2174 static gboolean
2175 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2176     GstEvent * event)
2177 {
2178   GstQTDemux *demux = GST_QTDEMUX (parent);
2179   gboolean res = TRUE;
2180
2181   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2182
2183   switch (GST_EVENT_TYPE (event)) {
2184     case GST_EVENT_SEGMENT:
2185     {
2186       gint64 offset = 0;
2187       QtDemuxStream *stream;
2188       gint idx;
2189       GstSegment segment;
2190
2191       /* some debug output */
2192       gst_event_copy_segment (event, &segment);
2193       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2194           &segment);
2195
2196       /* erase any previously set segment */
2197       gst_event_replace (&demux->pending_newsegment, NULL);
2198
2199       if (segment.format == GST_FORMAT_TIME) {
2200         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2201         gst_event_replace (&demux->pending_newsegment, event);
2202         demux->upstream_format_is_time = TRUE;
2203       } else {
2204         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2205             "not in time format");
2206
2207         /* chain will send initial newsegment after pads have been added */
2208         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2209           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2210           goto exit;
2211         }
2212       }
2213
2214       /* check if this matches a time seek we received previously
2215        * FIXME for backwards compatibility reasons we use the
2216        * seek_offset here to compare. In the future we might want to
2217        * change this to use the seqnum as it uniquely should identify
2218        * the segment that corresponds to the seek. */
2219       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2220           ", received segment offset %" G_GINT64_FORMAT,
2221           demux->seek_offset, segment.start);
2222       if (segment.format == GST_FORMAT_BYTES
2223           && demux->seek_offset == segment.start) {
2224         GST_OBJECT_LOCK (demux);
2225         offset = segment.start;
2226
2227         segment.format = GST_FORMAT_TIME;
2228         segment.start = demux->push_seek_start;
2229         segment.stop = demux->push_seek_stop;
2230         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2231             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2232             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2233         GST_OBJECT_UNLOCK (demux);
2234       }
2235
2236       /* we only expect a BYTE segment, e.g. following a seek */
2237       if (segment.format == GST_FORMAT_BYTES) {
2238         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2239           offset = segment.start;
2240
2241           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2242               NULL, (gint64 *) & segment.start);
2243           if ((gint64) segment.start < 0)
2244             segment.start = 0;
2245         }
2246         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2247           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2248               NULL, (gint64 *) & segment.stop);
2249           /* keyframe seeking should already arrange for start >= stop,
2250            * but make sure in other rare cases */
2251           segment.stop = MAX (segment.stop, segment.start);
2252         }
2253       } else if (segment.format == GST_FORMAT_TIME) {
2254         /* push all data on the adapter before starting this
2255          * new segment */
2256         gst_qtdemux_process_adapter (demux, TRUE);
2257       } else {
2258         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2259         goto exit;
2260       }
2261
2262       /* We shouldn't modify upstream driven TIME FORMAT segment */
2263       if (!demux->upstream_format_is_time) {
2264         /* accept upstream's notion of segment and distribute along */
2265         segment.format = GST_FORMAT_TIME;
2266         segment.position = segment.time = segment.start;
2267         segment.duration = demux->segment.duration;
2268         segment.base = gst_segment_to_running_time (&demux->segment,
2269             GST_FORMAT_TIME, demux->segment.position);
2270       }
2271
2272       gst_segment_copy_into (&segment, &demux->segment);
2273       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2274
2275       /* map segment to internal qt segments and push on each stream */
2276       if (demux->n_streams) {
2277         if (demux->fragmented) {
2278           GstEvent *segment_event = gst_event_new_segment (&segment);
2279
2280           gst_event_replace (&demux->pending_newsegment, NULL);
2281           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2282           gst_qtdemux_push_event (demux, segment_event);
2283         } else {
2284           gst_event_replace (&demux->pending_newsegment, NULL);
2285           gst_qtdemux_map_and_push_segments (demux, &segment);
2286         }
2287       }
2288
2289       /* clear leftover in current segment, if any */
2290       gst_adapter_clear (demux->adapter);
2291
2292       /* set up streaming thread */
2293       demux->offset = offset;
2294       if (demux->upstream_format_is_time) {
2295         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2296             "set values to restart reading from a new atom");
2297         demux->neededbytes = 16;
2298         demux->todrop = 0;
2299       } else {
2300         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2301             NULL);
2302         if (stream) {
2303           demux->todrop = stream->samples[idx].offset - offset;
2304           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2305         } else {
2306           /* set up for EOS */
2307           demux->neededbytes = -1;
2308           demux->todrop = 0;
2309         }
2310       }
2311     exit:
2312       gst_event_unref (event);
2313       res = TRUE;
2314       goto drop;
2315     }
2316     case GST_EVENT_FLUSH_START:
2317     {
2318       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2319         gst_event_unref (event);
2320         goto drop;
2321       }
2322       break;
2323     }
2324     case GST_EVENT_FLUSH_STOP:
2325     {
2326       guint64 dur;
2327
2328       dur = demux->segment.duration;
2329       gst_qtdemux_reset (demux, FALSE);
2330       demux->segment.duration = dur;
2331
2332       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2333         gst_event_unref (event);
2334         goto drop;
2335       }
2336       break;
2337     }
2338     case GST_EVENT_EOS:
2339       /* If we are in push mode, and get an EOS before we've seen any streams,
2340        * then error out - we have nowhere to send the EOS */
2341       if (!demux->pullbased) {
2342         gint i;
2343         gboolean has_valid_stream = FALSE;
2344         for (i = 0; i < demux->n_streams; i++) {
2345           if (demux->streams[i]->pad != NULL) {
2346             has_valid_stream = TRUE;
2347             break;
2348           }
2349         }
2350         if (!has_valid_stream)
2351           gst_qtdemux_post_no_playable_stream_error (demux);
2352         else {
2353           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2354               (guint) gst_adapter_available (demux->adapter));
2355           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2356             res = FALSE;
2357           }
2358         }
2359       }
2360       break;
2361     case GST_EVENT_CAPS:{
2362       GstCaps *caps = NULL;
2363
2364       gst_event_parse_caps (event, &caps);
2365       gst_qtdemux_setcaps (demux, caps);
2366       res = TRUE;
2367       gst_event_unref (event);
2368       goto drop;
2369     }
2370     case GST_EVENT_PROTECTION:
2371     {
2372       const gchar *system_id = NULL;
2373
2374       gst_event_parse_protection (event, &system_id, NULL, NULL);
2375       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2376           system_id);
2377       gst_qtdemux_append_protection_system_id (demux, system_id);
2378       /* save the event for later, for source pads that have not been created */
2379       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2380       /* send it to all pads that already exist */
2381       gst_qtdemux_push_event (demux, event);
2382       res = TRUE;
2383       goto drop;
2384     }
2385     default:
2386       break;
2387   }
2388
2389   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2390
2391 drop:
2392   return res;
2393 }
2394
2395 #if 0
2396 static void
2397 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2398 {
2399   GstQTDemux *demux = GST_QTDEMUX (element);
2400
2401   GST_OBJECT_LOCK (demux);
2402   if (demux->element_index)
2403     gst_object_unref (demux->element_index);
2404   if (index) {
2405     demux->element_index = gst_object_ref (index);
2406   } else {
2407     demux->element_index = NULL;
2408   }
2409   GST_OBJECT_UNLOCK (demux);
2410   /* object lock might be taken again */
2411   if (index)
2412     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2413   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2414       demux->element_index, demux->index_id);
2415 }
2416
2417 static GstIndex *
2418 gst_qtdemux_get_index (GstElement * element)
2419 {
2420   GstIndex *result = NULL;
2421   GstQTDemux *demux = GST_QTDEMUX (element);
2422
2423   GST_OBJECT_LOCK (demux);
2424   if (demux->element_index)
2425     result = gst_object_ref (demux->element_index);
2426   GST_OBJECT_UNLOCK (demux);
2427
2428   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2429
2430   return result;
2431 }
2432 #endif
2433
2434 static void
2435 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2436 {
2437   g_free ((gpointer) stream->stco.data);
2438   stream->stco.data = NULL;
2439   g_free ((gpointer) stream->stsz.data);
2440   stream->stsz.data = NULL;
2441   g_free ((gpointer) stream->stsc.data);
2442   stream->stsc.data = NULL;
2443   g_free ((gpointer) stream->stts.data);
2444   stream->stts.data = NULL;
2445   g_free ((gpointer) stream->stss.data);
2446   stream->stss.data = NULL;
2447   g_free ((gpointer) stream->stps.data);
2448   stream->stps.data = NULL;
2449   g_free ((gpointer) stream->ctts.data);
2450   stream->ctts.data = NULL;
2451 }
2452
2453 static void
2454 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2455     QtDemuxStream * stream)
2456 {
2457   g_free (stream->segments);
2458   stream->segments = NULL;
2459   stream->segment_index = -1;
2460   stream->accumulated_base = 0;
2461 }
2462
2463 static void
2464 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2465     QtDemuxStream * stream)
2466 {
2467   g_free (stream->samples);
2468   stream->samples = NULL;
2469   gst_qtdemux_stbl_free (stream);
2470
2471   /* fragments */
2472   g_free (stream->ra_entries);
2473   stream->ra_entries = NULL;
2474   stream->n_ra_entries = 0;
2475
2476   stream->sample_index = -1;
2477   stream->stbl_index = -1;
2478   stream->n_samples = 0;
2479   stream->time_position = 0;
2480
2481   stream->n_samples_moof = 0;
2482   stream->duration_moof = 0;
2483   stream->duration_last_moof = 0;
2484 }
2485
2486 static void
2487 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2488 {
2489   gint i;
2490   if (stream->allocator)
2491     gst_object_unref (stream->allocator);
2492   while (stream->buffers) {
2493     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2494     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2495   }
2496   for (i = 0; i < stream->stsd_entries_length; i++) {
2497     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2498     if (entry->rgb8_palette) {
2499       gst_memory_unref (entry->rgb8_palette);
2500       entry->rgb8_palette = NULL;
2501     }
2502     entry->sparse = FALSE;
2503   }
2504
2505   gst_tag_list_unref (stream->stream_tags);
2506   stream->stream_tags = gst_tag_list_new_empty ();
2507   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2508   g_free (stream->redirect_uri);
2509   stream->redirect_uri = NULL;
2510   stream->sent_eos = FALSE;
2511   stream->protected = FALSE;
2512   if (stream->protection_scheme_info) {
2513     if (stream->protection_scheme_type == FOURCC_cenc) {
2514       QtDemuxCencSampleSetInfo *info =
2515           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2516       if (info->default_properties)
2517         gst_structure_free (info->default_properties);
2518       if (info->crypto_info)
2519         g_ptr_array_free (info->crypto_info, TRUE);
2520     }
2521     g_free (stream->protection_scheme_info);
2522     stream->protection_scheme_info = NULL;
2523   }
2524   stream->protection_scheme_type = 0;
2525   stream->protection_scheme_version = 0;
2526   g_queue_foreach (&stream->protection_scheme_event_queue,
2527       (GFunc) gst_event_unref, NULL);
2528   g_queue_clear (&stream->protection_scheme_event_queue);
2529   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2530   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2531 }
2532
2533 static void
2534 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2535 {
2536   gint i;
2537   gst_qtdemux_stream_clear (qtdemux, stream);
2538   for (i = 0; i < stream->stsd_entries_length; i++) {
2539     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2540     if (entry->caps) {
2541       gst_caps_unref (entry->caps);
2542       entry->caps = NULL;
2543     }
2544   }
2545   gst_tag_list_unref (stream->stream_tags);
2546   if (stream->pad) {
2547     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2548     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2549   }
2550   g_free (stream->stsd_entries);
2551   g_free (stream);
2552 }
2553
2554 static void
2555 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2556 {
2557   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2558
2559   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2560   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2561   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2562   qtdemux->n_streams--;
2563 }
2564
2565 static GstStateChangeReturn
2566 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2567 {
2568   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2569   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2570
2571   switch (transition) {
2572     case GST_STATE_CHANGE_PAUSED_TO_READY:
2573       break;
2574     default:
2575       break;
2576   }
2577
2578   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2579
2580   switch (transition) {
2581     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2582       gst_qtdemux_reset (qtdemux, TRUE);
2583       break;
2584     }
2585     default:
2586       break;
2587   }
2588
2589   return result;
2590 }
2591
2592 static void
2593 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2594 {
2595   /* counts as header data */
2596   qtdemux->header_size += length;
2597
2598   /* only consider at least a sufficiently complete ftyp atom */
2599   if (length >= 20) {
2600     GstBuffer *buf;
2601
2602     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2603     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2604         GST_FOURCC_ARGS (qtdemux->major_brand));
2605     if (qtdemux->comp_brands)
2606       gst_buffer_unref (qtdemux->comp_brands);
2607     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2608     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2609   }
2610 }
2611
2612 static void
2613 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2614     GstTagList * xmptaglist)
2615 {
2616   /* Strip out bogus fields */
2617   if (xmptaglist) {
2618     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2619       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2620       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2621     } else {
2622       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2623     }
2624
2625     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2626
2627     /* prioritize native tags using _KEEP mode */
2628     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2629     gst_tag_list_unref (xmptaglist);
2630   }
2631 }
2632
2633 static void
2634 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2635     guint offset)
2636 {
2637   GstByteReader br;
2638   guint8 version;
2639   guint32 flags = 0;
2640   guint i;
2641   guint8 iv_size = 8;
2642   QtDemuxStream *stream;
2643   GstStructure *structure;
2644   QtDemuxCencSampleSetInfo *ss_info = NULL;
2645   const gchar *system_id;
2646   gboolean uses_sub_sample_encryption = FALSE;
2647
2648   if (qtdemux->n_streams == 0)
2649     return;
2650
2651   stream = qtdemux->streams[0];
2652
2653   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2654   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2655     GST_WARNING_OBJECT (qtdemux,
2656         "Attempting PIFF box parsing on an unencrypted stream.");
2657     return;
2658   }
2659
2660   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2661       G_TYPE_STRING, &system_id, NULL);
2662   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2663
2664   stream->protected = TRUE;
2665   stream->protection_scheme_type = FOURCC_cenc;
2666
2667   if (!stream->protection_scheme_info)
2668     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2669
2670   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2671
2672   if (ss_info->default_properties)
2673     gst_structure_free (ss_info->default_properties);
2674
2675   ss_info->default_properties =
2676       gst_structure_new ("application/x-cenc",
2677       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2678
2679   if (ss_info->crypto_info) {
2680     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2681     g_ptr_array_free (ss_info->crypto_info, TRUE);
2682     ss_info->crypto_info = NULL;
2683   }
2684
2685   /* skip UUID */
2686   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2687
2688   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2689     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2690     return;
2691   }
2692
2693   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2694     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2695     return;
2696   }
2697
2698   if ((flags & 0x000001)) {
2699     guint32 algorithm_id = 0;
2700     const guint8 *kid;
2701     GstBuffer *kid_buf;
2702     gboolean is_encrypted = TRUE;
2703
2704     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2705       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2706       return;
2707     }
2708
2709     algorithm_id >>= 8;
2710     if (algorithm_id == 0) {
2711       is_encrypted = FALSE;
2712     } else if (algorithm_id == 1) {
2713       /* FIXME: maybe store this in properties? */
2714       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2715     } else if (algorithm_id == 2) {
2716       /* FIXME: maybe store this in properties? */
2717       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2718     }
2719
2720     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2721       return;
2722
2723     if (!gst_byte_reader_get_data (&br, 16, &kid))
2724       return;
2725
2726     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2727     gst_buffer_fill (kid_buf, 0, kid, 16);
2728     if (ss_info->default_properties)
2729       gst_structure_free (ss_info->default_properties);
2730     ss_info->default_properties =
2731         gst_structure_new ("application/x-cenc",
2732         "iv_size", G_TYPE_UINT, iv_size,
2733         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2734         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2735     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2736         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2737     gst_buffer_unref (kid_buf);
2738   } else if ((flags & 0x000002)) {
2739     uses_sub_sample_encryption = TRUE;
2740   }
2741
2742   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2743     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2744     return;
2745   }
2746
2747   ss_info->crypto_info =
2748       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2749       (GDestroyNotify) qtdemux_gst_structure_free);
2750
2751   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2752     GstStructure *properties;
2753     guint8 *data;
2754     GstBuffer *buf;
2755
2756     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2757     if (properties == NULL) {
2758       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2759       return;
2760     }
2761
2762     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2763       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2764       gst_structure_free (properties);
2765       return;
2766     }
2767     buf = gst_buffer_new_wrapped (data, iv_size);
2768     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2769     gst_buffer_unref (buf);
2770
2771     if (uses_sub_sample_encryption) {
2772       guint16 n_subsamples;
2773
2774       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2775           || n_subsamples == 0) {
2776         GST_ERROR_OBJECT (qtdemux,
2777             "failed to get subsample count for sample %u", i);
2778         gst_structure_free (properties);
2779         return;
2780       }
2781       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2782       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2783         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2784             i);
2785         gst_structure_free (properties);
2786         return;
2787       }
2788       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2789       gst_structure_set (properties,
2790           "subsample_count", G_TYPE_UINT, n_subsamples,
2791           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2792       gst_buffer_unref (buf);
2793     } else {
2794       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2795     }
2796
2797     g_ptr_array_add (ss_info->crypto_info, properties);
2798   }
2799 }
2800
2801 static void
2802 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2803 {
2804   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2805     0x97, 0xA9, 0x42, 0xE8,
2806     0x9C, 0x71, 0x99, 0x94,
2807     0x91, 0xE3, 0xAF, 0xAC
2808   };
2809   static const guint8 playready_uuid[] = {
2810     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2811     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2812   };
2813
2814   static const guint8 piff_sample_encryption_uuid[] = {
2815     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2816     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2817   };
2818
2819   guint offset;
2820
2821   /* counts as header data */
2822   qtdemux->header_size += length;
2823
2824   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2825
2826   if (length <= offset + 16) {
2827     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2828     return;
2829   }
2830
2831   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2832     GstBuffer *buf;
2833     GstTagList *taglist;
2834
2835     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2836         length - offset - 16, NULL);
2837     taglist = gst_tag_list_from_xmp_buffer (buf);
2838     gst_buffer_unref (buf);
2839
2840     /* make sure we have a usable taglist */
2841     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2842
2843     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2844
2845   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2846     int len;
2847     const gunichar2 *s_utf16;
2848     char *contents;
2849
2850     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2851     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2852     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2853     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2854
2855     g_free (contents);
2856
2857     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2858         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2859         (NULL));
2860   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2861     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2862   } else {
2863     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2864         GST_READ_UINT32_LE (buffer + offset),
2865         GST_READ_UINT32_LE (buffer + offset + 4),
2866         GST_READ_UINT32_LE (buffer + offset + 8),
2867         GST_READ_UINT32_LE (buffer + offset + 12));
2868   }
2869 }
2870
2871 static void
2872 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2873 {
2874   GstSidxParser sidx_parser;
2875   GstIsoffParserResult res;
2876   guint consumed;
2877
2878   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2879
2880   res =
2881       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2882       &consumed);
2883   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2884   if (res == GST_ISOFF_QT_PARSER_DONE) {
2885     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2886   }
2887   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2888 }
2889
2890 /* caller verifies at least 8 bytes in buf */
2891 static void
2892 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2893     guint64 * plength, guint32 * pfourcc)
2894 {
2895   guint64 length;
2896   guint32 fourcc;
2897
2898   length = QT_UINT32 (data);
2899   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2900   fourcc = QT_FOURCC (data + 4);
2901   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2902
2903   if (length == 0) {
2904     length = G_MAXUINT64;
2905   } else if (length == 1 && size >= 16) {
2906     /* this means we have an extended size, which is the 64 bit value of
2907      * the next 8 bytes */
2908     length = QT_UINT64 (data + 8);
2909     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2910   }
2911
2912   if (plength)
2913     *plength = length;
2914   if (pfourcc)
2915     *pfourcc = fourcc;
2916 }
2917
2918 static gboolean
2919 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2920 {
2921   guint32 version = 0;
2922   GstClockTime duration = 0;
2923
2924   if (!gst_byte_reader_get_uint32_be (br, &version))
2925     goto failed;
2926
2927   version >>= 24;
2928   if (version == 1) {
2929     if (!gst_byte_reader_get_uint64_be (br, &duration))
2930       goto failed;
2931   } else {
2932     guint32 dur = 0;
2933
2934     if (!gst_byte_reader_get_uint32_be (br, &dur))
2935       goto failed;
2936     duration = dur;
2937   }
2938
2939   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2940   qtdemux->duration = duration;
2941
2942   return TRUE;
2943
2944 failed:
2945   {
2946     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2947     return FALSE;
2948   }
2949 }
2950
2951 static gboolean
2952 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2953     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2954 {
2955   if (!stream->parsed_trex && qtdemux->moov_node) {
2956     GNode *mvex, *trex;
2957     GstByteReader trex_data;
2958
2959     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2960     if (mvex) {
2961       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2962           &trex_data);
2963       while (trex) {
2964         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
2965
2966         /* skip version/flags */
2967         if (!gst_byte_reader_skip (&trex_data, 4))
2968           goto next;
2969         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2970           goto next;
2971         if (id != stream->track_id)
2972           goto next;
2973         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
2974           goto next;
2975         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2976           goto next;
2977         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2978           goto next;
2979         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2980           goto next;
2981
2982         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2983             "duration %d,  size %d, flags 0x%x", stream->track_id,
2984             dur, size, flags);
2985
2986         stream->parsed_trex = TRUE;
2987         stream->def_sample_description_index = sdi;
2988         stream->def_sample_duration = dur;
2989         stream->def_sample_size = size;
2990         stream->def_sample_flags = flags;
2991
2992       next:
2993         /* iterate all siblings */
2994         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2995             &trex_data);
2996       }
2997     }
2998   }
2999
3000   *ds_duration = stream->def_sample_duration;
3001   *ds_size = stream->def_sample_size;
3002   *ds_flags = stream->def_sample_flags;
3003
3004   /* even then, above values are better than random ... */
3005   if (G_UNLIKELY (!stream->parsed_trex)) {
3006     GST_WARNING_OBJECT (qtdemux,
3007         "failed to find fragment defaults for stream %d", stream->track_id);
3008     return FALSE;
3009   }
3010
3011   return TRUE;
3012 }
3013
3014 /* This method should be called whenever a more accurate duration might
3015  * have been found. It will update all relevant variables if/where needed
3016  */
3017 static void
3018 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3019 {
3020   guint i;
3021   guint64 movdur;
3022   GstClockTime prevdur;
3023
3024   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3025
3026   if (movdur > qtdemux->duration) {
3027     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3028     GST_DEBUG_OBJECT (qtdemux,
3029         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3030         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3031     qtdemux->duration = movdur;
3032     GST_DEBUG_OBJECT (qtdemux,
3033         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3034         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3035         GST_TIME_ARGS (qtdemux->segment.stop));
3036     if (qtdemux->segment.duration == prevdur) {
3037       /* If the current segment has duration/stop identical to previous duration
3038        * update them also (because they were set at that point in time with
3039        * the wrong duration */
3040       /* We convert the value *from* the timescale version to avoid rounding errors */
3041       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3042       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3043       qtdemux->segment.duration = fixeddur;
3044       qtdemux->segment.stop = fixeddur;
3045     }
3046   }
3047   for (i = 0; i < qtdemux->n_streams; i++) {
3048     QtDemuxStream *stream = qtdemux->streams[i];
3049     if (stream) {
3050       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3051       if (movdur > stream->duration) {
3052         GST_DEBUG_OBJECT (qtdemux,
3053             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3054             GST_TIME_ARGS (duration));
3055         stream->duration = movdur;
3056         if (stream->dummy_segment) {
3057           /* Update all dummy values to new duration */
3058           stream->segments[0].stop_time = duration;
3059           stream->segments[0].duration = duration;
3060           stream->segments[0].media_stop = duration;
3061
3062           /* let downstream know we possibly have a new stop time */
3063           if (stream->segment_index != -1) {
3064             GstClockTime pos;
3065
3066             if (qtdemux->segment.rate >= 0) {
3067               pos = stream->segment.start;
3068             } else {
3069               pos = stream->segment.stop;
3070             }
3071
3072             gst_qtdemux_stream_update_segment (qtdemux, stream,
3073                 stream->segment_index, pos, NULL, NULL);
3074           }
3075         }
3076       }
3077     }
3078   }
3079 }
3080
3081 static gboolean
3082 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3083     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3084     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3085     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3086     gboolean has_tfdt)
3087 {
3088   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3089   guint64 timestamp;
3090   gint32 data_offset = 0;
3091   guint32 flags = 0, first_flags = 0, samples_count = 0;
3092   gint i;
3093   guint8 *data;
3094   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3095   QtDemuxSample *sample;
3096   gboolean ismv = FALSE;
3097   gint64 initial_offset;
3098
3099   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3100       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3101       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3102       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3103
3104   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3105     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3106     return TRUE;
3107   }
3108
3109   /* presence of stss or not can't really tell us much,
3110    * and flags and so on tend to be marginally reliable in these files */
3111   if (stream->subtype == FOURCC_soun) {
3112     GST_DEBUG_OBJECT (qtdemux,
3113         "sound track in fragmented file; marking all keyframes");
3114     stream->all_keyframe = TRUE;
3115   }
3116
3117   if (!gst_byte_reader_skip (trun, 1) ||
3118       !gst_byte_reader_get_uint24_be (trun, &flags))
3119     goto fail;
3120
3121   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3122     goto fail;
3123
3124   if (flags & TR_DATA_OFFSET) {
3125     /* note this is really signed */
3126     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3127       goto fail;
3128     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3129     /* default base offset = first byte of moof */
3130     if (*base_offset == -1) {
3131       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3132       *base_offset = moof_offset;
3133     }
3134     *running_offset = *base_offset + data_offset;
3135   } else {
3136     /* if no offset at all, that would mean data starts at moof start,
3137      * which is a bit wrong and is ismv crappy way, so compensate
3138      * assuming data is in mdat following moof */
3139     if (*base_offset == -1) {
3140       *base_offset = moof_offset + moof_length + 8;
3141       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3142       ismv = TRUE;
3143     }
3144     if (*running_offset == -1)
3145       *running_offset = *base_offset;
3146   }
3147
3148   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3149       *running_offset);
3150   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3151       data_offset, flags, samples_count);
3152
3153   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3154     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3155       GST_DEBUG_OBJECT (qtdemux,
3156           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3157       flags ^= TR_FIRST_SAMPLE_FLAGS;
3158     } else {
3159       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3160         goto fail;
3161       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3162     }
3163   }
3164
3165   /* FIXME ? spec says other bits should also be checked to determine
3166    * entry size (and prefix size for that matter) */
3167   entry_size = 0;
3168   dur_offset = size_offset = 0;
3169   if (flags & TR_SAMPLE_DURATION) {
3170     GST_LOG_OBJECT (qtdemux, "entry duration present");
3171     dur_offset = entry_size;
3172     entry_size += 4;
3173   }
3174   if (flags & TR_SAMPLE_SIZE) {
3175     GST_LOG_OBJECT (qtdemux, "entry size present");
3176     size_offset = entry_size;
3177     entry_size += 4;
3178   }
3179   if (flags & TR_SAMPLE_FLAGS) {
3180     GST_LOG_OBJECT (qtdemux, "entry flags present");
3181     flags_offset = entry_size;
3182     entry_size += 4;
3183   }
3184   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3185     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3186     ct_offset = entry_size;
3187     entry_size += 4;
3188   }
3189
3190   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3191     goto fail;
3192   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3193
3194   if (stream->n_samples + samples_count >=
3195       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3196     goto index_too_big;
3197
3198   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3199       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3200       (stream->n_samples + samples_count) *
3201       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3202
3203   /* create a new array of samples if it's the first sample parsed */
3204   if (stream->n_samples == 0) {
3205     g_assert (stream->samples == NULL);
3206     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3207     /* or try to reallocate it with space enough to insert the new samples */
3208   } else
3209     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3210         stream->n_samples + samples_count);
3211   if (stream->samples == NULL)
3212     goto out_of_memory;
3213
3214   if (qtdemux->fragment_start != -1) {
3215     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3216     qtdemux->fragment_start = -1;
3217   } else {
3218     if (stream->n_samples == 0) {
3219       if (decode_ts > 0) {
3220         timestamp = decode_ts;
3221       } else if (stream->pending_seek != NULL) {
3222         /* if we don't have a timestamp from a tfdt box, we'll use the one
3223          * from the mfra seek table */
3224         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3225             GST_TIME_ARGS (stream->pending_seek->ts));
3226
3227         /* FIXME: this is not fully correct, the timestamp refers to the random
3228          * access sample refered to in the tfra entry, which may not necessarily
3229          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3230         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3231       } else {
3232         timestamp = 0;
3233       }
3234
3235       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3236       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3237           GST_TIME_ARGS (gst_ts));
3238     } else {
3239       /* subsequent fragments extend stream */
3240       timestamp =
3241           stream->samples[stream->n_samples - 1].timestamp +
3242           stream->samples[stream->n_samples - 1].duration;
3243
3244       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3245        * difference (1 sec.) between decode_ts and timestamp, prefer the
3246        * former */
3247       if (has_tfdt && !qtdemux->upstream_format_is_time
3248           && ABSDIFF (decode_ts, timestamp) >
3249           MAX (stream->duration_last_moof / 2,
3250               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3251         GST_INFO_OBJECT (qtdemux,
3252             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3253             ") are significantly different (more than %" GST_TIME_FORMAT
3254             "), using decode_ts",
3255             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3256             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3257             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3258                     MAX (stream->duration_last_moof / 2,
3259                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3260         timestamp = decode_ts;
3261       }
3262
3263       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3264       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3265           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3266     }
3267   }
3268
3269   initial_offset = *running_offset;
3270
3271   sample = stream->samples + stream->n_samples;
3272   for (i = 0; i < samples_count; i++) {
3273     guint32 dur, size, sflags, ct;
3274
3275     /* first read sample data */
3276     if (flags & TR_SAMPLE_DURATION) {
3277       dur = QT_UINT32 (data + dur_offset);
3278     } else {
3279       dur = d_sample_duration;
3280     }
3281     if (flags & TR_SAMPLE_SIZE) {
3282       size = QT_UINT32 (data + size_offset);
3283     } else {
3284       size = d_sample_size;
3285     }
3286     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3287       if (i == 0) {
3288         sflags = first_flags;
3289       } else {
3290         sflags = d_sample_flags;
3291       }
3292     } else if (flags & TR_SAMPLE_FLAGS) {
3293       sflags = QT_UINT32 (data + flags_offset);
3294     } else {
3295       sflags = d_sample_flags;
3296     }
3297     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3298       ct = QT_UINT32 (data + ct_offset);
3299     } else {
3300       ct = 0;
3301     }
3302     data += entry_size;
3303
3304     /* fill the sample information */
3305     sample->offset = *running_offset;
3306     sample->pts_offset = ct;
3307     sample->size = size;
3308     sample->timestamp = timestamp;
3309     sample->duration = dur;
3310     /* sample-is-difference-sample */
3311     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3312      * now idea how it relates to bitfield other than massive LE/BE confusion */
3313     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3314     *running_offset += size;
3315     timestamp += dur;
3316     stream->duration_moof += dur;
3317     sample++;
3318   }
3319
3320   /* Update total duration if needed */
3321   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3322
3323   /* Pre-emptively figure out size of mdat based on trun information.
3324    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3325    * size, else we will still be able to use this when dealing with gap'ed
3326    * input */
3327   qtdemux->mdatleft = *running_offset - initial_offset;
3328   qtdemux->mdatoffset = initial_offset;
3329   qtdemux->mdatsize = qtdemux->mdatleft;
3330
3331   stream->n_samples += samples_count;
3332   stream->n_samples_moof += samples_count;
3333
3334   if (stream->pending_seek != NULL)
3335     stream->pending_seek = NULL;
3336
3337   return TRUE;
3338
3339 fail:
3340   {
3341     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3342     return FALSE;
3343   }
3344 out_of_memory:
3345   {
3346     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3347         stream->n_samples);
3348     return FALSE;
3349   }
3350 index_too_big:
3351   {
3352     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3353         "be larger than %uMB (broken file?)", stream->n_samples,
3354         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3355     return FALSE;
3356   }
3357 }
3358
3359 /* find stream with @id */
3360 static inline QtDemuxStream *
3361 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3362 {
3363   QtDemuxStream *stream;
3364   gint i;
3365
3366   /* check */
3367   if (G_UNLIKELY (!id)) {
3368     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3369     return NULL;
3370   }
3371
3372   /* try to get it fast and simple */
3373   if (G_LIKELY (id <= qtdemux->n_streams)) {
3374     stream = qtdemux->streams[id - 1];
3375     if (G_LIKELY (stream->track_id == id))
3376       return stream;
3377   }
3378
3379   /* linear search otherwise */
3380   for (i = 0; i < qtdemux->n_streams; i++) {
3381     stream = qtdemux->streams[i];
3382     if (stream->track_id == id)
3383       return stream;
3384   }
3385   if (qtdemux->mss_mode) {
3386     /* mss should have only 1 stream anyway */
3387     return qtdemux->streams[0];
3388   }
3389
3390   return NULL;
3391 }
3392
3393 static gboolean
3394 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3395     guint32 * fragment_number)
3396 {
3397   if (!gst_byte_reader_skip (mfhd, 4))
3398     goto fail;
3399   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3400     goto fail;
3401   return TRUE;
3402 fail:
3403   {
3404     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3405     return FALSE;
3406   }
3407 }
3408
3409 static gboolean
3410 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3411     QtDemuxStream ** stream, guint32 * default_sample_duration,
3412     guint32 * default_sample_size, guint32 * default_sample_flags,
3413     gint64 * base_offset)
3414 {
3415   guint32 flags = 0;
3416   guint32 track_id = 0;
3417
3418   if (!gst_byte_reader_skip (tfhd, 1) ||
3419       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3420     goto invalid_track;
3421
3422   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3423     goto invalid_track;
3424
3425   *stream = qtdemux_find_stream (qtdemux, track_id);
3426   if (G_UNLIKELY (!*stream))
3427     goto unknown_stream;
3428
3429   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3430     *base_offset = qtdemux->moof_offset;
3431
3432   if (flags & TF_BASE_DATA_OFFSET)
3433     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3434       goto invalid_track;
3435
3436   /* obtain stream defaults */
3437   qtdemux_parse_trex (qtdemux, *stream,
3438       default_sample_duration, default_sample_size, default_sample_flags);
3439
3440   (*stream)->stsd_sample_description_id =
3441       (*stream)->def_sample_description_index - 1;
3442
3443   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3444     guint32 sample_description_index;
3445     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3446       goto invalid_track;
3447     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3448   }
3449
3450   if (qtdemux->mss_mode) {
3451     /* mss has no stsd entry */
3452     (*stream)->stsd_sample_description_id = 0;
3453   }
3454
3455   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3456     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3457       goto invalid_track;
3458
3459   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3460     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3461       goto invalid_track;
3462
3463   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3464     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3465       goto invalid_track;
3466
3467   return TRUE;
3468
3469 invalid_track:
3470   {
3471     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3472     return FALSE;
3473   }
3474 unknown_stream:
3475   {
3476     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3477     return TRUE;
3478   }
3479 }
3480
3481 static gboolean
3482 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3483     guint64 * decode_time)
3484 {
3485   guint32 version = 0;
3486
3487   if (!gst_byte_reader_get_uint32_be (br, &version))
3488     return FALSE;
3489
3490   version >>= 24;
3491   if (version == 1) {
3492     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3493       goto failed;
3494   } else {
3495     guint32 dec_time = 0;
3496     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3497       goto failed;
3498     *decode_time = dec_time;
3499   }
3500
3501   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3502       *decode_time);
3503
3504   return TRUE;
3505
3506 failed:
3507   {
3508     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3509     return FALSE;
3510   }
3511 }
3512
3513 /* Returns a pointer to a GstStructure containing the properties of
3514  * the stream sample identified by @sample_index. The caller must unref
3515  * the returned object after use. Returns NULL if unsuccessful. */
3516 static GstStructure *
3517 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3518     QtDemuxStream * stream, guint sample_index)
3519 {
3520   QtDemuxCencSampleSetInfo *info = NULL;
3521
3522   g_return_val_if_fail (stream != NULL, NULL);
3523   g_return_val_if_fail (stream->protected, NULL);
3524   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3525
3526   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3527
3528   /* Currently, cenc properties for groups of samples are not supported, so
3529    * simply return a copy of the default sample properties */
3530   return gst_structure_copy (info->default_properties);
3531 }
3532
3533 /* Parses the sizes of sample auxiliary information contained within a stream,
3534  * as given in a saiz box. Returns array of sample_count guint8 size values,
3535  * or NULL on failure */
3536 static guint8 *
3537 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3538     GstByteReader * br, guint32 * sample_count)
3539 {
3540   guint32 flags = 0;
3541   guint8 *info_sizes;
3542   guint8 default_info_size;
3543
3544   g_return_val_if_fail (qtdemux != NULL, NULL);
3545   g_return_val_if_fail (stream != NULL, NULL);
3546   g_return_val_if_fail (br != NULL, NULL);
3547   g_return_val_if_fail (sample_count != NULL, NULL);
3548
3549   if (!gst_byte_reader_get_uint32_be (br, &flags))
3550     return NULL;
3551
3552   if (flags & 0x1) {
3553     /* aux_info_type and aux_info_type_parameter are ignored */
3554     if (!gst_byte_reader_skip (br, 8))
3555       return NULL;
3556   }
3557
3558   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3559     return NULL;
3560   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3561
3562   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3563     return NULL;
3564   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3565
3566
3567   if (default_info_size == 0) {
3568     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3569       return NULL;
3570     }
3571   } else {
3572     info_sizes = g_new (guint8, *sample_count);
3573     memset (info_sizes, default_info_size, *sample_count);
3574   }
3575
3576   return info_sizes;
3577 }
3578
3579 /* Parses the offset of sample auxiliary information contained within a stream,
3580  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3581 static gboolean
3582 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3583     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3584     guint64 * offset)
3585 {
3586   guint8 version = 0;
3587   guint32 flags = 0;
3588   guint32 aux_info_type = 0;
3589   guint32 aux_info_type_parameter = 0;
3590   guint32 entry_count;
3591   guint32 off_32;
3592   guint64 off_64;
3593   const guint8 *aux_info_type_data = NULL;
3594
3595   g_return_val_if_fail (qtdemux != NULL, FALSE);
3596   g_return_val_if_fail (stream != NULL, FALSE);
3597   g_return_val_if_fail (br != NULL, FALSE);
3598   g_return_val_if_fail (offset != NULL, FALSE);
3599
3600   if (!gst_byte_reader_get_uint8 (br, &version))
3601     return FALSE;
3602
3603   if (!gst_byte_reader_get_uint24_be (br, &flags))
3604     return FALSE;
3605
3606   if (flags & 0x1) {
3607
3608     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3609       return FALSE;
3610     aux_info_type = QT_FOURCC (aux_info_type_data);
3611
3612     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3613       return FALSE;
3614   } else if (stream->protected) {
3615     aux_info_type = stream->protection_scheme_type;
3616   } else {
3617     aux_info_type = CUR_STREAM (stream)->fourcc;
3618   }
3619
3620   if (info_type)
3621     *info_type = aux_info_type;
3622   if (info_type_parameter)
3623     *info_type_parameter = aux_info_type_parameter;
3624
3625   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3626       "aux_info_type_parameter:  %#06x",
3627       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3628
3629   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3630     return FALSE;
3631
3632   if (entry_count != 1) {
3633     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3634     return FALSE;
3635   }
3636
3637   if (version == 0) {
3638     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3639       return FALSE;
3640     *offset = (guint64) off_32;
3641   } else {
3642     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3643       return FALSE;
3644     *offset = off_64;
3645   }
3646
3647   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3648   return TRUE;
3649 }
3650
3651 static void
3652 qtdemux_gst_structure_free (GstStructure * gststructure)
3653 {
3654   if (gststructure) {
3655     gst_structure_free (gststructure);
3656   }
3657 }
3658
3659 /* Parses auxiliary information relating to samples protected using Common
3660  * Encryption (cenc); the format of this information is defined in
3661  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3662 static gboolean
3663 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3664     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3665 {
3666   QtDemuxCencSampleSetInfo *ss_info = NULL;
3667   guint8 size;
3668   gint i;
3669   GPtrArray *old_crypto_info = NULL;
3670   guint old_entries = 0;
3671
3672   g_return_val_if_fail (qtdemux != NULL, FALSE);
3673   g_return_val_if_fail (stream != NULL, FALSE);
3674   g_return_val_if_fail (br != NULL, FALSE);
3675   g_return_val_if_fail (stream->protected, FALSE);
3676   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3677
3678   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3679
3680   if (ss_info->crypto_info) {
3681     old_crypto_info = ss_info->crypto_info;
3682     /* Count number of non-null entries remaining at the tail end */
3683     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3684       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3685         break;
3686       old_entries++;
3687     }
3688   }
3689
3690   ss_info->crypto_info =
3691       g_ptr_array_new_full (sample_count + old_entries,
3692       (GDestroyNotify) qtdemux_gst_structure_free);
3693
3694   /* We preserve old entries because we parse the next moof in advance
3695    * of consuming all samples from the previous moof, and otherwise
3696    * we'd discard the corresponding crypto info for the samples
3697    * from the previous fragment. */
3698   if (old_entries) {
3699     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3700         old_entries);
3701     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3702       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3703               i));
3704       g_ptr_array_index (old_crypto_info, i) = NULL;
3705     }
3706   }
3707
3708   if (old_crypto_info) {
3709     /* Everything now belongs to the new array */
3710     g_ptr_array_free (old_crypto_info, TRUE);
3711   }
3712
3713   for (i = 0; i < sample_count; ++i) {
3714     GstStructure *properties;
3715     guint16 n_subsamples = 0;
3716     guint8 *data;
3717     guint iv_size;
3718     GstBuffer *buf;
3719
3720     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3721     if (properties == NULL) {
3722       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3723       return FALSE;
3724     }
3725     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3726       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3727       gst_structure_free (properties);
3728       return FALSE;
3729     }
3730     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3731       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3732       gst_structure_free (properties);
3733       return FALSE;
3734     }
3735     buf = gst_buffer_new_wrapped (data, iv_size);
3736     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3737     gst_buffer_unref (buf);
3738     size = info_sizes[i];
3739     if (size > iv_size) {
3740       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3741           || !(n_subsamples > 0)) {
3742         gst_structure_free (properties);
3743         GST_ERROR_OBJECT (qtdemux,
3744             "failed to get subsample count for sample %u", i);
3745         return FALSE;
3746       }
3747       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3748       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3749         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3750             i);
3751         gst_structure_free (properties);
3752         return FALSE;
3753       }
3754       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3755       if (!buf) {
3756         gst_structure_free (properties);
3757         return FALSE;
3758       }
3759       gst_structure_set (properties,
3760           "subsample_count", G_TYPE_UINT, n_subsamples,
3761           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3762       gst_buffer_unref (buf);
3763     } else {
3764       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3765     }
3766     g_ptr_array_add (ss_info->crypto_info, properties);
3767   }
3768   return TRUE;
3769 }
3770
3771 /* Converts a UUID in raw byte form to a string representation, as defined in
3772  * RFC 4122. The caller takes ownership of the returned string and is
3773  * responsible for freeing it after use. */
3774 static gchar *
3775 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3776 {
3777   const guint8 *uuid = (const guint8 *) uuid_bytes;
3778
3779   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3780       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3781       uuid[0], uuid[1], uuid[2], uuid[3],
3782       uuid[4], uuid[5], uuid[6], uuid[7],
3783       uuid[8], uuid[9], uuid[10], uuid[11],
3784       uuid[12], uuid[13], uuid[14], uuid[15]);
3785 }
3786
3787 /* Parses a Protection System Specific Header box (pssh), as defined in the
3788  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3789  * information needed by a specific content protection system in order to
3790  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3791  * otherwise. */
3792 static gboolean
3793 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3794 {
3795   gchar *sysid_string;
3796   guint32 pssh_size = QT_UINT32 (node->data);
3797   GstBuffer *pssh = NULL;
3798   GstEvent *event = NULL;
3799   guint32 parent_box_type;
3800   gint i;
3801
3802   if (G_UNLIKELY (pssh_size < 32U)) {
3803     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3804     return FALSE;
3805   }
3806
3807   sysid_string =
3808       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3809
3810   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3811
3812   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3813   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3814       gst_buffer_get_size (pssh));
3815
3816   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3817
3818   /* Push an event containing the pssh box onto the queues of all streams. */
3819   event = gst_event_new_protection (sysid_string, pssh,
3820       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3821   for (i = 0; i < qtdemux->n_streams; ++i) {
3822     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3823         gst_event_ref (event));
3824   }
3825   g_free (sysid_string);
3826   gst_event_unref (event);
3827   gst_buffer_unref (pssh);
3828   return TRUE;
3829 }
3830
3831 static gboolean
3832 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3833     guint64 moof_offset, QtDemuxStream * stream)
3834 {
3835   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3836   GNode *uuid_node;
3837   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3838   GNode *saiz_node, *saio_node, *pssh_node;
3839   GstByteReader saiz_data, saio_data;
3840   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3841   gint64 base_offset, running_offset;
3842   guint32 frag_num;
3843
3844   /* NOTE @stream ignored */
3845
3846   moof_node = g_node_new ((guint8 *) buffer);
3847   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3848   qtdemux_node_dump (qtdemux, moof_node);
3849
3850   /* Get fragment number from mfhd and check it's valid */
3851   mfhd_node =
3852       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3853   if (mfhd_node == NULL)
3854     goto missing_mfhd;
3855   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3856     goto fail;
3857   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3858
3859   /* unknown base_offset to start with */
3860   base_offset = running_offset = -1;
3861   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3862   while (traf_node) {
3863     guint64 decode_time = 0;
3864
3865     /* Fragment Header node */
3866     tfhd_node =
3867         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3868         &tfhd_data);
3869     if (!tfhd_node)
3870       goto missing_tfhd;
3871     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3872             &ds_size, &ds_flags, &base_offset))
3873       goto missing_tfhd;
3874
3875     /* The following code assumes at most a single set of sample auxiliary
3876      * data in the fragment (consisting of a saiz box and a corresponding saio
3877      * box); in theory, however, there could be multiple sets of sample
3878      * auxiliary data in a fragment. */
3879     saiz_node =
3880         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3881         &saiz_data);
3882     if (saiz_node) {
3883       guint32 info_type = 0;
3884       guint64 offset = 0;
3885       guint32 info_type_parameter = 0;
3886
3887       g_free (qtdemux->cenc_aux_info_sizes);
3888
3889       qtdemux->cenc_aux_info_sizes =
3890           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3891           &qtdemux->cenc_aux_sample_count);
3892       if (qtdemux->cenc_aux_info_sizes == NULL) {
3893         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3894         goto fail;
3895       }
3896       saio_node =
3897           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3898           &saio_data);
3899       if (!saio_node) {
3900         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3901         g_free (qtdemux->cenc_aux_info_sizes);
3902         qtdemux->cenc_aux_info_sizes = NULL;
3903         goto fail;
3904       }
3905
3906       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3907                   &info_type, &info_type_parameter, &offset))) {
3908         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3909         g_free (qtdemux->cenc_aux_info_sizes);
3910         qtdemux->cenc_aux_info_sizes = NULL;
3911         goto fail;
3912       }
3913       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3914         offset += (guint64) (base_offset - qtdemux->moof_offset);
3915       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3916         GstByteReader br;
3917         if (offset > length) {
3918           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3919           qtdemux->cenc_aux_info_offset = offset;
3920         } else {
3921           gst_byte_reader_init (&br, buffer + offset, length - offset);
3922           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3923                   qtdemux->cenc_aux_info_sizes,
3924                   qtdemux->cenc_aux_sample_count)) {
3925             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3926             g_free (qtdemux->cenc_aux_info_sizes);
3927             qtdemux->cenc_aux_info_sizes = NULL;
3928             goto fail;
3929           }
3930         }
3931       }
3932     }
3933
3934     tfdt_node =
3935         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3936         &tfdt_data);
3937     if (tfdt_node) {
3938       /* We'll use decode_time to interpolate timestamps
3939        * in case the input timestamps are missing */
3940       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3941
3942       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3943           " (%" GST_TIME_FORMAT ")", decode_time,
3944           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
3945                   decode_time) : GST_CLOCK_TIME_NONE));
3946
3947       /* Discard the fragment buffer timestamp info to avoid using it.
3948        * Rely on tfdt instead as it is more accurate than the timestamp
3949        * that is fetched from a manifest/playlist and is usually
3950        * less accurate. */
3951       qtdemux->fragment_start = -1;
3952     }
3953
3954     if (G_UNLIKELY (!stream)) {
3955       /* we lost track of offset, we'll need to regain it,
3956        * but can delay complaining until later or avoid doing so altogether */
3957       base_offset = -2;
3958       goto next;
3959     }
3960     if (G_UNLIKELY (base_offset < -1))
3961       goto lost_offset;
3962
3963     if (qtdemux->upstream_format_is_time)
3964       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3965
3966     /* initialise moof sample data */
3967     stream->n_samples_moof = 0;
3968     stream->duration_last_moof = stream->duration_moof;
3969     stream->duration_moof = 0;
3970
3971     /* Track Run node */
3972     trun_node =
3973         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3974         &trun_data);
3975     while (trun_node) {
3976       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3977           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3978           &running_offset, decode_time, (tfdt_node != NULL));
3979       /* iterate all siblings */
3980       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3981           &trun_data);
3982     }
3983
3984     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3985     if (uuid_node) {
3986       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3987       guint32 box_length = QT_UINT32 (uuid_buffer);
3988
3989       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3990     }
3991
3992     /* if no new base_offset provided for next traf,
3993      * base is end of current traf */
3994     base_offset = running_offset;
3995     running_offset = -1;
3996
3997     if (stream->n_samples_moof && stream->duration_moof)
3998       stream->new_caps = TRUE;
3999
4000   next:
4001     /* iterate all siblings */
4002     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4003   }
4004
4005   /* parse any protection system info */
4006   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4007   while (pssh_node) {
4008     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4009     qtdemux_parse_pssh (qtdemux, pssh_node);
4010     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4011   }
4012
4013   g_node_destroy (moof_node);
4014   return TRUE;
4015
4016 missing_tfhd:
4017   {
4018     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4019     goto fail;
4020   }
4021 missing_mfhd:
4022   {
4023     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4024     goto fail;
4025   }
4026 lost_offset:
4027   {
4028     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4029     goto fail;
4030   }
4031 fail:
4032   {
4033     g_node_destroy (moof_node);
4034     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4035         (_("This file is corrupt and cannot be played.")), (NULL));
4036     return FALSE;
4037   }
4038 }
4039
4040 #if 0
4041 /* might be used if some day we actually use mfra & co
4042  * for random access to fragments,
4043  * but that will require quite some modifications and much less relying
4044  * on a sample array */
4045 #endif
4046
4047 static gboolean
4048 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4049 {
4050   QtDemuxStream *stream;
4051   guint32 ver_flags, track_id, len, num_entries, i;
4052   guint value_size, traf_size, trun_size, sample_size;
4053   guint64 time = 0, moof_offset = 0;
4054 #if 0
4055   GstBuffer *buf = NULL;
4056   GstFlowReturn ret;
4057 #endif
4058   GstByteReader tfra;
4059
4060   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4061
4062   if (!gst_byte_reader_skip (&tfra, 8))
4063     return FALSE;
4064
4065   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4066     return FALSE;
4067
4068   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4069       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4070       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4071     return FALSE;
4072
4073   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4074
4075   stream = qtdemux_find_stream (qtdemux, track_id);
4076   if (stream == NULL)
4077     goto unknown_trackid;
4078
4079   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4080   sample_size = (len & 3) + 1;
4081   trun_size = ((len & 12) >> 2) + 1;
4082   traf_size = ((len & 48) >> 4) + 1;
4083
4084   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4085       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4086
4087   if (num_entries == 0)
4088     goto no_samples;
4089
4090   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4091           value_size + value_size + traf_size + trun_size + sample_size))
4092     goto corrupt_file;
4093
4094   g_free (stream->ra_entries);
4095   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4096   stream->n_ra_entries = num_entries;
4097
4098   for (i = 0; i < num_entries; i++) {
4099     qt_atom_parser_get_offset (&tfra, value_size, &time);
4100     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4101     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4102     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4103     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4104
4105     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4106
4107     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4108         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4109
4110     stream->ra_entries[i].ts = time;
4111     stream->ra_entries[i].moof_offset = moof_offset;
4112
4113     /* don't want to go through the entire file and read all moofs at startup */
4114 #if 0
4115     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4116     if (ret != GST_FLOW_OK)
4117       goto corrupt_file;
4118     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4119         moof_offset, stream);
4120     gst_buffer_unref (buf);
4121 #endif
4122   }
4123
4124   check_update_duration (qtdemux, time);
4125
4126   return TRUE;
4127
4128 /* ERRORS */
4129 unknown_trackid:
4130   {
4131     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4132     return FALSE;
4133   }
4134 corrupt_file:
4135   {
4136     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4137     return FALSE;
4138   }
4139 no_samples:
4140   {
4141     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4142     return FALSE;
4143   }
4144 }
4145
4146 static gboolean
4147 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4148 {
4149   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4150   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4151   GstBuffer *mfro = NULL, *mfra = NULL;
4152   GstFlowReturn flow;
4153   gboolean ret = FALSE;
4154   GNode *mfra_node, *tfra_node;
4155   guint64 mfra_offset = 0;
4156   guint32 fourcc, mfra_size;
4157   gint64 len;
4158
4159   /* query upstream size in bytes */
4160   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4161     goto size_query_failed;
4162
4163   /* mfro box should be at the very end of the file */
4164   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4165   if (flow != GST_FLOW_OK)
4166     goto exit;
4167
4168   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4169
4170   fourcc = QT_FOURCC (mfro_map.data + 4);
4171   if (fourcc != FOURCC_mfro)
4172     goto exit;
4173
4174   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4175   if (mfro_map.size < 16)
4176     goto invalid_mfro_size;
4177
4178   mfra_size = QT_UINT32 (mfro_map.data + 12);
4179   if (mfra_size >= len)
4180     goto invalid_mfra_size;
4181
4182   mfra_offset = len - mfra_size;
4183
4184   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4185       mfra_offset, mfra_size);
4186
4187   /* now get and parse mfra box */
4188   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4189   if (flow != GST_FLOW_OK)
4190     goto broken_file;
4191
4192   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4193
4194   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4195   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4196
4197   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4198
4199   while (tfra_node) {
4200     qtdemux_parse_tfra (qtdemux, tfra_node);
4201     /* iterate all siblings */
4202     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4203   }
4204   g_node_destroy (mfra_node);
4205
4206   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4207   ret = TRUE;
4208
4209 exit:
4210
4211   if (mfro) {
4212     if (mfro_map.memory != NULL)
4213       gst_buffer_unmap (mfro, &mfro_map);
4214     gst_buffer_unref (mfro);
4215   }
4216   if (mfra) {
4217     if (mfra_map.memory != NULL)
4218       gst_buffer_unmap (mfra, &mfra_map);
4219     gst_buffer_unref (mfra);
4220   }
4221   return ret;
4222
4223 /* ERRORS */
4224 size_query_failed:
4225   {
4226     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4227     goto exit;
4228   }
4229 invalid_mfro_size:
4230   {
4231     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4232     goto exit;
4233   }
4234 invalid_mfra_size:
4235   {
4236     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4237     goto exit;
4238   }
4239 broken_file:
4240   {
4241     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4242     goto exit;
4243   }
4244 }
4245
4246 static guint64
4247 add_offset (guint64 offset, guint64 advance)
4248 {
4249   /* Avoid 64-bit overflow by clamping */
4250   if (offset > G_MAXUINT64 - advance)
4251     return G_MAXUINT64;
4252   return offset + advance;
4253 }
4254
4255 static GstFlowReturn
4256 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4257 {
4258   guint64 length = 0;
4259   guint32 fourcc = 0;
4260   GstBuffer *buf = NULL;
4261   GstFlowReturn ret = GST_FLOW_OK;
4262   guint64 cur_offset = qtdemux->offset;
4263   GstMapInfo map;
4264
4265   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4266   if (G_UNLIKELY (ret != GST_FLOW_OK))
4267     goto beach;
4268   gst_buffer_map (buf, &map, GST_MAP_READ);
4269   if (G_LIKELY (map.size >= 8))
4270     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4271   gst_buffer_unmap (buf, &map);
4272   gst_buffer_unref (buf);
4273
4274   /* maybe we already got most we needed, so only consider this eof */
4275   if (G_UNLIKELY (length == 0)) {
4276     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4277         (_("Invalid atom size.")),
4278         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4279             GST_FOURCC_ARGS (fourcc)));
4280     ret = GST_FLOW_EOS;
4281     goto beach;
4282   }
4283
4284   switch (fourcc) {
4285     case FOURCC_moof:
4286       /* record for later parsing when needed */
4287       if (!qtdemux->moof_offset) {
4288         qtdemux->moof_offset = qtdemux->offset;
4289       }
4290       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4291         /* FIXME */
4292       } else {
4293         qtdemux->offset += length;      /* skip moof and keep going */
4294       }
4295       if (qtdemux->got_moov) {
4296         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4297         ret = GST_FLOW_EOS;
4298         goto beach;
4299       }
4300       break;
4301     case FOURCC_mdat:
4302     case FOURCC_free:
4303     case FOURCC_skip:
4304     case FOURCC_wide:
4305     case FOURCC_PICT:
4306     case FOURCC_pnot:
4307     {
4308       GST_LOG_OBJECT (qtdemux,
4309           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4310           GST_FOURCC_ARGS (fourcc), cur_offset);
4311       qtdemux->offset = add_offset (qtdemux->offset, length);
4312       break;
4313     }
4314     case FOURCC_moov:
4315     {
4316       GstBuffer *moov = NULL;
4317
4318       if (qtdemux->got_moov) {
4319         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4320         qtdemux->offset = add_offset (qtdemux->offset, length);
4321         goto beach;
4322       }
4323
4324       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4325       if (ret != GST_FLOW_OK)
4326         goto beach;
4327       gst_buffer_map (moov, &map, GST_MAP_READ);
4328
4329       if (length != map.size) {
4330         /* Some files have a 'moov' atom at the end of the file which contains
4331          * a terminal 'free' atom where the body of the atom is missing.
4332          * Check for, and permit, this special case.
4333          */
4334         if (map.size >= 8) {
4335           guint8 *final_data = map.data + (map.size - 8);
4336           guint32 final_length = QT_UINT32 (final_data);
4337           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4338
4339           if (final_fourcc == FOURCC_free
4340               && map.size + final_length - 8 == length) {
4341             /* Ok, we've found that special case. Allocate a new buffer with
4342              * that free atom actually present. */
4343             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4344             gst_buffer_fill (newmoov, 0, map.data, map.size);
4345             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4346             gst_buffer_unmap (moov, &map);
4347             gst_buffer_unref (moov);
4348             moov = newmoov;
4349             gst_buffer_map (moov, &map, GST_MAP_READ);
4350           }
4351         }
4352       }
4353
4354       if (length != map.size) {
4355         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4356             (_("This file is incomplete and cannot be played.")),
4357             ("We got less than expected (received %" G_GSIZE_FORMAT
4358                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4359                 (guint) length, cur_offset));
4360         gst_buffer_unmap (moov, &map);
4361         gst_buffer_unref (moov);
4362         ret = GST_FLOW_ERROR;
4363         goto beach;
4364       }
4365       qtdemux->offset += length;
4366
4367       qtdemux_parse_moov (qtdemux, map.data, length);
4368       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4369
4370       qtdemux_parse_tree (qtdemux);
4371       if (qtdemux->moov_node_compressed) {
4372         g_node_destroy (qtdemux->moov_node_compressed);
4373         g_free (qtdemux->moov_node->data);
4374       }
4375       qtdemux->moov_node_compressed = NULL;
4376       g_node_destroy (qtdemux->moov_node);
4377       qtdemux->moov_node = NULL;
4378       gst_buffer_unmap (moov, &map);
4379       gst_buffer_unref (moov);
4380       qtdemux->got_moov = TRUE;
4381
4382       break;
4383     }
4384     case FOURCC_ftyp:
4385     {
4386       GstBuffer *ftyp = NULL;
4387
4388       /* extract major brand; might come in handy for ISO vs QT issues */
4389       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4390       if (ret != GST_FLOW_OK)
4391         goto beach;
4392       qtdemux->offset += length;
4393       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4394       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4395       gst_buffer_unmap (ftyp, &map);
4396       gst_buffer_unref (ftyp);
4397       break;
4398     }
4399     case FOURCC_uuid:
4400     {
4401       GstBuffer *uuid = NULL;
4402
4403       /* uuid are extension atoms */
4404       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4405       if (ret != GST_FLOW_OK)
4406         goto beach;
4407       qtdemux->offset += length;
4408       gst_buffer_map (uuid, &map, GST_MAP_READ);
4409       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4410       gst_buffer_unmap (uuid, &map);
4411       gst_buffer_unref (uuid);
4412       break;
4413     }
4414     case FOURCC_sidx:
4415     {
4416       GstBuffer *sidx = NULL;
4417       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4418       if (ret != GST_FLOW_OK)
4419         goto beach;
4420       qtdemux->offset += length;
4421       gst_buffer_map (sidx, &map, GST_MAP_READ);
4422       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4423       gst_buffer_unmap (sidx, &map);
4424       gst_buffer_unref (sidx);
4425       break;
4426     }
4427     default:
4428     {
4429       GstBuffer *unknown = NULL;
4430
4431       GST_LOG_OBJECT (qtdemux,
4432           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4433           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4434           cur_offset);
4435       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4436       if (ret != GST_FLOW_OK)
4437         goto beach;
4438       gst_buffer_map (unknown, &map, GST_MAP_READ);
4439       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4440       gst_buffer_unmap (unknown, &map);
4441       gst_buffer_unref (unknown);
4442       qtdemux->offset += length;
4443       break;
4444     }
4445   }
4446
4447 beach:
4448   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4449     /* digested all data, show what we have */
4450     qtdemux_prepare_streams (qtdemux);
4451     ret = qtdemux_expose_streams (qtdemux);
4452
4453     qtdemux->state = QTDEMUX_STATE_MOVIE;
4454     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4455         qtdemux->state);
4456     return ret;
4457   }
4458   return ret;
4459 }
4460
4461 /* Seeks to the previous keyframe of the indexed stream and
4462  * aligns other streams with respect to the keyframe timestamp
4463  * of indexed stream. Only called in case of Reverse Playback
4464  */
4465 static GstFlowReturn
4466 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4467 {
4468   guint8 n = 0;
4469   guint32 seg_idx = 0, k_index = 0;
4470   guint32 ref_seg_idx, ref_k_index;
4471   GstClockTime k_pos = 0, last_stop = 0;
4472   QtDemuxSegment *seg = NULL;
4473   QtDemuxStream *ref_str = NULL;
4474   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4475   guint64 target_ts;
4476
4477   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4478    * and finally align all the other streams on that timestamp with their
4479    * respective keyframes */
4480   for (n = 0; n < qtdemux->n_streams; n++) {
4481     QtDemuxStream *str = qtdemux->streams[n];
4482
4483     /* No candidate yet, take the first stream */
4484     if (!ref_str) {
4485       ref_str = str;
4486       continue;
4487     }
4488
4489     /* So that stream has a segment, we prefer video streams */
4490     if (str->subtype == FOURCC_vide) {
4491       ref_str = str;
4492       break;
4493     }
4494   }
4495
4496   if (G_UNLIKELY (!ref_str)) {
4497     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4498     goto eos;
4499   }
4500
4501   if (G_UNLIKELY (!ref_str->from_sample)) {
4502     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4503     goto eos;
4504   }
4505
4506   /* So that stream has been playing from from_sample to to_sample. We will
4507    * get the timestamp of the previous sample and search for a keyframe before
4508    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4509   if (ref_str->subtype == FOURCC_vide) {
4510     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4511         ref_str->from_sample - 1, FALSE);
4512   } else {
4513     if (ref_str->from_sample >= 10)
4514       k_index = ref_str->from_sample - 10;
4515     else
4516       k_index = 0;
4517   }
4518
4519   target_ts =
4520       ref_str->samples[k_index].timestamp +
4521       ref_str->samples[k_index].pts_offset;
4522
4523   /* get current segment for that stream */
4524   seg = &ref_str->segments[ref_str->segment_index];
4525   /* Use segment start in original timescale for comparisons */
4526   seg_media_start_mov = seg->trak_media_start;
4527
4528   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4529       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4530       k_index, target_ts, seg_media_start_mov,
4531       GST_TIME_ARGS (seg->media_start));
4532
4533   /* Crawl back through segments to find the one containing this I frame */
4534   while (target_ts < seg_media_start_mov) {
4535     GST_DEBUG_OBJECT (qtdemux,
4536         "keyframe position (sample %u) is out of segment %u " " target %"
4537         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4538         ref_str->segment_index, target_ts, seg_media_start_mov);
4539
4540     if (G_UNLIKELY (!ref_str->segment_index)) {
4541       /* Reached first segment, let's consider it's EOS */
4542       goto eos;
4543     }
4544     ref_str->segment_index--;
4545     seg = &ref_str->segments[ref_str->segment_index];
4546     /* Use segment start in original timescale for comparisons */
4547     seg_media_start_mov = seg->trak_media_start;
4548   }
4549   /* Calculate time position of the keyframe and where we should stop */
4550   k_pos =
4551       QTSTREAMTIME_TO_GSTTIME (ref_str,
4552       target_ts - seg->trak_media_start) + seg->time;
4553   last_stop =
4554       QTSTREAMTIME_TO_GSTTIME (ref_str,
4555       ref_str->samples[ref_str->from_sample].timestamp -
4556       seg->trak_media_start) + seg->time;
4557
4558   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4559       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4560       k_index, GST_TIME_ARGS (k_pos));
4561
4562   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4563   qtdemux->segment.position = last_stop;
4564   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4565       GST_TIME_ARGS (last_stop));
4566
4567   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4568     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4569     goto eos;
4570   }
4571
4572   ref_seg_idx = ref_str->segment_index;
4573   ref_k_index = k_index;
4574
4575   /* Align them all on this */
4576   for (n = 0; n < qtdemux->n_streams; n++) {
4577     guint32 index = 0;
4578     GstClockTime seg_time = 0;
4579     QtDemuxStream *str = qtdemux->streams[n];
4580
4581     /* aligning reference stream again might lead to backing up to yet another
4582      * keyframe (due to timestamp rounding issues),
4583      * potentially putting more load on downstream; so let's try to avoid */
4584     if (str == ref_str) {
4585       seg_idx = ref_seg_idx;
4586       seg = &str->segments[seg_idx];
4587       k_index = ref_k_index;
4588       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4589           "sample at index %d", n, ref_str->segment_index, k_index);
4590     } else {
4591       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4592       GST_DEBUG_OBJECT (qtdemux,
4593           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4594           seg_idx, GST_TIME_ARGS (k_pos));
4595
4596       /* get segment and time in the segment */
4597       seg = &str->segments[seg_idx];
4598       seg_time = k_pos - seg->time;
4599
4600       /* get the media time in the segment.
4601        * No adjustment for empty "filler" segments */
4602       if (seg->media_start != GST_CLOCK_TIME_NONE)
4603         seg_time += seg->media_start;
4604
4605       /* get the index of the sample with media time */
4606       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4607       GST_DEBUG_OBJECT (qtdemux,
4608           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4609           GST_TIME_ARGS (seg_time), index);
4610
4611       /* find previous keyframe */
4612       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4613     }
4614
4615     /* Remember until where we want to go */
4616     str->to_sample = str->from_sample - 1;
4617     /* Define our time position */
4618     target_ts =
4619         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4620     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4621     if (seg->media_start != GST_CLOCK_TIME_NONE)
4622       str->time_position -= seg->media_start;
4623
4624     /* Now seek back in time */
4625     gst_qtdemux_move_stream (qtdemux, str, k_index);
4626     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4627         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4628         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4629   }
4630
4631   return GST_FLOW_OK;
4632
4633 eos:
4634   return GST_FLOW_EOS;
4635 }
4636
4637 /*
4638  * Gets the current qt segment start, stop and position for the
4639  * given time offset. This is used in update_segment()
4640  */
4641 static void
4642 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4643     QtDemuxStream * stream, GstClockTime offset,
4644     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4645 {
4646   GstClockTime seg_time;
4647   GstClockTime start, stop, time;
4648   QtDemuxSegment *segment;
4649
4650   segment = &stream->segments[stream->segment_index];
4651
4652   /* get time in this segment */
4653   seg_time = (offset - segment->time) * segment->rate;
4654
4655   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4656       GST_TIME_ARGS (seg_time));
4657
4658   if (G_UNLIKELY (seg_time > segment->duration)) {
4659     GST_LOG_OBJECT (stream->pad,
4660         "seg_time > segment->duration %" GST_TIME_FORMAT,
4661         GST_TIME_ARGS (segment->duration));
4662     seg_time = segment->duration;
4663   }
4664
4665   /* qtdemux->segment.stop is in outside-time-realm, whereas
4666    * segment->media_stop is in track-time-realm.
4667    *
4668    * In order to compare the two, we need to bring segment.stop
4669    * into the track-time-realm
4670    *
4671    * FIXME - does this comment still hold? Don't see any conversion here */
4672
4673   stop = qtdemux->segment.stop;
4674   if (stop == GST_CLOCK_TIME_NONE)
4675     stop = qtdemux->segment.duration;
4676   if (stop == GST_CLOCK_TIME_NONE)
4677     stop = segment->media_stop;
4678   else
4679     stop =
4680         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4681
4682   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4683     start = segment->time + seg_time;
4684     time = offset;
4685     stop = start - seg_time + segment->duration;
4686   } else if (qtdemux->segment.rate >= 0) {
4687     start = MIN (segment->media_start + seg_time, stop);
4688     time = offset;
4689   } else {
4690     if (segment->media_start >= qtdemux->segment.start) {
4691       time = segment->time;
4692     } else {
4693       time = segment->time + (qtdemux->segment.start - segment->media_start);
4694     }
4695
4696     start = MAX (segment->media_start, qtdemux->segment.start);
4697     stop = MIN (segment->media_start + seg_time, stop);
4698   }
4699
4700   *_start = start;
4701   *_stop = stop;
4702   *_time = time;
4703 }
4704
4705 /*
4706  * Updates the qt segment used for the stream and pushes a new segment event
4707  * downstream on this stream's pad.
4708  */
4709 static gboolean
4710 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4711     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4712     GstClockTime * _stop)
4713 {
4714   QtDemuxSegment *segment;
4715   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4716   gdouble rate;
4717   GstEvent *event;
4718
4719   /* update the current segment */
4720   stream->segment_index = seg_idx;
4721
4722   /* get the segment */
4723   segment = &stream->segments[seg_idx];
4724
4725   if (G_UNLIKELY (offset < segment->time)) {
4726     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4727         GST_TIME_ARGS (segment->time));
4728     return FALSE;
4729   }
4730
4731   /* segment lies beyond total indicated duration */
4732   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4733           segment->time > qtdemux->segment.duration)) {
4734     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4735         " < segment->time %" GST_TIME_FORMAT,
4736         GST_TIME_ARGS (qtdemux->segment.duration),
4737         GST_TIME_ARGS (segment->time));
4738     return FALSE;
4739   }
4740
4741   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4742       &start, &stop, &time);
4743
4744   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4745       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4746       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4747
4748   /* combine global rate with that of the segment */
4749   rate = segment->rate * qtdemux->segment.rate;
4750
4751   /* Copy flags from main segment */
4752   stream->segment.flags = qtdemux->segment.flags;
4753
4754   /* update the segment values used for clipping */
4755   stream->segment.offset = qtdemux->segment.offset;
4756   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4757   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4758   stream->segment.rate = rate;
4759   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4760       stream->cslg_shift);
4761   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4762       stream->cslg_shift);
4763   stream->segment.time = time;
4764   stream->segment.position = stream->segment.start;
4765
4766   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4767       &stream->segment);
4768
4769   /* now prepare and send the segment */
4770   if (stream->pad) {
4771     event = gst_event_new_segment (&stream->segment);
4772     if (qtdemux->segment_seqnum) {
4773       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4774     }
4775     gst_pad_push_event (stream->pad, event);
4776     /* assume we can send more data now */
4777     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4778     /* clear to send tags on this pad now */
4779     gst_qtdemux_push_tags (qtdemux, stream);
4780   }
4781
4782   if (_start)
4783     *_start = start;
4784   if (_stop)
4785     *_stop = stop;
4786
4787   return TRUE;
4788 }
4789
4790 /* activate the given segment number @seg_idx of @stream at time @offset.
4791  * @offset is an absolute global position over all the segments.
4792  *
4793  * This will push out a NEWSEGMENT event with the right values and
4794  * position the stream index to the first decodable sample before
4795  * @offset.
4796  */
4797 static gboolean
4798 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4799     guint32 seg_idx, GstClockTime offset)
4800 {
4801   QtDemuxSegment *segment;
4802   guint32 index, kf_index;
4803   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4804
4805   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4806       seg_idx, GST_TIME_ARGS (offset));
4807
4808   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4809           &start, &stop))
4810     return FALSE;
4811
4812   segment = &stream->segments[stream->segment_index];
4813
4814   /* in the fragmented case, we pick a fragment that starts before our
4815    * desired position and rely on downstream to wait for a keyframe
4816    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4817    * tfra entries tells us which trun/sample the key unit is in, but we don't
4818    * make use of this additional information at the moment) */
4819   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4820     stream->to_sample = G_MAXUINT32;
4821     return TRUE;
4822   } else {
4823     /* well, it will be taken care of below */
4824     qtdemux->fragmented_seek_pending = FALSE;
4825     /* FIXME ideally the do_fragmented_seek can be done right here,
4826      * rather than at loop level
4827      * (which might even allow handling edit lists in a fragmented file) */
4828   }
4829
4830   /* We don't need to look for a sample in push-based */
4831   if (!qtdemux->pullbased)
4832     return TRUE;
4833
4834   /* and move to the keyframe before the indicated media time of the
4835    * segment */
4836   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4837     if (qtdemux->segment.rate >= 0) {
4838       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4839       stream->to_sample = G_MAXUINT32;
4840       GST_DEBUG_OBJECT (stream->pad,
4841           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4842           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4843           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4844     } else {
4845       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4846       stream->to_sample = index;
4847       GST_DEBUG_OBJECT (stream->pad,
4848           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4849           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4850           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4851     }
4852   } else {
4853     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4854         "this is an empty segment");
4855     return TRUE;
4856   }
4857
4858   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4859    * encountered an error and printed a message so we return appropriately */
4860   if (index == -1)
4861     return FALSE;
4862
4863   /* we're at the right spot */
4864   if (index == stream->sample_index) {
4865     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4866     return TRUE;
4867   }
4868
4869   /* find keyframe of the target index */
4870   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4871
4872 /* *INDENT-OFF* */
4873 /* indent does stupid stuff with stream->samples[].timestamp */
4874
4875   /* if we move forwards, we don't have to go back to the previous
4876    * keyframe since we already sent that. We can also just jump to
4877    * the keyframe right before the target index if there is one. */
4878   if (index > stream->sample_index) {
4879     /* moving forwards check if we move past a keyframe */
4880     if (kf_index > stream->sample_index) {
4881       GST_DEBUG_OBJECT (stream->pad,
4882            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4883            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4884            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4885       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4886     } else {
4887       GST_DEBUG_OBJECT (stream->pad,
4888           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4889           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4890           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4891     }
4892   } else {
4893     GST_DEBUG_OBJECT (stream->pad,
4894         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4895         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4896         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4897     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4898   }
4899
4900 /* *INDENT-ON* */
4901
4902   return TRUE;
4903 }
4904
4905 /* prepare to get the current sample of @stream, getting essential values.
4906  *
4907  * This function will also prepare and send the segment when needed.
4908  *
4909  * Return FALSE if the stream is EOS.
4910  *
4911  * PULL-BASED
4912  */
4913 static gboolean
4914 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4915     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4916     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4917     gboolean * keyframe)
4918 {
4919   QtDemuxSample *sample;
4920   GstClockTime time_position;
4921   guint32 seg_idx;
4922
4923   g_return_val_if_fail (stream != NULL, FALSE);
4924
4925   time_position = stream->time_position;
4926   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4927     goto eos;
4928
4929   seg_idx = stream->segment_index;
4930   if (G_UNLIKELY (seg_idx == -1)) {
4931     /* find segment corresponding to time_position if we are looking
4932      * for a segment. */
4933     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4934   }
4935
4936   /* different segment, activate it, sample_index will be set. */
4937   if (G_UNLIKELY (stream->segment_index != seg_idx))
4938     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4939
4940   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4941                   segment_index]))) {
4942     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4943
4944     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4945         " prepare empty sample");
4946
4947     *empty = TRUE;
4948     *pts = *dts = time_position;
4949     *duration = seg->duration - (time_position - seg->time);
4950
4951     return TRUE;
4952   }
4953
4954   *empty = FALSE;
4955
4956   if (stream->sample_index == -1)
4957     stream->sample_index = 0;
4958
4959   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4960       stream->sample_index, stream->n_samples);
4961
4962   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4963     if (!qtdemux->fragmented)
4964       goto eos;
4965
4966     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4967     do {
4968       GstFlowReturn flow;
4969
4970       GST_OBJECT_LOCK (qtdemux);
4971       flow = qtdemux_add_fragmented_samples (qtdemux);
4972       GST_OBJECT_UNLOCK (qtdemux);
4973
4974       if (flow != GST_FLOW_OK)
4975         goto eos;
4976     }
4977     while (stream->sample_index >= stream->n_samples);
4978   }
4979
4980   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4981     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4982         stream->sample_index);
4983     return FALSE;
4984   }
4985
4986   /* now get the info for the sample we're at */
4987   sample = &stream->samples[stream->sample_index];
4988
4989   *dts = QTSAMPLE_DTS (stream, sample);
4990   *pts = QTSAMPLE_PTS (stream, sample);
4991   *offset = sample->offset;
4992   *size = sample->size;
4993   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4994   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4995
4996   return TRUE;
4997
4998   /* special cases */
4999 eos:
5000   {
5001     stream->time_position = GST_CLOCK_TIME_NONE;
5002     return FALSE;
5003   }
5004 }
5005
5006 /* move to the next sample in @stream.
5007  *
5008  * Moves to the next segment when needed.
5009  */
5010 static void
5011 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5012 {
5013   QtDemuxSample *sample;
5014   QtDemuxSegment *segment;
5015
5016   /* get current segment */
5017   segment = &stream->segments[stream->segment_index];
5018
5019   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5020     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5021     goto next_segment;
5022   }
5023
5024   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5025     /* Mark the stream as EOS */
5026     GST_DEBUG_OBJECT (qtdemux,
5027         "reached max allowed sample %u, mark EOS", stream->to_sample);
5028     stream->time_position = GST_CLOCK_TIME_NONE;
5029     return;
5030   }
5031
5032   /* move to next sample */
5033   stream->sample_index++;
5034   stream->offset_in_sample = 0;
5035
5036   /* reached the last sample, we need the next segment */
5037   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5038     goto next_segment;
5039
5040   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5041     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5042         stream->sample_index);
5043     return;
5044   }
5045
5046   /* get next sample */
5047   sample = &stream->samples[stream->sample_index];
5048
5049   /* see if we are past the segment */
5050   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5051     goto next_segment;
5052
5053   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5054     /* inside the segment, update time_position, looks very familiar to
5055      * GStreamer segments, doesn't it? */
5056     stream->time_position =
5057         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5058   } else {
5059     /* not yet in segment, time does not yet increment. This means
5060      * that we are still prerolling keyframes to the decoder so it can
5061      * decode the first sample of the segment. */
5062     stream->time_position = segment->time;
5063   }
5064   return;
5065
5066   /* move to the next segment */
5067 next_segment:
5068   {
5069     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5070
5071     if (stream->segment_index == stream->n_segments - 1) {
5072       /* are we at the end of the last segment, we're EOS */
5073       stream->time_position = GST_CLOCK_TIME_NONE;
5074     } else {
5075       /* else we're only at the end of the current segment */
5076       stream->time_position = segment->stop_time;
5077     }
5078     /* make sure we select a new segment */
5079
5080     /* accumulate previous segments */
5081     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5082       stream->accumulated_base +=
5083           (stream->segment.stop -
5084           stream->segment.start) / ABS (stream->segment.rate);
5085
5086     stream->segment_index = -1;
5087   }
5088 }
5089
5090 static void
5091 gst_qtdemux_sync_streams (GstQTDemux * demux)
5092 {
5093   gint i;
5094
5095   if (demux->n_streams <= 1)
5096     return;
5097
5098   for (i = 0; i < demux->n_streams; i++) {
5099     QtDemuxStream *stream;
5100     GstClockTime end_time;
5101
5102     stream = demux->streams[i];
5103
5104     if (!stream->pad)
5105       continue;
5106
5107     /* TODO advance time on subtitle streams here, if any some day */
5108
5109     /* some clips/trailers may have unbalanced streams at the end,
5110      * so send EOS on shorter stream to prevent stalling others */
5111
5112     /* do not mess with EOS if SEGMENT seeking */
5113     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5114       continue;
5115
5116     if (demux->pullbased) {
5117       /* loop mode is sample time based */
5118       if (!STREAM_IS_EOS (stream))
5119         continue;
5120     } else {
5121       /* push mode is byte position based */
5122       if (stream->n_samples &&
5123           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5124         continue;
5125     }
5126
5127     if (stream->sent_eos)
5128       continue;
5129
5130     /* only act if some gap */
5131     end_time = stream->segments[stream->n_segments - 1].stop_time;
5132     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5133         ", stream end: %" GST_TIME_FORMAT,
5134         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5135     if (GST_CLOCK_TIME_IS_VALID (end_time)
5136         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5137       GstEvent *event;
5138
5139       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5140           GST_PAD_NAME (stream->pad));
5141       stream->sent_eos = TRUE;
5142       event = gst_event_new_eos ();
5143       if (demux->segment_seqnum)
5144         gst_event_set_seqnum (event, demux->segment_seqnum);
5145       gst_pad_push_event (stream->pad, event);
5146     }
5147   }
5148 }
5149
5150 /* EOS and NOT_LINKED need to be combined. This means that we return:
5151  *
5152  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5153  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5154  */
5155 static GstFlowReturn
5156 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5157     GstFlowReturn ret)
5158 {
5159   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5160
5161   if (stream->pad)
5162     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5163         ret);
5164   else
5165     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5166
5167   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5168   return ret;
5169 }
5170
5171 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5172  * completely clipped
5173  *
5174  * Should be used only with raw buffers */
5175 static GstBuffer *
5176 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5177     GstBuffer * buf)
5178 {
5179   guint64 start, stop, cstart, cstop, diff;
5180   GstClockTime pts, duration;
5181   gsize size, osize;
5182   gint num_rate, denom_rate;
5183   gint frame_size;
5184   gboolean clip_data;
5185   guint offset;
5186
5187   osize = size = gst_buffer_get_size (buf);
5188   offset = 0;
5189
5190   /* depending on the type, setup the clip parameters */
5191   if (stream->subtype == FOURCC_soun) {
5192     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5193     num_rate = GST_SECOND;
5194     denom_rate = (gint) CUR_STREAM (stream)->rate;
5195     clip_data = TRUE;
5196   } else if (stream->subtype == FOURCC_vide) {
5197     frame_size = size;
5198     num_rate = CUR_STREAM (stream)->fps_n;
5199     denom_rate = CUR_STREAM (stream)->fps_d;
5200     clip_data = FALSE;
5201   } else
5202     goto wrong_type;
5203
5204   if (frame_size <= 0)
5205     goto bad_frame_size;
5206
5207   /* we can only clip if we have a valid pts */
5208   pts = GST_BUFFER_PTS (buf);
5209   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5210     goto no_pts;
5211
5212   duration = GST_BUFFER_DURATION (buf);
5213
5214   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5215     duration =
5216         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5217   }
5218
5219   start = pts;
5220   stop = start + duration;
5221
5222   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5223               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5224     goto clipped;
5225
5226   /* see if some clipping happened */
5227   diff = cstart - start;
5228   if (diff > 0) {
5229     pts += diff;
5230     duration -= diff;
5231
5232     if (clip_data) {
5233       /* bring clipped time to samples and to bytes */
5234       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5235       diff *= frame_size;
5236
5237       GST_DEBUG_OBJECT (qtdemux,
5238           "clipping start to %" GST_TIME_FORMAT " %"
5239           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5240
5241       offset = diff;
5242       size -= diff;
5243     }
5244   }
5245   diff = stop - cstop;
5246   if (diff > 0) {
5247     duration -= diff;
5248
5249     if (clip_data) {
5250       /* bring clipped time to samples and then to bytes */
5251       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5252       diff *= frame_size;
5253       GST_DEBUG_OBJECT (qtdemux,
5254           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5255           " bytes", GST_TIME_ARGS (cstop), diff);
5256       size -= diff;
5257     }
5258   }
5259
5260   if (offset != 0 || size != osize)
5261     gst_buffer_resize (buf, offset, size);
5262
5263   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5264   GST_BUFFER_PTS (buf) = pts;
5265   GST_BUFFER_DURATION (buf) = duration;
5266
5267   return buf;
5268
5269   /* dropped buffer */
5270 wrong_type:
5271   {
5272     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5273     return buf;
5274   }
5275 bad_frame_size:
5276   {
5277     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5278     return buf;
5279   }
5280 no_pts:
5281   {
5282     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5283     return buf;
5284   }
5285 clipped:
5286   {
5287     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5288     gst_buffer_unref (buf);
5289     return NULL;
5290   }
5291 }
5292
5293 static GstBuffer *
5294 gst_qtdemux_align_buffer (GstQTDemux * demux,
5295     GstBuffer * buffer, gsize alignment)
5296 {
5297   GstMapInfo map;
5298
5299   gst_buffer_map (buffer, &map, GST_MAP_READ);
5300
5301   if (map.size < sizeof (guintptr)) {
5302     gst_buffer_unmap (buffer, &map);
5303     return buffer;
5304   }
5305
5306   if (((guintptr) map.data) & (alignment - 1)) {
5307     GstBuffer *new_buffer;
5308     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5309
5310     new_buffer = gst_buffer_new_allocate (NULL,
5311         gst_buffer_get_size (buffer), &params);
5312
5313     /* Copy data "by hand", so ensure alignment is kept: */
5314     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5315
5316     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5317     GST_DEBUG_OBJECT (demux,
5318         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5319         alignment);
5320
5321     gst_buffer_unmap (buffer, &map);
5322     gst_buffer_unref (buffer);
5323
5324     return new_buffer;
5325   }
5326
5327   gst_buffer_unmap (buffer, &map);
5328   return buffer;
5329 }
5330
5331 /* the input buffer metadata must be writable,
5332  * but time/duration etc not yet set and need not be preserved */
5333 static GstBuffer *
5334 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5335     GstBuffer * buf)
5336 {
5337   GstMapInfo map;
5338   guint nsize = 0;
5339   gchar *str;
5340
5341   /* not many cases for now */
5342   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5343     /* send a one time dvd clut event */
5344     if (stream->pending_event && stream->pad)
5345       gst_pad_push_event (stream->pad, stream->pending_event);
5346     stream->pending_event = NULL;
5347   }
5348
5349   if (G_UNLIKELY (stream->subtype != FOURCC_text
5350           && stream->subtype != FOURCC_sbtl &&
5351           stream->subtype != FOURCC_subp)) {
5352     return buf;
5353   }
5354
5355   gst_buffer_map (buf, &map, GST_MAP_READ);
5356
5357   /* empty buffer is sent to terminate previous subtitle */
5358   if (map.size <= 2) {
5359     gst_buffer_unmap (buf, &map);
5360     gst_buffer_unref (buf);
5361     return NULL;
5362   }
5363   if (stream->subtype == FOURCC_subp) {
5364     /* That's all the processing needed for subpictures */
5365     gst_buffer_unmap (buf, &map);
5366     return buf;
5367   }
5368
5369   nsize = GST_READ_UINT16_BE (map.data);
5370   nsize = MIN (nsize, map.size - 2);
5371
5372   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5373       nsize, map.size);
5374
5375   /* takes care of UTF-8 validation or UTF-16 recognition,
5376    * no other encoding expected */
5377   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5378   gst_buffer_unmap (buf, &map);
5379   if (str) {
5380     gst_buffer_unref (buf);
5381     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5382   } else {
5383     /* this should not really happen unless the subtitle is corrupted */
5384     gst_buffer_unref (buf);
5385     buf = NULL;
5386   }
5387
5388   /* FIXME ? convert optional subsequent style info to markup */
5389
5390   return buf;
5391 }
5392
5393 /* Sets a buffer's attributes properly and pushes it downstream.
5394  * Also checks for additional actions and custom processing that may
5395  * need to be done first.
5396  */
5397 static GstFlowReturn
5398 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5399     QtDemuxStream * stream, GstBuffer * buf,
5400     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5401     gboolean keyframe, GstClockTime position, guint64 byte_position)
5402 {
5403   GstFlowReturn ret = GST_FLOW_OK;
5404
5405   /* offset the timestamps according to the edit list */
5406
5407   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5408     gchar *url;
5409     GstMapInfo map;
5410
5411     gst_buffer_map (buf, &map, GST_MAP_READ);
5412     url = g_strndup ((gchar *) map.data, map.size);
5413     gst_buffer_unmap (buf, &map);
5414     if (url != NULL && strlen (url) != 0) {
5415       /* we have RTSP redirect now */
5416       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5417           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5418               gst_structure_new ("redirect",
5419                   "new-location", G_TYPE_STRING, url, NULL)));
5420       qtdemux->posted_redirect = TRUE;
5421     } else {
5422       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5423           "posting");
5424     }
5425     g_free (url);
5426   }
5427
5428   /* position reporting */
5429   if (qtdemux->segment.rate >= 0) {
5430     qtdemux->segment.position = position;
5431     gst_qtdemux_sync_streams (qtdemux);
5432   }
5433
5434   if (G_UNLIKELY (!stream->pad)) {
5435     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5436     gst_buffer_unref (buf);
5437     goto exit;
5438   }
5439
5440   /* send out pending buffers */
5441   while (stream->buffers) {
5442     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5443
5444     if (G_UNLIKELY (stream->discont)) {
5445       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5446       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5447       stream->discont = FALSE;
5448     } else {
5449       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5450     }
5451
5452     if (stream->alignment > 1)
5453       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5454     gst_pad_push (stream->pad, buffer);
5455
5456     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5457   }
5458
5459   /* we're going to modify the metadata */
5460   buf = gst_buffer_make_writable (buf);
5461
5462   if (G_UNLIKELY (stream->need_process))
5463     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5464
5465   if (!buf) {
5466     goto exit;
5467   }
5468
5469   GST_BUFFER_DTS (buf) = dts;
5470   GST_BUFFER_PTS (buf) = pts;
5471   GST_BUFFER_DURATION (buf) = duration;
5472   GST_BUFFER_OFFSET (buf) = -1;
5473   GST_BUFFER_OFFSET_END (buf) = -1;
5474
5475   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5476     gst_buffer_append_memory (buf,
5477         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5478
5479   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5480     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5481   }
5482 #if 0
5483   if (G_UNLIKELY (qtdemux->element_index)) {
5484     GstClockTime stream_time;
5485
5486     stream_time =
5487         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5488         timestamp);
5489     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5490       GST_LOG_OBJECT (qtdemux,
5491           "adding association %" GST_TIME_FORMAT "-> %"
5492           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5493       gst_index_add_association (qtdemux->element_index,
5494           qtdemux->index_id,
5495           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5496           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5497           GST_FORMAT_BYTES, byte_position, NULL);
5498     }
5499   }
5500 #endif
5501
5502   if (stream->need_clip)
5503     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5504
5505   if (G_UNLIKELY (buf == NULL))
5506     goto exit;
5507
5508   if (G_UNLIKELY (stream->discont)) {
5509     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5510     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5511     stream->discont = FALSE;
5512   } else {
5513     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5514   }
5515
5516   if (!keyframe) {
5517     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5518     stream->on_keyframe = FALSE;
5519   } else {
5520     stream->on_keyframe = TRUE;
5521   }
5522
5523
5524   GST_LOG_OBJECT (qtdemux,
5525       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5526       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5527       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5528       GST_PAD_NAME (stream->pad));
5529
5530   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5531     GstStructure *crypto_info;
5532     QtDemuxCencSampleSetInfo *info =
5533         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5534     gint index;
5535     GstEvent *event;
5536
5537     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5538       gst_pad_push_event (stream->pad, event);
5539     }
5540
5541     if (info->crypto_info == NULL) {
5542       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5543       gst_buffer_unref (buf);
5544       goto exit;
5545     }
5546
5547     /* The end of the crypto_info array matches our n_samples position,
5548      * so count backward from there */
5549     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5550     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5551       /* steal structure from array */
5552       crypto_info = g_ptr_array_index (info->crypto_info, index);
5553       g_ptr_array_index (info->crypto_info, index) = NULL;
5554       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5555           info->crypto_info->len);
5556       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5557         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5558     } else {
5559       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5560           index, stream->sample_index);
5561     }
5562   }
5563
5564   if (stream->alignment > 1)
5565     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5566
5567   ret = gst_pad_push (stream->pad, buf);
5568
5569   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5570     /* mark position in stream, we'll need this to know when to send GAP event */
5571     stream->segment.position = pts + duration;
5572   }
5573
5574 exit:
5575   return ret;
5576 }
5577
5578 static const QtDemuxRandomAccessEntry *
5579 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5580     GstClockTime pos, gboolean after)
5581 {
5582   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5583   guint n_entries = stream->n_ra_entries;
5584   guint i;
5585
5586   /* we assume the table is sorted */
5587   for (i = 0; i < n_entries; ++i) {
5588     if (entries[i].ts > pos)
5589       break;
5590   }
5591
5592   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5593    * probably okay to assume that the index lists the very first fragment */
5594   if (i == 0)
5595     return &entries[0];
5596
5597   if (after)
5598     return &entries[i];
5599   else
5600     return &entries[i - 1];
5601 }
5602
5603 static gboolean
5604 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5605 {
5606   const QtDemuxRandomAccessEntry *best_entry = NULL;
5607   guint i;
5608
5609   GST_OBJECT_LOCK (qtdemux);
5610
5611   g_assert (qtdemux->n_streams > 0);
5612
5613   /* first see if we can determine where to go to using mfra,
5614    * before we start clearing things */
5615   for (i = 0; i < qtdemux->n_streams; i++) {
5616     const QtDemuxRandomAccessEntry *entry;
5617     QtDemuxStream *stream;
5618     gboolean is_audio_or_video;
5619
5620     stream = qtdemux->streams[i];
5621
5622     if (stream->ra_entries == NULL)
5623       continue;
5624
5625     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5626       is_audio_or_video = TRUE;
5627     else
5628       is_audio_or_video = FALSE;
5629
5630     entry =
5631         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5632         stream->time_position, !is_audio_or_video);
5633
5634     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5635         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5636
5637     stream->pending_seek = entry;
5638
5639     /* decide position to jump to just based on audio/video tracks, not subs */
5640     if (!is_audio_or_video)
5641       continue;
5642
5643     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5644       best_entry = entry;
5645   }
5646
5647   /* no luck, will handle seek otherwise */
5648   if (best_entry == NULL) {
5649     GST_OBJECT_UNLOCK (qtdemux);
5650     return FALSE;
5651   }
5652
5653   /* ok, now we can prepare for processing as of located moof */
5654   for (i = 0; i < qtdemux->n_streams; i++) {
5655     QtDemuxStream *stream;
5656
5657     stream = qtdemux->streams[i];
5658
5659     g_free (stream->samples);
5660     stream->samples = NULL;
5661     stream->n_samples = 0;
5662     stream->stbl_index = -1;    /* no samples have yet been parsed */
5663     stream->sample_index = -1;
5664
5665     if (stream->protection_scheme_info) {
5666       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5667       if (stream->protection_scheme_type == FOURCC_cenc) {
5668         QtDemuxCencSampleSetInfo *info =
5669             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5670         if (info->crypto_info) {
5671           g_ptr_array_free (info->crypto_info, TRUE);
5672           info->crypto_info = NULL;
5673         }
5674       }
5675     }
5676   }
5677
5678   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5679       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5680       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5681       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5682
5683   qtdemux->moof_offset = best_entry->moof_offset;
5684
5685   qtdemux_add_fragmented_samples (qtdemux);
5686
5687   GST_OBJECT_UNLOCK (qtdemux);
5688   return TRUE;
5689 }
5690
5691 static GstFlowReturn
5692 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5693 {
5694   GstFlowReturn ret = GST_FLOW_OK;
5695   GstBuffer *buf = NULL;
5696   QtDemuxStream *stream;
5697   GstClockTime min_time;
5698   guint64 offset = 0;
5699   GstClockTime dts = GST_CLOCK_TIME_NONE;
5700   GstClockTime pts = GST_CLOCK_TIME_NONE;
5701   GstClockTime duration = 0;
5702   gboolean keyframe = FALSE;
5703   guint sample_size = 0;
5704   gboolean empty = 0;
5705   guint size;
5706   gint index;
5707   gint i;
5708
5709   gst_qtdemux_push_pending_newsegment (qtdemux);
5710
5711   if (qtdemux->fragmented_seek_pending) {
5712     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5713     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
5714       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5715       qtdemux->fragmented_seek_pending = FALSE;
5716     } else {
5717       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
5718     }
5719   }
5720
5721   /* Figure out the next stream sample to output, min_time is expressed in
5722    * global time and runs over the edit list segments. */
5723   min_time = G_MAXUINT64;
5724   index = -1;
5725   for (i = 0; i < qtdemux->n_streams; i++) {
5726     GstClockTime position;
5727
5728     stream = qtdemux->streams[i];
5729     position = stream->time_position;
5730
5731     /* position of -1 is EOS */
5732     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5733       min_time = position;
5734       index = i;
5735     }
5736   }
5737   /* all are EOS */
5738   if (G_UNLIKELY (index == -1)) {
5739     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5740     goto eos;
5741   }
5742
5743   /* check for segment end */
5744   if (G_UNLIKELY (qtdemux->segment.stop != -1
5745           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5746               || (qtdemux->segment.rate < 0
5747                   && qtdemux->segment.start > min_time))
5748           && qtdemux->streams[index]->on_keyframe)) {
5749     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5750     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5751     goto eos_stream;
5752   }
5753
5754   /* gap events for subtitle streams */
5755   for (i = 0; i < qtdemux->n_streams; i++) {
5756     stream = qtdemux->streams[i];
5757     if (stream->pad && (stream->subtype == FOURCC_subp
5758             || stream->subtype == FOURCC_text
5759             || stream->subtype == FOURCC_sbtl)) {
5760       /* send one second gap events until the stream catches up */
5761       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5762       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5763           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5764           stream->segment.position + GST_SECOND < min_time) {
5765         GstEvent *gap =
5766             gst_event_new_gap (stream->segment.position, GST_SECOND);
5767         gst_pad_push_event (stream->pad, gap);
5768         stream->segment.position += GST_SECOND;
5769       }
5770     }
5771   }
5772
5773   stream = qtdemux->streams[index];
5774   /* fetch info for the current sample of this stream */
5775   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5776               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5777     goto eos_stream;
5778
5779   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5780   if (stream->new_caps) {
5781     gst_qtdemux_configure_stream (qtdemux, stream);
5782     qtdemux_do_allocation (qtdemux, stream);
5783   }
5784
5785   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5786   if (G_UNLIKELY (qtdemux->
5787           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5788     if (stream->subtype == FOURCC_vide && !keyframe) {
5789       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5790       goto next;
5791     }
5792   }
5793
5794   GST_DEBUG_OBJECT (qtdemux,
5795       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5796       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5797       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5798       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5799
5800   if (G_UNLIKELY (empty)) {
5801     /* empty segment, push a gap and move to the next one */
5802     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5803     stream->segment.position = pts + duration;
5804     goto next;
5805   }
5806
5807   /* hmm, empty sample, skip and move to next sample */
5808   if (G_UNLIKELY (sample_size <= 0))
5809     goto next;
5810
5811   /* last pushed sample was out of boundary, goto next sample */
5812   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5813     goto next;
5814
5815   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5816     size = sample_size;
5817   } else {
5818     GST_DEBUG_OBJECT (qtdemux,
5819         "size %d larger than stream max_buffer_size %d, trimming",
5820         sample_size, stream->max_buffer_size);
5821     size =
5822         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5823   }
5824
5825   if (qtdemux->cenc_aux_info_offset > 0) {
5826     GstMapInfo map;
5827     GstByteReader br;
5828     GstBuffer *aux_info = NULL;
5829
5830     /* pull the data stored before the sample */
5831     ret =
5832         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5833         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5834     if (G_UNLIKELY (ret != GST_FLOW_OK))
5835       goto beach;
5836     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5837     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5838     gst_byte_reader_init (&br, map.data + 8, map.size);
5839     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5840             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5841       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5842       gst_buffer_unmap (aux_info, &map);
5843       gst_buffer_unref (aux_info);
5844       ret = GST_FLOW_ERROR;
5845       goto beach;
5846     }
5847     gst_buffer_unmap (aux_info, &map);
5848     gst_buffer_unref (aux_info);
5849   }
5850
5851   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5852       offset);
5853
5854   if (stream->use_allocator) {
5855     /* if we have a per-stream allocator, use it */
5856     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5857   }
5858
5859   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5860       size, &buf);
5861   if (G_UNLIKELY (ret != GST_FLOW_OK))
5862     goto beach;
5863
5864   if (size != sample_size) {
5865     pts += gst_util_uint64_scale_int (GST_SECOND,
5866         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5867         stream->timescale);
5868     dts +=
5869         gst_util_uint64_scale_int (GST_SECOND,
5870         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5871         stream->timescale);
5872     duration =
5873         gst_util_uint64_scale_int (GST_SECOND,
5874         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5875   }
5876
5877   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5878       dts, pts, duration, keyframe, min_time, offset);
5879
5880   if (size != sample_size) {
5881     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5882     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5883
5884     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5885         sample->timestamp +
5886         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5887     if (time_position >= segment->media_start) {
5888       /* inside the segment, update time_position, looks very familiar to
5889        * GStreamer segments, doesn't it? */
5890       stream->time_position = (time_position - segment->media_start) +
5891           segment->time;
5892     } else {
5893       /* not yet in segment, time does not yet increment. This means
5894        * that we are still prerolling keyframes to the decoder so it can
5895        * decode the first sample of the segment. */
5896       stream->time_position = segment->time;
5897     }
5898   }
5899
5900   /* combine flows */
5901   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5902   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5903    * we have no more data for the pad to push */
5904   if (ret == GST_FLOW_EOS)
5905     ret = GST_FLOW_OK;
5906
5907   stream->offset_in_sample += size;
5908   if (stream->offset_in_sample >= sample_size) {
5909     gst_qtdemux_advance_sample (qtdemux, stream);
5910   }
5911   goto beach;
5912
5913 next:
5914   gst_qtdemux_advance_sample (qtdemux, stream);
5915
5916 beach:
5917   return ret;
5918
5919   /* special cases */
5920 eos:
5921   {
5922     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5923     ret = GST_FLOW_EOS;
5924     goto beach;
5925   }
5926 eos_stream:
5927   {
5928     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5929     /* EOS will be raised if all are EOS */
5930     ret = GST_FLOW_OK;
5931     goto beach;
5932   }
5933 }
5934
5935 static void
5936 gst_qtdemux_loop (GstPad * pad)
5937 {
5938   GstQTDemux *qtdemux;
5939   guint64 cur_offset;
5940   GstFlowReturn ret;
5941
5942   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5943
5944   cur_offset = qtdemux->offset;
5945   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5946       cur_offset, qt_demux_state_string (qtdemux->state));
5947
5948   switch (qtdemux->state) {
5949     case QTDEMUX_STATE_INITIAL:
5950     case QTDEMUX_STATE_HEADER:
5951       ret = gst_qtdemux_loop_state_header (qtdemux);
5952       break;
5953     case QTDEMUX_STATE_MOVIE:
5954       ret = gst_qtdemux_loop_state_movie (qtdemux);
5955       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5956         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5957       }
5958       break;
5959     default:
5960       /* ouch */
5961       goto invalid_state;
5962   }
5963
5964   /* if something went wrong, pause */
5965   if (ret != GST_FLOW_OK)
5966     goto pause;
5967
5968 done:
5969   gst_object_unref (qtdemux);
5970   return;
5971
5972   /* ERRORS */
5973 invalid_state:
5974   {
5975     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5976         (NULL), ("streaming stopped, invalid state"));
5977     gst_pad_pause_task (pad);
5978     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5979     goto done;
5980   }
5981 pause:
5982   {
5983     const gchar *reason = gst_flow_get_name (ret);
5984
5985     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5986
5987     gst_pad_pause_task (pad);
5988
5989     /* fatal errors need special actions */
5990     /* check EOS */
5991     if (ret == GST_FLOW_EOS) {
5992       if (qtdemux->n_streams == 0) {
5993         /* we have no streams, post an error */
5994         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5995       }
5996       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5997         gint64 stop;
5998
5999         if ((stop = qtdemux->segment.stop) == -1)
6000           stop = qtdemux->segment.duration;
6001
6002         if (qtdemux->segment.rate >= 0) {
6003           GstMessage *message;
6004           GstEvent *event;
6005
6006           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6007           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6008               GST_FORMAT_TIME, stop);
6009           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6010           if (qtdemux->segment_seqnum) {
6011             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6012             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6013           }
6014           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6015           gst_qtdemux_push_event (qtdemux, event);
6016         } else {
6017           GstMessage *message;
6018           GstEvent *event;
6019
6020           /*  For Reverse Playback */
6021           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6022           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6023               GST_FORMAT_TIME, qtdemux->segment.start);
6024           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6025               qtdemux->segment.start);
6026           if (qtdemux->segment_seqnum) {
6027             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6028             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6029           }
6030           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6031           gst_qtdemux_push_event (qtdemux, event);
6032         }
6033       } else {
6034         GstEvent *event;
6035
6036         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6037         event = gst_event_new_eos ();
6038         if (qtdemux->segment_seqnum)
6039           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6040         gst_qtdemux_push_event (qtdemux, event);
6041       }
6042     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6043       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6044       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6045     }
6046     goto done;
6047   }
6048 }
6049
6050 /*
6051  * has_next_entry
6052  *
6053  * Returns if there are samples to be played.
6054  */
6055 static gboolean
6056 has_next_entry (GstQTDemux * demux)
6057 {
6058   QtDemuxStream *stream;
6059   int i;
6060
6061   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6062
6063   for (i = 0; i < demux->n_streams; i++) {
6064     stream = demux->streams[i];
6065
6066     if (stream->sample_index == -1) {
6067       stream->sample_index = 0;
6068       stream->offset_in_sample = 0;
6069     }
6070
6071     if (stream->sample_index >= stream->n_samples) {
6072       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6073       continue;
6074     }
6075     GST_DEBUG_OBJECT (demux, "Found a sample");
6076     return TRUE;
6077   }
6078
6079   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6080   return FALSE;
6081 }
6082
6083 /*
6084  * next_entry_size
6085  *
6086  * Returns the size of the first entry at the current offset.
6087  * If -1, there are none (which means EOS or empty file).
6088  */
6089 static guint64
6090 next_entry_size (GstQTDemux * demux)
6091 {
6092   QtDemuxStream *stream;
6093   int i;
6094   int smallidx = -1;
6095   guint64 smalloffs = (guint64) - 1;
6096   QtDemuxSample *sample;
6097
6098   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6099       demux->offset);
6100
6101   for (i = 0; i < demux->n_streams; i++) {
6102     stream = demux->streams[i];
6103
6104     if (stream->sample_index == -1) {
6105       stream->sample_index = 0;
6106       stream->offset_in_sample = 0;
6107     }
6108
6109     if (stream->sample_index >= stream->n_samples) {
6110       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6111       continue;
6112     }
6113
6114     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6115       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6116           stream->sample_index);
6117       return -1;
6118     }
6119
6120     sample = &stream->samples[stream->sample_index];
6121
6122     GST_LOG_OBJECT (demux,
6123         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6124         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6125         sample->offset, sample->size);
6126
6127     if (((smalloffs == -1)
6128             || (sample->offset < smalloffs)) && (sample->size)) {
6129       smallidx = i;
6130       smalloffs = sample->offset;
6131     }
6132   }
6133
6134   GST_LOG_OBJECT (demux,
6135       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6136       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6137
6138   if (smallidx == -1)
6139     return -1;
6140
6141   stream = demux->streams[smallidx];
6142   sample = &stream->samples[stream->sample_index];
6143
6144   if (sample->offset >= demux->offset) {
6145     demux->todrop = sample->offset - demux->offset;
6146     return sample->size + demux->todrop;
6147   }
6148
6149   GST_DEBUG_OBJECT (demux,
6150       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6151   return -1;
6152 }
6153
6154 static void
6155 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6156 {
6157   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6158
6159   gst_element_post_message (GST_ELEMENT_CAST (demux),
6160       gst_message_new_element (GST_OBJECT_CAST (demux),
6161           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6162 }
6163
6164 static gboolean
6165 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6166 {
6167   GstEvent *event;
6168   gboolean res = 0;
6169
6170   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6171
6172   event =
6173       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6174       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6175       GST_SEEK_TYPE_NONE, -1);
6176
6177   /* store seqnum to drop flush events, they don't need to reach downstream */
6178   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6179   res = gst_pad_push_event (demux->sinkpad, event);
6180   demux->offset_seek_seqnum = 0;
6181
6182   return res;
6183 }
6184
6185 /* check for seekable upstream, above and beyond a mere query */
6186 static void
6187 gst_qtdemux_check_seekability (GstQTDemux * demux)
6188 {
6189   GstQuery *query;
6190   gboolean seekable = FALSE;
6191   gint64 start = -1, stop = -1;
6192
6193   if (demux->upstream_size)
6194     return;
6195
6196   if (demux->upstream_format_is_time)
6197     return;
6198
6199   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6200   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6201     GST_DEBUG_OBJECT (demux, "seeking query failed");
6202     goto done;
6203   }
6204
6205   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6206
6207   /* try harder to query upstream size if we didn't get it the first time */
6208   if (seekable && stop == -1) {
6209     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6210     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6211   }
6212
6213   /* if upstream doesn't know the size, it's likely that it's not seekable in
6214    * practice even if it technically may be seekable */
6215   if (seekable && (start != 0 || stop <= start)) {
6216     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6217     seekable = FALSE;
6218   }
6219
6220 done:
6221   gst_query_unref (query);
6222
6223   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6224       G_GUINT64_FORMAT ")", seekable, start, stop);
6225   demux->upstream_seekable = seekable;
6226   demux->upstream_size = seekable ? stop : -1;
6227 }
6228
6229 static void
6230 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6231 {
6232   g_return_if_fail (bytes <= demux->todrop);
6233
6234   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6235   gst_adapter_flush (demux->adapter, bytes);
6236   demux->neededbytes -= bytes;
6237   demux->offset += bytes;
6238   demux->todrop -= bytes;
6239 }
6240
6241 static void
6242 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6243 {
6244   if (G_UNLIKELY (demux->pending_newsegment)) {
6245     gint i;
6246
6247     gst_qtdemux_push_pending_newsegment (demux);
6248     /* clear to send tags on all streams */
6249     for (i = 0; i < demux->n_streams; i++) {
6250       QtDemuxStream *stream;
6251       stream = demux->streams[i];
6252       gst_qtdemux_push_tags (demux, stream);
6253       if (CUR_STREAM (stream)->sparse) {
6254         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6255         gst_pad_push_event (stream->pad,
6256             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6257       }
6258     }
6259   }
6260 }
6261
6262 static void
6263 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6264     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6265 {
6266   GstClockTime ts, dur;
6267   GstEvent *gap;
6268
6269   ts = pos;
6270   dur =
6271       stream->segments[segment_index].duration - (pos -
6272       stream->segments[segment_index].time);
6273   gap = gst_event_new_gap (ts, dur);
6274   stream->time_position += dur;
6275
6276   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6277       "segment: %" GST_PTR_FORMAT, gap);
6278   gst_pad_push_event (stream->pad, gap);
6279 }
6280
6281 static void
6282 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6283     QtDemuxStream * stream)
6284 {
6285   gint i;
6286
6287   /* Push any initial gap segments before proceeding to the
6288    * 'real' data */
6289   for (i = 0; i < stream->n_segments; i++) {
6290     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6291
6292     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6293       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6294           stream->time_position);
6295     } else {
6296       /* Only support empty segment at the beginning followed by
6297        * one non-empty segment, this was checked when parsing the
6298        * edts atom, arriving here is unexpected */
6299       g_assert (i + 1 == stream->n_segments);
6300       break;
6301     }
6302   }
6303 }
6304
6305 static GstFlowReturn
6306 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6307 {
6308   GstQTDemux *demux;
6309
6310   demux = GST_QTDEMUX (parent);
6311
6312   GST_DEBUG_OBJECT (demux,
6313       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6314       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6315       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6316       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6317       gst_buffer_get_size (inbuf), demux->offset);
6318
6319   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6320     gboolean is_gap_input = FALSE;
6321     gint i;
6322
6323     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6324
6325     for (i = 0; i < demux->n_streams; i++) {
6326       demux->streams[i]->discont = TRUE;
6327     }
6328
6329     /* Check if we can land back on our feet in the case where upstream is
6330      * handling the seeking/pushing of samples with gaps in between (like
6331      * in the case of trick-mode DASH for example) */
6332     if (demux->upstream_format_is_time
6333         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6334       gint i;
6335       for (i = 0; i < demux->n_streams; i++) {
6336         guint32 res;
6337         GST_LOG_OBJECT (demux,
6338             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6339             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6340         res =
6341             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6342             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6343         if (res != -1) {
6344           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6345           GST_LOG_OBJECT (demux,
6346               "Checking if sample %d from stream %d is valid (offset:%"
6347               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6348               sample->offset, sample->size);
6349           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6350             GST_LOG_OBJECT (demux,
6351                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6352                 res);
6353             is_gap_input = TRUE;
6354             /* We can go back to standard playback mode */
6355             demux->state = QTDEMUX_STATE_MOVIE;
6356             /* Remember which sample this stream is at */
6357             demux->streams[i]->sample_index = res;
6358             /* Finally update all push-based values to the expected values */
6359             demux->neededbytes = demux->streams[i]->samples[res].size;
6360             demux->offset = GST_BUFFER_OFFSET (inbuf);
6361             demux->mdatleft =
6362                 demux->mdatsize - demux->offset + demux->mdatoffset;
6363             demux->todrop = 0;
6364           }
6365         }
6366       }
6367       if (!is_gap_input) {
6368         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6369         /* Reset state if it's a real discont */
6370         demux->neededbytes = 16;
6371         demux->state = QTDEMUX_STATE_INITIAL;
6372         demux->offset = GST_BUFFER_OFFSET (inbuf);
6373         gst_adapter_clear (demux->adapter);
6374       }
6375     }
6376     /* Reverse fragmented playback, need to flush all we have before
6377      * consuming a new fragment.
6378      * The samples array have the timestamps calculated by accumulating the
6379      * durations but this won't work for reverse playback of fragments as
6380      * the timestamps of a subsequent fragment should be smaller than the
6381      * previously received one. */
6382     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6383       gst_qtdemux_process_adapter (demux, TRUE);
6384       for (i = 0; i < demux->n_streams; i++)
6385         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6386     }
6387   }
6388
6389   gst_adapter_push (demux->adapter, inbuf);
6390
6391   GST_DEBUG_OBJECT (demux,
6392       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6393       demux->neededbytes, gst_adapter_available (demux->adapter));
6394
6395   return gst_qtdemux_process_adapter (demux, FALSE);
6396 }
6397
6398 static GstFlowReturn
6399 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6400 {
6401   GstFlowReturn ret = GST_FLOW_OK;
6402
6403   /* we never really mean to buffer that much */
6404   if (demux->neededbytes == -1) {
6405     goto eos;
6406   }
6407
6408   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6409       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6410
6411 #ifndef GST_DISABLE_GST_DEBUG
6412     {
6413       guint64 discont_offset, distance_from_discont;
6414
6415       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6416       distance_from_discont =
6417           gst_adapter_distance_from_discont (demux->adapter);
6418
6419       GST_DEBUG_OBJECT (demux,
6420           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6421           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6422           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6423           demux->offset, discont_offset, distance_from_discont);
6424     }
6425 #endif
6426
6427     switch (demux->state) {
6428       case QTDEMUX_STATE_INITIAL:{
6429         const guint8 *data;
6430         guint32 fourcc;
6431         guint64 size;
6432
6433         gst_qtdemux_check_seekability (demux);
6434
6435         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6436
6437         /* get fourcc/length, set neededbytes */
6438         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6439             &size, &fourcc);
6440         gst_adapter_unmap (demux->adapter);
6441         data = NULL;
6442         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6443             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6444         if (size == 0) {
6445           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6446               (_("This file is invalid and cannot be played.")),
6447               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6448                   GST_FOURCC_ARGS (fourcc)));
6449           ret = GST_FLOW_ERROR;
6450           break;
6451         }
6452         if (fourcc == FOURCC_mdat) {
6453           gint next_entry = next_entry_size (demux);
6454           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6455             /* we have the headers, start playback */
6456             demux->state = QTDEMUX_STATE_MOVIE;
6457             demux->neededbytes = next_entry;
6458             demux->mdatleft = size;
6459             demux->mdatsize = demux->mdatleft;
6460           } else {
6461             /* no headers yet, try to get them */
6462             guint bs;
6463             gboolean res;
6464             guint64 old, target;
6465
6466           buffer_data:
6467             old = demux->offset;
6468             target = old + size;
6469
6470             /* try to jump over the atom with a seek */
6471             /* only bother if it seems worth doing so,
6472              * and avoids possible upstream/server problems */
6473             if (demux->upstream_seekable &&
6474                 demux->upstream_size > 4 * (1 << 20)) {
6475               res = qtdemux_seek_offset (demux, target);
6476             } else {
6477               GST_DEBUG_OBJECT (demux, "skipping seek");
6478               res = FALSE;
6479             }
6480
6481             if (res) {
6482               GST_DEBUG_OBJECT (demux, "seek success");
6483               /* remember the offset fo the first mdat so we can seek back to it
6484                * after we have the headers */
6485               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6486                 demux->first_mdat = old;
6487                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6488                     demux->first_mdat);
6489               }
6490               /* seek worked, continue reading */
6491               demux->offset = target;
6492               demux->neededbytes = 16;
6493               demux->state = QTDEMUX_STATE_INITIAL;
6494             } else {
6495               /* seek failed, need to buffer */
6496               demux->offset = old;
6497               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6498               /* there may be multiple mdat (or alike) buffers */
6499               /* sanity check */
6500               if (demux->mdatbuffer)
6501                 bs = gst_buffer_get_size (demux->mdatbuffer);
6502               else
6503                 bs = 0;
6504               if (size + bs > 10 * (1 << 20))
6505                 goto no_moov;
6506               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6507               demux->neededbytes = size;
6508               if (!demux->mdatbuffer)
6509                 demux->mdatoffset = demux->offset;
6510             }
6511           }
6512         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6513           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6514               (_("This file is invalid and cannot be played.")),
6515               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6516                   GST_FOURCC_ARGS (fourcc), size));
6517           ret = GST_FLOW_ERROR;
6518           break;
6519         } else {
6520           /* this means we already started buffering and still no moov header,
6521            * let's continue buffering everything till we get moov */
6522           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6523                   || fourcc == FOURCC_moof))
6524             goto buffer_data;
6525           demux->neededbytes = size;
6526           demux->state = QTDEMUX_STATE_HEADER;
6527         }
6528         break;
6529       }
6530       case QTDEMUX_STATE_HEADER:{
6531         const guint8 *data;
6532         guint32 fourcc;
6533
6534         GST_DEBUG_OBJECT (demux, "In header");
6535
6536         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6537
6538         /* parse the header */
6539         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6540             &fourcc);
6541         if (fourcc == FOURCC_moov) {
6542           gint n;
6543
6544           /* in usual fragmented setup we could try to scan for more
6545            * and end up at the the moov (after mdat) again */
6546           if (demux->got_moov && demux->n_streams > 0 &&
6547               (!demux->fragmented
6548                   || demux->last_moov_offset == demux->offset)) {
6549             GST_DEBUG_OBJECT (demux,
6550                 "Skipping moov atom as we have (this) one already");
6551           } else {
6552             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6553
6554             if (demux->got_moov && demux->fragmented) {
6555               GST_DEBUG_OBJECT (demux,
6556                   "Got a second moov, clean up data from old one");
6557               if (demux->moov_node_compressed) {
6558                 g_node_destroy (demux->moov_node_compressed);
6559                 if (demux->moov_node)
6560                   g_free (demux->moov_node->data);
6561               }
6562               demux->moov_node_compressed = NULL;
6563               if (demux->moov_node)
6564                 g_node_destroy (demux->moov_node);
6565               demux->moov_node = NULL;
6566             } else {
6567               /* prepare newsegment to send when streaming actually starts */
6568               if (!demux->pending_newsegment) {
6569                 demux->pending_newsegment =
6570                     gst_event_new_segment (&demux->segment);
6571                 if (demux->segment_seqnum)
6572                   gst_event_set_seqnum (demux->pending_newsegment,
6573                       demux->segment_seqnum);
6574               }
6575             }
6576
6577             demux->last_moov_offset = demux->offset;
6578
6579             qtdemux_parse_moov (demux, data, demux->neededbytes);
6580             qtdemux_node_dump (demux, demux->moov_node);
6581             qtdemux_parse_tree (demux);
6582             qtdemux_prepare_streams (demux);
6583             if (!demux->got_moov)
6584               qtdemux_expose_streams (demux);
6585             else {
6586
6587               for (n = 0; n < demux->n_streams; n++) {
6588                 QtDemuxStream *stream = demux->streams[n];
6589
6590                 gst_qtdemux_configure_stream (demux, stream);
6591               }
6592             }
6593
6594             demux->got_moov = TRUE;
6595             gst_qtdemux_check_send_pending_segment (demux);
6596
6597             /* fragmented streams headers shouldn't contain edts atoms */
6598             if (!demux->fragmented) {
6599               for (n = 0; n < demux->n_streams; n++) {
6600                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6601                     demux->streams[n]);
6602               }
6603             }
6604
6605             if (demux->moov_node_compressed) {
6606               g_node_destroy (demux->moov_node_compressed);
6607               g_free (demux->moov_node->data);
6608             }
6609             demux->moov_node_compressed = NULL;
6610             g_node_destroy (demux->moov_node);
6611             demux->moov_node = NULL;
6612             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6613           }
6614         } else if (fourcc == FOURCC_moof) {
6615           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6616             guint64 dist = 0;
6617             GstClockTime prev_pts;
6618             guint64 prev_offset;
6619             guint64 adapter_discont_offset, adapter_discont_dist;
6620
6621             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6622
6623             /*
6624              * The timestamp of the moof buffer is relevant as some scenarios
6625              * won't have the initial timestamp in the atoms. Whenever a new
6626              * buffer has started, we get that buffer's PTS and use it as a base
6627              * timestamp for the trun entries.
6628              *
6629              * To keep track of the current buffer timestamp and starting point
6630              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6631              * from the beggining of the buffer, with the distance and demux->offset
6632              * we know if it is still the same buffer or not.
6633              */
6634             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6635             prev_offset = demux->offset - dist;
6636             if (demux->fragment_start_offset == -1
6637                 || prev_offset > demux->fragment_start_offset) {
6638               demux->fragment_start_offset = prev_offset;
6639               demux->fragment_start = prev_pts;
6640               GST_DEBUG_OBJECT (demux,
6641                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6642                   GST_TIME_FORMAT, demux->fragment_start_offset,
6643                   GST_TIME_ARGS (demux->fragment_start));
6644             }
6645
6646             /* We can't use prev_offset() here because this would require
6647              * upstream to set consistent and correct offsets on all buffers
6648              * since the discont. Nothing ever did that in the past and we
6649              * would break backwards compatibility here then.
6650              * Instead take the offset we had at the last discont and count
6651              * the bytes from there. This works with old code as there would
6652              * be no discont between moov and moof, and also works with
6653              * adaptivedemux which correctly sets offset and will set the
6654              * DISCONT flag accordingly when needed.
6655              *
6656              * We also only do this for upstream TIME segments as otherwise
6657              * there are potential backwards compatibility problems with
6658              * seeking in PUSH mode and upstream providing inconsistent
6659              * timestamps. */
6660             adapter_discont_offset =
6661                 gst_adapter_offset_at_discont (demux->adapter);
6662             adapter_discont_dist =
6663                 gst_adapter_distance_from_discont (demux->adapter);
6664
6665             GST_DEBUG_OBJECT (demux,
6666                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6667                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6668                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6669
6670             if (demux->upstream_format_is_time) {
6671               demux->moof_offset = adapter_discont_offset;
6672               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6673                 demux->moof_offset += adapter_discont_dist;
6674               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6675                 demux->moof_offset = demux->offset;
6676             } else {
6677               demux->moof_offset = demux->offset;
6678             }
6679
6680             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6681                     demux->moof_offset, NULL)) {
6682               gst_adapter_unmap (demux->adapter);
6683               ret = GST_FLOW_ERROR;
6684               goto done;
6685             }
6686             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6687             if (demux->mss_mode && !demux->exposed) {
6688               if (!demux->pending_newsegment) {
6689                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6690                 demux->pending_newsegment =
6691                     gst_event_new_segment (&demux->segment);
6692                 if (demux->segment_seqnum)
6693                   gst_event_set_seqnum (demux->pending_newsegment,
6694                       demux->segment_seqnum);
6695               }
6696               qtdemux_expose_streams (demux);
6697             }
6698           } else {
6699             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6700           }
6701         } else if (fourcc == FOURCC_ftyp) {
6702           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6703           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6704         } else if (fourcc == FOURCC_uuid) {
6705           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6706           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6707         } else if (fourcc == FOURCC_sidx) {
6708           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6709           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6710         } else {
6711           switch (fourcc) {
6712             case FOURCC_styp:
6713               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6714                * FALLTHROUGH */
6715             case FOURCC_skip:
6716             case FOURCC_free:
6717               /* [free] and [skip] are padding atoms */
6718               GST_DEBUG_OBJECT (demux,
6719                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6720                   GST_FOURCC_ARGS (fourcc));
6721               break;
6722             default:
6723               GST_WARNING_OBJECT (demux,
6724                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6725                   GST_FOURCC_ARGS (fourcc));
6726               /* Let's jump that one and go back to initial state */
6727               break;
6728           }
6729         }
6730         gst_adapter_unmap (demux->adapter);
6731         data = NULL;
6732
6733         if (demux->mdatbuffer && demux->n_streams) {
6734           gsize remaining_data_size = 0;
6735
6736           /* the mdat was before the header */
6737           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6738               demux->n_streams, demux->mdatbuffer);
6739           /* restore our adapter/offset view of things with upstream;
6740            * put preceding buffered data ahead of current moov data.
6741            * This should also handle evil mdat, moov, mdat cases and alike */
6742           gst_adapter_flush (demux->adapter, demux->neededbytes);
6743
6744           /* Store any remaining data after the mdat for later usage */
6745           remaining_data_size = gst_adapter_available (demux->adapter);
6746           if (remaining_data_size > 0) {
6747             g_assert (demux->restoredata_buffer == NULL);
6748             demux->restoredata_buffer =
6749                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6750             demux->restoredata_offset = demux->offset + demux->neededbytes;
6751             GST_DEBUG_OBJECT (demux,
6752                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6753                 G_GUINT64_FORMAT, remaining_data_size,
6754                 demux->restoredata_offset);
6755           }
6756
6757           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6758           demux->mdatbuffer = NULL;
6759           demux->offset = demux->mdatoffset;
6760           demux->neededbytes = next_entry_size (demux);
6761           demux->state = QTDEMUX_STATE_MOVIE;
6762           demux->mdatleft = gst_adapter_available (demux->adapter);
6763           demux->mdatsize = demux->mdatleft;
6764         } else {
6765           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6766           gst_adapter_flush (demux->adapter, demux->neededbytes);
6767
6768           /* only go back to the mdat if there are samples to play */
6769           if (demux->got_moov && demux->first_mdat != -1
6770               && has_next_entry (demux)) {
6771             gboolean res;
6772
6773             /* we need to seek back */
6774             res = qtdemux_seek_offset (demux, demux->first_mdat);
6775             if (res) {
6776               demux->offset = demux->first_mdat;
6777             } else {
6778               GST_DEBUG_OBJECT (demux, "Seek back failed");
6779             }
6780           } else {
6781             demux->offset += demux->neededbytes;
6782           }
6783           demux->neededbytes = 16;
6784           demux->state = QTDEMUX_STATE_INITIAL;
6785         }
6786
6787         break;
6788       }
6789       case QTDEMUX_STATE_BUFFER_MDAT:{
6790         GstBuffer *buf;
6791         guint8 fourcc[4];
6792
6793         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6794             demux->offset);
6795         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6796         gst_buffer_extract (buf, 0, fourcc, 4);
6797         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6798             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6799         if (demux->mdatbuffer)
6800           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6801         else
6802           demux->mdatbuffer = buf;
6803         demux->offset += demux->neededbytes;
6804         demux->neededbytes = 16;
6805         demux->state = QTDEMUX_STATE_INITIAL;
6806         gst_qtdemux_post_progress (demux, 1, 1);
6807
6808         break;
6809       }
6810       case QTDEMUX_STATE_MOVIE:{
6811         QtDemuxStream *stream = NULL;
6812         QtDemuxSample *sample;
6813         int i = -1;
6814         GstClockTime dts, pts, duration;
6815         gboolean keyframe;
6816
6817         GST_DEBUG_OBJECT (demux,
6818             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6819
6820         if (demux->fragmented) {
6821           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6822               demux->mdatleft);
6823           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6824             /* if needed data starts within this atom,
6825              * then it should not exceed this atom */
6826             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6827               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6828                   (_("This file is invalid and cannot be played.")),
6829                   ("sample data crosses atom boundary"));
6830               ret = GST_FLOW_ERROR;
6831               break;
6832             }
6833             demux->mdatleft -= demux->neededbytes;
6834           } else {
6835             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6836             /* so we are dropping more than left in this atom */
6837             gst_qtdemux_drop_data (demux, demux->mdatleft);
6838             demux->mdatleft = 0;
6839
6840             /* need to resume atom parsing so we do not miss any other pieces */
6841             demux->state = QTDEMUX_STATE_INITIAL;
6842             demux->neededbytes = 16;
6843
6844             /* check if there was any stored post mdat data from previous buffers */
6845             if (demux->restoredata_buffer) {
6846               g_assert (gst_adapter_available (demux->adapter) == 0);
6847
6848               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6849               demux->restoredata_buffer = NULL;
6850               demux->offset = demux->restoredata_offset;
6851             }
6852
6853             break;
6854           }
6855         }
6856
6857         if (demux->todrop) {
6858           if (demux->cenc_aux_info_offset > 0) {
6859             GstByteReader br;
6860             const guint8 *data;
6861
6862             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6863             data = gst_adapter_map (demux->adapter, demux->todrop);
6864             gst_byte_reader_init (&br, data + 8, demux->todrop);
6865             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6866                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6867               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6868               ret = GST_FLOW_ERROR;
6869               gst_adapter_unmap (demux->adapter);
6870               g_free (demux->cenc_aux_info_sizes);
6871               demux->cenc_aux_info_sizes = NULL;
6872               goto done;
6873             }
6874             demux->cenc_aux_info_offset = 0;
6875             g_free (demux->cenc_aux_info_sizes);
6876             demux->cenc_aux_info_sizes = NULL;
6877             gst_adapter_unmap (demux->adapter);
6878           }
6879           gst_qtdemux_drop_data (demux, demux->todrop);
6880         }
6881
6882         /* first buffer? */
6883         /* initial newsegment sent here after having added pads,
6884          * possible others in sink_event */
6885         gst_qtdemux_check_send_pending_segment (demux);
6886
6887         /* Figure out which stream this packet belongs to */
6888         for (i = 0; i < demux->n_streams; i++) {
6889           stream = demux->streams[i];
6890           if (stream->sample_index >= stream->n_samples)
6891             continue;
6892           GST_LOG_OBJECT (demux,
6893               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6894               " / size:%d)", i, stream->sample_index,
6895               stream->samples[stream->sample_index].offset,
6896               stream->samples[stream->sample_index].size);
6897
6898           if (stream->samples[stream->sample_index].offset == demux->offset)
6899             break;
6900         }
6901
6902         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6903           goto unknown_stream;
6904
6905         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6906
6907         if (stream->new_caps) {
6908           gst_qtdemux_configure_stream (demux, stream);
6909         }
6910
6911         /* Put data in a buffer, set timestamps, caps, ... */
6912         sample = &stream->samples[stream->sample_index];
6913
6914         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6915           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6916               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6917
6918           dts = QTSAMPLE_DTS (stream, sample);
6919           pts = QTSAMPLE_PTS (stream, sample);
6920           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6921           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6922
6923           /* check for segment end */
6924           if (G_UNLIKELY (demux->segment.stop != -1
6925                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6926             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6927             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6928
6929             /* skip this data, stream is EOS */
6930             gst_adapter_flush (demux->adapter, demux->neededbytes);
6931             demux->offset += demux->neededbytes;
6932
6933             /* check if all streams are eos */
6934             ret = GST_FLOW_EOS;
6935             for (i = 0; i < demux->n_streams; i++) {
6936               if (!STREAM_IS_EOS (demux->streams[i])) {
6937                 ret = GST_FLOW_OK;
6938                 break;
6939               }
6940             }
6941           } else {
6942             GstBuffer *outbuf;
6943
6944             outbuf =
6945                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6946
6947             /* FIXME: should either be an assert or a plain check */
6948             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6949
6950             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6951                 dts, pts, duration, keyframe, dts, demux->offset);
6952           }
6953
6954           /* combine flows */
6955           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6956         } else {
6957           /* skip this data, stream is EOS */
6958           gst_adapter_flush (demux->adapter, demux->neededbytes);
6959         }
6960
6961         stream->sample_index++;
6962         stream->offset_in_sample = 0;
6963
6964         /* update current offset and figure out size of next buffer */
6965         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6966             demux->offset, demux->neededbytes);
6967         demux->offset += demux->neededbytes;
6968         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6969             demux->offset);
6970
6971
6972         if (ret == GST_FLOW_EOS) {
6973           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6974           demux->neededbytes = -1;
6975           goto eos;
6976         }
6977
6978         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6979           if (demux->fragmented) {
6980             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6981             /* there may be more to follow, only finish this atom */
6982             demux->todrop = demux->mdatleft;
6983             demux->neededbytes = demux->todrop;
6984             break;
6985           }
6986           goto eos;
6987         }
6988         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
6989           goto non_ok_unlinked_flow;
6990         }
6991         break;
6992       }
6993       default:
6994         goto invalid_state;
6995     }
6996   }
6997
6998   /* when buffering movie data, at least show user something is happening */
6999   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7000       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7001     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7002         demux->neededbytes);
7003   }
7004 done:
7005
7006   return ret;
7007
7008   /* ERRORS */
7009 non_ok_unlinked_flow:
7010   {
7011     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7012         gst_flow_get_name (ret));
7013     return ret;
7014   }
7015 unknown_stream:
7016   {
7017     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7018     ret = GST_FLOW_ERROR;
7019     goto done;
7020   }
7021 eos:
7022   {
7023     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7024     ret = GST_FLOW_EOS;
7025     goto done;
7026   }
7027 invalid_state:
7028   {
7029     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7030         (NULL), ("qtdemuxer invalid state %d", demux->state));
7031     ret = GST_FLOW_ERROR;
7032     goto done;
7033   }
7034 no_moov:
7035   {
7036     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7037         (NULL), ("no 'moov' atom within the first 10 MB"));
7038     ret = GST_FLOW_ERROR;
7039     goto done;
7040   }
7041 }
7042
7043 static gboolean
7044 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7045 {
7046   GstQuery *query;
7047   gboolean pull_mode;
7048
7049   query = gst_query_new_scheduling ();
7050
7051   if (!gst_pad_peer_query (sinkpad, query)) {
7052     gst_query_unref (query);
7053     goto activate_push;
7054   }
7055
7056   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7057       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7058   gst_query_unref (query);
7059
7060   if (!pull_mode)
7061     goto activate_push;
7062
7063   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7064   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7065
7066 activate_push:
7067   {
7068     GST_DEBUG_OBJECT (sinkpad, "activating push");
7069     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7070   }
7071 }
7072
7073 static gboolean
7074 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7075     GstPadMode mode, gboolean active)
7076 {
7077   gboolean res;
7078   GstQTDemux *demux = GST_QTDEMUX (parent);
7079
7080   switch (mode) {
7081     case GST_PAD_MODE_PUSH:
7082       demux->pullbased = FALSE;
7083       res = TRUE;
7084       break;
7085     case GST_PAD_MODE_PULL:
7086       if (active) {
7087         demux->pullbased = TRUE;
7088         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7089             sinkpad, NULL);
7090       } else {
7091         res = gst_pad_stop_task (sinkpad);
7092       }
7093       break;
7094     default:
7095       res = FALSE;
7096       break;
7097   }
7098   return res;
7099 }
7100
7101 #ifdef HAVE_ZLIB
7102 static void *
7103 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7104 {
7105   guint8 *buffer;
7106   z_stream z;
7107   int ret;
7108
7109   memset (&z, 0, sizeof (z));
7110   z.zalloc = NULL;
7111   z.zfree = NULL;
7112   z.opaque = NULL;
7113
7114   if ((ret = inflateInit (&z)) != Z_OK) {
7115     GST_ERROR ("inflateInit() returned %d", ret);
7116     return NULL;
7117   }
7118
7119   z.next_in = z_buffer;
7120   z.avail_in = z_length;
7121
7122   buffer = (guint8 *) g_malloc (*length);
7123   z.avail_out = *length;
7124   z.next_out = (Bytef *) buffer;
7125   do {
7126     ret = inflate (&z, Z_NO_FLUSH);
7127     if (ret == Z_STREAM_END) {
7128       break;
7129     } else if (ret != Z_OK) {
7130       GST_WARNING ("inflate() returned %d", ret);
7131       break;
7132     }
7133
7134     *length += 4096;
7135     buffer = (guint8 *) g_realloc (buffer, *length);
7136     z.next_out = (Bytef *) (buffer + z.total_out);
7137     z.avail_out += 4096;
7138   } while (z.avail_in > 0);
7139
7140   if (ret != Z_STREAM_END) {
7141     g_free (buffer);
7142     buffer = NULL;
7143     *length = 0;
7144   } else {
7145     *length = z.total_out;
7146   }
7147
7148   inflateEnd (&z);
7149
7150   return buffer;
7151 }
7152 #endif /* HAVE_ZLIB */
7153
7154 static gboolean
7155 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7156 {
7157   GNode *cmov;
7158
7159   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7160
7161   /* counts as header data */
7162   qtdemux->header_size += length;
7163
7164   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7165   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7166
7167   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7168   if (cmov) {
7169     guint32 method;
7170     GNode *dcom;
7171     GNode *cmvd;
7172     guint32 dcom_len;
7173
7174     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7175     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7176     if (dcom == NULL || cmvd == NULL)
7177       goto invalid_compression;
7178
7179     dcom_len = QT_UINT32 (dcom->data);
7180     if (dcom_len < 12)
7181       goto invalid_compression;
7182
7183     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7184     switch (method) {
7185 #ifdef HAVE_ZLIB
7186       case FOURCC_zlib:{
7187         guint uncompressed_length;
7188         guint compressed_length;
7189         guint8 *buf;
7190         guint32 cmvd_len;
7191
7192         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7193         if (cmvd_len < 12)
7194           goto invalid_compression;
7195
7196         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7197         compressed_length = cmvd_len - 12;
7198         GST_LOG ("length = %u", uncompressed_length);
7199
7200         buf =
7201             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7202             compressed_length, &uncompressed_length);
7203
7204         if (buf) {
7205           qtdemux->moov_node_compressed = qtdemux->moov_node;
7206           qtdemux->moov_node = g_node_new (buf);
7207
7208           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7209               uncompressed_length);
7210         }
7211         break;
7212       }
7213 #endif /* HAVE_ZLIB */
7214       default:
7215         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7216             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7217         break;
7218     }
7219   }
7220   return TRUE;
7221
7222   /* ERRORS */
7223 invalid_compression:
7224   {
7225     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7226     return FALSE;
7227   }
7228 }
7229
7230 static gboolean
7231 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7232     const guint8 * end)
7233 {
7234   while (G_UNLIKELY (buf < end)) {
7235     GNode *child;
7236     guint32 len;
7237
7238     if (G_UNLIKELY (buf + 4 > end)) {
7239       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7240       break;
7241     }
7242     len = QT_UINT32 (buf);
7243     if (G_UNLIKELY (len == 0)) {
7244       GST_LOG_OBJECT (qtdemux, "empty container");
7245       break;
7246     }
7247     if (G_UNLIKELY (len < 8)) {
7248       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7249       break;
7250     }
7251     if (G_UNLIKELY (len > (end - buf))) {
7252       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7253           (gint) (end - buf));
7254       break;
7255     }
7256
7257     child = g_node_new ((guint8 *) buf);
7258     g_node_append (node, child);
7259     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7260     qtdemux_parse_node (qtdemux, child, buf, len);
7261
7262     buf += len;
7263   }
7264   return TRUE;
7265 }
7266
7267 static gboolean
7268 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7269     GNode * xdxt)
7270 {
7271   int len = QT_UINT32 (xdxt->data);
7272   guint8 *buf = xdxt->data;
7273   guint8 *end = buf + len;
7274   GstBuffer *buffer;
7275
7276   /* skip size and type */
7277   buf += 8;
7278   end -= 8;
7279
7280   while (buf < end) {
7281     gint size;
7282     guint32 type;
7283
7284     size = QT_UINT32 (buf);
7285     type = QT_FOURCC (buf + 4);
7286
7287     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7288
7289     if (buf + size > end || size <= 0)
7290       break;
7291
7292     buf += 8;
7293     size -= 8;
7294
7295     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7296         GST_FOURCC_ARGS (type));
7297
7298     switch (type) {
7299       case FOURCC_tCtH:
7300         buffer = gst_buffer_new_and_alloc (size);
7301         gst_buffer_fill (buffer, 0, buf, size);
7302         stream->buffers = g_slist_append (stream->buffers, buffer);
7303         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7304         break;
7305       case FOURCC_tCt_:
7306         buffer = gst_buffer_new_and_alloc (size);
7307         gst_buffer_fill (buffer, 0, buf, size);
7308         stream->buffers = g_slist_append (stream->buffers, buffer);
7309         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7310         break;
7311       case FOURCC_tCtC:
7312         buffer = gst_buffer_new_and_alloc (size);
7313         gst_buffer_fill (buffer, 0, buf, size);
7314         stream->buffers = g_slist_append (stream->buffers, buffer);
7315         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7316         break;
7317       default:
7318         GST_WARNING_OBJECT (qtdemux,
7319             "unknown theora cookie %" GST_FOURCC_FORMAT,
7320             GST_FOURCC_ARGS (type));
7321         break;
7322     }
7323     buf += size;
7324   }
7325   return TRUE;
7326 }
7327
7328 static gboolean
7329 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7330     guint length)
7331 {
7332   guint32 fourcc = 0;
7333   guint32 node_length = 0;
7334   const QtNodeType *type;
7335   const guint8 *end;
7336
7337   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7338
7339   if (G_UNLIKELY (length < 8))
7340     goto not_enough_data;
7341
7342   node_length = QT_UINT32 (buffer);
7343   fourcc = QT_FOURCC (buffer + 4);
7344
7345   /* ignore empty nodes */
7346   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7347     return TRUE;
7348
7349   type = qtdemux_type_get (fourcc);
7350
7351   end = buffer + length;
7352
7353   GST_LOG_OBJECT (qtdemux,
7354       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7355       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7356
7357   if (node_length > length)
7358     goto broken_atom_size;
7359
7360   if (type->flags & QT_FLAG_CONTAINER) {
7361     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7362   } else {
7363     switch (fourcc) {
7364       case FOURCC_stsd:
7365       {
7366         if (node_length < 20) {
7367           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7368           break;
7369         }
7370         GST_DEBUG_OBJECT (qtdemux,
7371             "parsing stsd (sample table, sample description) atom");
7372         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7373         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7374         break;
7375       }
7376       case FOURCC_mp4a:
7377       case FOURCC_alac:
7378       case FOURCC_fLaC:
7379       {
7380         guint32 version;
7381         guint32 offset;
7382         guint min_size;
7383
7384         /* also read alac (or whatever) in stead of mp4a in the following,
7385          * since a similar layout is used in other cases as well */
7386         if (fourcc == FOURCC_mp4a)
7387           min_size = 20;
7388         else if (fourcc == FOURCC_fLaC)
7389           min_size = 86;
7390         else
7391           min_size = 40;
7392
7393         /* There are two things we might encounter here: a true mp4a atom, and
7394            an mp4a entry in an stsd atom. The latter is what we're interested
7395            in, and it looks like an atom, but isn't really one. The true mp4a
7396            atom is short, so we detect it based on length here. */
7397         if (length < min_size) {
7398           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7399               GST_FOURCC_ARGS (fourcc));
7400           break;
7401         }
7402
7403         /* 'version' here is the sound sample description version. Types 0 and
7404            1 are documented in the QTFF reference, but type 2 is not: it's
7405            described in Apple header files instead (struct SoundDescriptionV2
7406            in Movies.h) */
7407         version = QT_UINT16 (buffer + 16);
7408
7409         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7410             GST_FOURCC_ARGS (fourcc), version);
7411
7412         /* parse any esds descriptors */
7413         switch (version) {
7414           case 0:
7415             offset = 0x24;
7416             break;
7417           case 1:
7418             offset = 0x34;
7419             break;
7420           case 2:
7421             offset = 0x48;
7422             break;
7423           default:
7424             GST_WARNING_OBJECT (qtdemux,
7425                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7426                 GST_FOURCC_ARGS (fourcc), version);
7427             offset = 0;
7428             break;
7429         }
7430         if (offset)
7431           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7432         break;
7433       }
7434       case FOURCC_mp4v:
7435       case FOURCC_MP4V:
7436       case FOURCC_fmp4:
7437       case FOURCC_FMP4:
7438       case FOURCC_apcs:
7439       case FOURCC_apch:
7440       case FOURCC_apcn:
7441       case FOURCC_apco:
7442       case FOURCC_ap4h:
7443       case FOURCC_xvid:
7444       case FOURCC_XVID:
7445       case FOURCC_H264:
7446       case FOURCC_avc1:
7447       case FOURCC_avc3:
7448       case FOURCC_H265:
7449       case FOURCC_hvc1:
7450       case FOURCC_hev1:
7451       case FOURCC_mjp2:
7452       case FOURCC_encv:
7453       {
7454         guint32 version;
7455         guint32 str_len;
7456
7457         /* codec_data is contained inside these atoms, which all have
7458          * the same format. */
7459         /* video sample description size is 86 bytes without extension.
7460          * node_length have to be bigger than 86 bytes because video sample
7461          * description can include extenstions such as esds, fiel, glbl, etc. */
7462         if (node_length < 86) {
7463           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7464               " sample description length too short (%u < 86)",
7465               GST_FOURCC_ARGS (fourcc), node_length);
7466           break;
7467         }
7468
7469         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7470             GST_FOURCC_ARGS (fourcc));
7471
7472         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7473          *              its data format.
7474          * revision level (2 bytes) : must be set to 0. */
7475         version = QT_UINT32 (buffer + 16);
7476         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7477
7478         /* compressor name : PASCAL string and informative purposes
7479          * first byte : the number of bytes to be displayed.
7480          *              it has to be less than 32 because it is reserved
7481          *              space of 32 bytes total including itself. */
7482         str_len = QT_UINT8 (buffer + 50);
7483         if (str_len < 32)
7484           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7485               (char *) buffer + 51);
7486         else
7487           GST_WARNING_OBJECT (qtdemux,
7488               "compressorname length too big (%u > 31)", str_len);
7489
7490         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7491             end - buffer);
7492         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7493         break;
7494       }
7495       case FOURCC_meta:
7496       {
7497         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7498         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7499         break;
7500       }
7501       case FOURCC_mp4s:
7502       {
7503         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7504         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7505         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7506         break;
7507       }
7508       case FOURCC_XiTh:
7509       {
7510         guint32 version;
7511         guint32 offset;
7512
7513         if (length < 16) {
7514           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7515               GST_FOURCC_ARGS (fourcc));
7516           break;
7517         }
7518
7519         version = QT_UINT32 (buffer + 12);
7520         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7521
7522         switch (version) {
7523           case 0x00000001:
7524             offset = 0x62;
7525             break;
7526           default:
7527             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7528             offset = 0;
7529             break;
7530         }
7531         if (offset) {
7532           if (length < offset) {
7533             GST_WARNING_OBJECT (qtdemux,
7534                 "skipping too small %" GST_FOURCC_FORMAT " box",
7535                 GST_FOURCC_ARGS (fourcc));
7536             break;
7537           }
7538           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7539         }
7540         break;
7541       }
7542       case FOURCC_in24:
7543       {
7544         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7545         break;
7546       }
7547       case FOURCC_uuid:
7548       {
7549         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7550         break;
7551       }
7552       case FOURCC_enca:
7553       {
7554         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7555         break;
7556       }
7557       default:
7558         if (!strcmp (type->name, "unknown"))
7559           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7560         break;
7561     }
7562   }
7563   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7564       GST_FOURCC_ARGS (fourcc));
7565   return TRUE;
7566
7567 /* ERRORS */
7568 not_enough_data:
7569   {
7570     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7571         (_("This file is corrupt and cannot be played.")),
7572         ("Not enough data for an atom header, got only %u bytes", length));
7573     return FALSE;
7574   }
7575 broken_atom_size:
7576   {
7577     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7578         (_("This file is corrupt and cannot be played.")),
7579         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7580             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7581             length));
7582     return FALSE;
7583   }
7584 }
7585
7586 static GNode *
7587 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7588 {
7589   GNode *child;
7590   guint8 *buffer;
7591   guint32 child_fourcc;
7592
7593   for (child = g_node_first_child (node); child;
7594       child = g_node_next_sibling (child)) {
7595     buffer = (guint8 *) child->data;
7596
7597     child_fourcc = QT_FOURCC (buffer + 4);
7598
7599     if (G_UNLIKELY (child_fourcc == fourcc)) {
7600       return child;
7601     }
7602   }
7603   return NULL;
7604 }
7605
7606 static GNode *
7607 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7608     GstByteReader * parser)
7609 {
7610   GNode *child;
7611   guint8 *buffer;
7612   guint32 child_fourcc, child_len;
7613
7614   for (child = g_node_first_child (node); child;
7615       child = g_node_next_sibling (child)) {
7616     buffer = (guint8 *) child->data;
7617
7618     child_len = QT_UINT32 (buffer);
7619     child_fourcc = QT_FOURCC (buffer + 4);
7620
7621     if (G_UNLIKELY (child_fourcc == fourcc)) {
7622       if (G_UNLIKELY (child_len < (4 + 4)))
7623         return NULL;
7624       /* FIXME: must verify if atom length < parent atom length */
7625       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7626       return child;
7627     }
7628   }
7629   return NULL;
7630 }
7631
7632 static GNode *
7633 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7634 {
7635   return g_node_nth_child (node, index);
7636 }
7637
7638 static GNode *
7639 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7640     GstByteReader * parser)
7641 {
7642   GNode *child;
7643   guint8 *buffer;
7644   guint32 child_fourcc, child_len;
7645
7646   for (child = g_node_next_sibling (node); child;
7647       child = g_node_next_sibling (child)) {
7648     buffer = (guint8 *) child->data;
7649
7650     child_fourcc = QT_FOURCC (buffer + 4);
7651
7652     if (child_fourcc == fourcc) {
7653       if (parser) {
7654         child_len = QT_UINT32 (buffer);
7655         if (G_UNLIKELY (child_len < (4 + 4)))
7656           return NULL;
7657         /* FIXME: must verify if atom length < parent atom length */
7658         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7659       }
7660       return child;
7661     }
7662   }
7663   return NULL;
7664 }
7665
7666 static GNode *
7667 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7668 {
7669   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7670 }
7671
7672 static void
7673 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7674 {
7675 /* FIXME: This can only reliably work if demuxers have a
7676  * separate streaming thread per srcpad. This should be
7677  * done in a demuxer base class, which integrates parts
7678  * of multiqueue
7679  *
7680  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7681  */
7682 #if 0
7683   GstQuery *query;
7684
7685   query = gst_query_new_allocation (stream->caps, FALSE);
7686
7687   if (!gst_pad_peer_query (stream->pad, query)) {
7688     /* not a problem, just debug a little */
7689     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7690   }
7691
7692   if (stream->allocator)
7693     gst_object_unref (stream->allocator);
7694
7695   if (gst_query_get_n_allocation_params (query) > 0) {
7696     /* try the allocator */
7697     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7698         &stream->params);
7699     stream->use_allocator = TRUE;
7700   } else {
7701     stream->allocator = NULL;
7702     gst_allocation_params_init (&stream->params);
7703     stream->use_allocator = FALSE;
7704   }
7705   gst_query_unref (query);
7706 #endif
7707 }
7708
7709 static gboolean
7710 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7711     QtDemuxStream * stream)
7712 {
7713   GstStructure *s;
7714   const gchar *selected_system;
7715
7716   g_return_val_if_fail (qtdemux != NULL, FALSE);
7717   g_return_val_if_fail (stream != NULL, FALSE);
7718   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7719       FALSE);
7720
7721   if (stream->protection_scheme_type != FOURCC_cenc) {
7722     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7723     return FALSE;
7724   }
7725   if (qtdemux->protection_system_ids == NULL) {
7726     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7727         "cenc protection system information has been found");
7728     return FALSE;
7729   }
7730   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7731   selected_system = gst_protection_select_system ((const gchar **)
7732       qtdemux->protection_system_ids->pdata);
7733   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7734       qtdemux->protection_system_ids->len - 1);
7735   if (!selected_system) {
7736     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7737         "suitable decryptor element has been found");
7738     return FALSE;
7739   }
7740
7741   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7742   if (!gst_structure_has_name (s, "application/x-cenc")) {
7743     gst_structure_set (s,
7744         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7745         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7746         NULL);
7747     gst_structure_set_name (s, "application/x-cenc");
7748   }
7749   return TRUE;
7750 }
7751
7752 static gboolean
7753 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7754 {
7755   if (stream->subtype == FOURCC_vide) {
7756     /* fps is calculated base on the duration of the average framerate since
7757      * qt does not have a fixed framerate. */
7758     gboolean fps_available = TRUE;
7759
7760     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7761       /* still frame */
7762       CUR_STREAM (stream)->fps_n = 0;
7763       CUR_STREAM (stream)->fps_d = 1;
7764     } else {
7765       if (stream->duration == 0 || stream->n_samples < 2) {
7766         CUR_STREAM (stream)->fps_n = stream->timescale;
7767         CUR_STREAM (stream)->fps_d = 1;
7768         fps_available = FALSE;
7769       } else {
7770         GstClockTime avg_duration;
7771         guint64 duration;
7772         guint32 n_samples;
7773
7774         /* duration and n_samples can be updated for fragmented format
7775          * so, framerate of fragmented format is calculated using data in a moof */
7776         if (qtdemux->fragmented && stream->n_samples_moof > 0
7777             && stream->duration_moof > 0) {
7778           n_samples = stream->n_samples_moof;
7779           duration = stream->duration_moof;
7780         } else {
7781           n_samples = stream->n_samples;
7782           duration = stream->duration;
7783         }
7784
7785         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7786         /* stream->duration is guint64, timescale, n_samples are guint32 */
7787         avg_duration =
7788             gst_util_uint64_scale_round (duration -
7789             stream->first_duration, GST_SECOND,
7790             (guint64) (stream->timescale) * (n_samples - 1));
7791
7792         GST_LOG_OBJECT (qtdemux,
7793             "Calculating avg sample duration based on stream (or moof) duration %"
7794             G_GUINT64_FORMAT
7795             " minus first sample %u, leaving %d samples gives %"
7796             GST_TIME_FORMAT, duration, stream->first_duration,
7797             n_samples - 1, GST_TIME_ARGS (avg_duration));
7798
7799         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7800             &CUR_STREAM (stream)->fps_d);
7801
7802         GST_DEBUG_OBJECT (qtdemux,
7803             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7804             stream->timescale, CUR_STREAM (stream)->fps_n,
7805             CUR_STREAM (stream)->fps_d);
7806       }
7807     }
7808
7809     if (CUR_STREAM (stream)->caps) {
7810       CUR_STREAM (stream)->caps =
7811           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7812
7813       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7814           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7815           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7816
7817       /* set framerate if calculated framerate is reliable */
7818       if (fps_available) {
7819         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7820             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7821             CUR_STREAM (stream)->fps_d, NULL);
7822       }
7823
7824       /* calculate pixel-aspect-ratio using display width and height */
7825       GST_DEBUG_OBJECT (qtdemux,
7826           "video size %dx%d, target display size %dx%d",
7827           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7828           stream->display_width, stream->display_height);
7829       /* qt file might have pasp atom */
7830       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7831         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7832             CUR_STREAM (stream)->par_h);
7833         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7834             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7835             CUR_STREAM (stream)->par_h, NULL);
7836       } else if (stream->display_width > 0 && stream->display_height > 0
7837           && CUR_STREAM (stream)->width > 0
7838           && CUR_STREAM (stream)->height > 0) {
7839         gint n, d;
7840
7841         /* calculate the pixel aspect ratio using the display and pixel w/h */
7842         n = stream->display_width * CUR_STREAM (stream)->height;
7843         d = stream->display_height * CUR_STREAM (stream)->width;
7844         if (n == d)
7845           n = d = 1;
7846         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7847         CUR_STREAM (stream)->par_w = n;
7848         CUR_STREAM (stream)->par_h = d;
7849         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7850             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7851             CUR_STREAM (stream)->par_h, NULL);
7852       }
7853
7854       if (CUR_STREAM (stream)->interlace_mode > 0) {
7855         if (CUR_STREAM (stream)->interlace_mode == 1) {
7856           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7857               G_TYPE_STRING, "progressive", NULL);
7858         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7859           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7860               G_TYPE_STRING, "interleaved", NULL);
7861           if (CUR_STREAM (stream)->field_order == 9) {
7862             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7863                 G_TYPE_STRING, "top-field-first", NULL);
7864           } else if (CUR_STREAM (stream)->field_order == 14) {
7865             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7866                 G_TYPE_STRING, "bottom-field-first", NULL);
7867           }
7868         }
7869       }
7870
7871       /* Create incomplete colorimetry here if needed */
7872       if (CUR_STREAM (stream)->colorimetry.range ||
7873           CUR_STREAM (stream)->colorimetry.matrix ||
7874           CUR_STREAM (stream)->colorimetry.transfer
7875           || CUR_STREAM (stream)->colorimetry.primaries) {
7876         gchar *colorimetry =
7877             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7878         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7879             G_TYPE_STRING, colorimetry, NULL);
7880         g_free (colorimetry);
7881       }
7882
7883       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7884         guint par_w = 1, par_h = 1;
7885
7886         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7887           par_w = CUR_STREAM (stream)->par_w;
7888           par_h = CUR_STREAM (stream)->par_h;
7889         }
7890
7891         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7892                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7893                 par_h)) {
7894           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7895         }
7896
7897         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7898             "multiview-mode", G_TYPE_STRING,
7899             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7900             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7901             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7902       }
7903     }
7904   }
7905
7906   else if (stream->subtype == FOURCC_soun) {
7907     if (CUR_STREAM (stream)->caps) {
7908       CUR_STREAM (stream)->caps =
7909           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7910       if (CUR_STREAM (stream)->rate > 0)
7911         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7912             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
7913       if (CUR_STREAM (stream)->n_channels > 0)
7914         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7915             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
7916       if (CUR_STREAM (stream)->n_channels > 2) {
7917         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7918          * correctly; this is just the minimum we can do - assume
7919          * we don't actually have any channel positions. */
7920         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7921             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7922       }
7923     }
7924   }
7925
7926   if (stream->pad) {
7927     GstCaps *prev_caps = NULL;
7928
7929     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7930     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7931     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7932     gst_pad_set_active (stream->pad, TRUE);
7933
7934     gst_pad_use_fixed_caps (stream->pad);
7935
7936     if (stream->protected) {
7937       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7938         GST_ERROR_OBJECT (qtdemux,
7939             "Failed to configure protected stream caps.");
7940         return FALSE;
7941       }
7942     }
7943
7944     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7945         CUR_STREAM (stream)->caps);
7946     if (stream->new_stream) {
7947       gchar *stream_id;
7948       GstEvent *event;
7949       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7950
7951       event =
7952           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7953           0);
7954       if (event) {
7955         gst_event_parse_stream_flags (event, &stream_flags);
7956         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7957           qtdemux->have_group_id = TRUE;
7958         else
7959           qtdemux->have_group_id = FALSE;
7960         gst_event_unref (event);
7961       } else if (!qtdemux->have_group_id) {
7962         qtdemux->have_group_id = TRUE;
7963         qtdemux->group_id = gst_util_group_id_next ();
7964       }
7965
7966       stream->new_stream = FALSE;
7967       stream_id =
7968           gst_pad_create_stream_id_printf (stream->pad,
7969           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7970       event = gst_event_new_stream_start (stream_id);
7971       if (qtdemux->have_group_id)
7972         gst_event_set_group_id (event, qtdemux->group_id);
7973       if (stream->disabled)
7974         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7975       if (CUR_STREAM (stream)->sparse) {
7976         stream_flags |= GST_STREAM_FLAG_SPARSE;
7977       } else {
7978         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
7979       }
7980       gst_event_set_stream_flags (event, stream_flags);
7981       gst_pad_push_event (stream->pad, event);
7982       g_free (stream_id);
7983     }
7984
7985     prev_caps = gst_pad_get_current_caps (stream->pad);
7986
7987     if (CUR_STREAM (stream)->caps) {
7988       if (!prev_caps
7989           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
7990         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7991             CUR_STREAM (stream)->caps);
7992         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
7993       } else {
7994         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7995       }
7996     } else {
7997       GST_WARNING_OBJECT (qtdemux, "stream without caps");
7998     }
7999
8000     if (prev_caps)
8001       gst_caps_unref (prev_caps);
8002     stream->new_caps = FALSE;
8003   }
8004   return TRUE;
8005 }
8006
8007 static void
8008 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8009     QtDemuxStream * stream)
8010 {
8011   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8012     return;
8013
8014   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8015       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8016   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8017           stream->stsd_entries_length)) {
8018     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8019         (_("This file is invalid and cannot be played.")),
8020         ("New sample description id is out of bounds (%d >= %d)",
8021             stream->stsd_sample_description_id, stream->stsd_entries_length));
8022   } else {
8023     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8024     stream->new_caps = TRUE;
8025   }
8026 }
8027
8028 static gboolean
8029 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8030     QtDemuxStream * stream, GstTagList * list)
8031 {
8032   gboolean ret = TRUE;
8033   /* consistent default for push based mode */
8034   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8035
8036   if (stream->subtype == FOURCC_vide) {
8037     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8038
8039     stream->pad =
8040         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8041     g_free (name);
8042
8043     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8044       gst_object_unref (stream->pad);
8045       stream->pad = NULL;
8046       ret = FALSE;
8047       goto done;
8048     }
8049
8050     qtdemux->n_video_streams++;
8051   } else if (stream->subtype == FOURCC_soun) {
8052     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8053
8054     stream->pad =
8055         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8056     g_free (name);
8057     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8058       gst_object_unref (stream->pad);
8059       stream->pad = NULL;
8060       ret = FALSE;
8061       goto done;
8062     }
8063     qtdemux->n_audio_streams++;
8064   } else if (stream->subtype == FOURCC_strm) {
8065     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8066   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8067       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8068     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8069
8070     stream->pad =
8071         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8072     g_free (name);
8073     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8074       gst_object_unref (stream->pad);
8075       stream->pad = NULL;
8076       ret = FALSE;
8077       goto done;
8078     }
8079     qtdemux->n_sub_streams++;
8080   } else if (CUR_STREAM (stream)->caps) {
8081     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8082
8083     stream->pad =
8084         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8085     g_free (name);
8086     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8087       gst_object_unref (stream->pad);
8088       stream->pad = NULL;
8089       ret = FALSE;
8090       goto done;
8091     }
8092     qtdemux->n_video_streams++;
8093   } else {
8094     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8095     goto done;
8096   }
8097
8098   if (stream->pad) {
8099     GList *l;
8100
8101     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8102         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8103     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8104     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8105
8106     if (stream->stream_tags)
8107       gst_tag_list_unref (stream->stream_tags);
8108     stream->stream_tags = list;
8109     list = NULL;
8110     /* global tags go on each pad anyway */
8111     stream->send_global_tags = TRUE;
8112     /* send upstream GST_EVENT_PROTECTION events that were received before
8113        this source pad was created */
8114     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8115       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8116   }
8117 done:
8118   if (list)
8119     gst_tag_list_unref (list);
8120   return ret;
8121 }
8122
8123 /* find next atom with @fourcc starting at @offset */
8124 static GstFlowReturn
8125 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8126     guint64 * length, guint32 fourcc)
8127 {
8128   GstFlowReturn ret;
8129   guint32 lfourcc;
8130   GstBuffer *buf;
8131
8132   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8133       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8134
8135   while (TRUE) {
8136     GstMapInfo map;
8137
8138     buf = NULL;
8139     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8140     if (G_UNLIKELY (ret != GST_FLOW_OK))
8141       goto locate_failed;
8142     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8143       /* likely EOF */
8144       ret = GST_FLOW_EOS;
8145       gst_buffer_unref (buf);
8146       goto locate_failed;
8147     }
8148     gst_buffer_map (buf, &map, GST_MAP_READ);
8149     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8150     gst_buffer_unmap (buf, &map);
8151     gst_buffer_unref (buf);
8152
8153     if (G_UNLIKELY (*length == 0)) {
8154       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8155       ret = GST_FLOW_ERROR;
8156       goto locate_failed;
8157     }
8158
8159     if (lfourcc == fourcc) {
8160       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8161           *offset);
8162       break;
8163     } else {
8164       GST_LOG_OBJECT (qtdemux,
8165           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8166           GST_FOURCC_ARGS (fourcc), *offset);
8167       *offset += *length;
8168     }
8169   }
8170
8171   return GST_FLOW_OK;
8172
8173 locate_failed:
8174   {
8175     /* might simply have had last one */
8176     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8177     return ret;
8178   }
8179 }
8180
8181 /* should only do something in pull mode */
8182 /* call with OBJECT lock */
8183 static GstFlowReturn
8184 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8185 {
8186   guint64 length, offset;
8187   GstBuffer *buf = NULL;
8188   GstFlowReturn ret = GST_FLOW_OK;
8189   GstFlowReturn res = GST_FLOW_OK;
8190   GstMapInfo map;
8191
8192   offset = qtdemux->moof_offset;
8193   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8194
8195   if (!offset) {
8196     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8197     return GST_FLOW_EOS;
8198   }
8199
8200   /* best not do pull etc with lock held */
8201   GST_OBJECT_UNLOCK (qtdemux);
8202
8203   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8204   if (ret != GST_FLOW_OK)
8205     goto flow_failed;
8206
8207   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8208   if (G_UNLIKELY (ret != GST_FLOW_OK))
8209     goto flow_failed;
8210   gst_buffer_map (buf, &map, GST_MAP_READ);
8211   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8212     gst_buffer_unmap (buf, &map);
8213     gst_buffer_unref (buf);
8214     buf = NULL;
8215     goto parse_failed;
8216   }
8217
8218   gst_buffer_unmap (buf, &map);
8219   gst_buffer_unref (buf);
8220   buf = NULL;
8221
8222   offset += length;
8223   /* look for next moof */
8224   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8225   if (G_UNLIKELY (ret != GST_FLOW_OK))
8226     goto flow_failed;
8227
8228 exit:
8229   GST_OBJECT_LOCK (qtdemux);
8230
8231   qtdemux->moof_offset = offset;
8232
8233   return res;
8234
8235 parse_failed:
8236   {
8237     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8238     offset = 0;
8239     res = GST_FLOW_ERROR;
8240     goto exit;
8241   }
8242 flow_failed:
8243   {
8244     /* maybe upstream temporarily flushing */
8245     if (ret != GST_FLOW_FLUSHING) {
8246       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8247       offset = 0;
8248     } else {
8249       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8250       /* resume at current position next time */
8251     }
8252     res = ret;
8253     goto exit;
8254   }
8255 }
8256
8257 /* initialise bytereaders for stbl sub-atoms */
8258 static gboolean
8259 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8260 {
8261   stream->stbl_index = -1;      /* no samples have yet been parsed */
8262   stream->sample_index = -1;
8263
8264   /* time-to-sample atom */
8265   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8266     goto corrupt_file;
8267
8268   /* copy atom data into a new buffer for later use */
8269   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8270
8271   /* skip version + flags */
8272   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8273       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8274     goto corrupt_file;
8275   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8276
8277   /* make sure there's enough data */
8278   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8279     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8280     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8281         stream->n_sample_times);
8282     if (!stream->n_sample_times)
8283       goto corrupt_file;
8284   }
8285
8286   /* sync sample atom */
8287   stream->stps_present = FALSE;
8288   if ((stream->stss_present =
8289           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8290               &stream->stss) ? TRUE : FALSE) == TRUE) {
8291     /* copy atom data into a new buffer for later use */
8292     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8293
8294     /* skip version + flags */
8295     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8296         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8297       goto corrupt_file;
8298
8299     if (stream->n_sample_syncs) {
8300       /* make sure there's enough data */
8301       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8302         goto corrupt_file;
8303     }
8304
8305     /* partial sync sample atom */
8306     if ((stream->stps_present =
8307             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8308                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8309       /* copy atom data into a new buffer for later use */
8310       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8311
8312       /* skip version + flags */
8313       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8314           !gst_byte_reader_get_uint32_be (&stream->stps,
8315               &stream->n_sample_partial_syncs))
8316         goto corrupt_file;
8317
8318       /* if there are no entries, the stss table contains the real
8319        * sync samples */
8320       if (stream->n_sample_partial_syncs) {
8321         /* make sure there's enough data */
8322         if (!qt_atom_parser_has_chunks (&stream->stps,
8323                 stream->n_sample_partial_syncs, 4))
8324           goto corrupt_file;
8325       }
8326     }
8327   }
8328
8329   /* sample size */
8330   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8331     goto no_samples;
8332
8333   /* copy atom data into a new buffer for later use */
8334   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8335
8336   /* skip version + flags */
8337   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8338       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8339     goto corrupt_file;
8340
8341   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8342     goto corrupt_file;
8343
8344   if (!stream->n_samples)
8345     goto no_samples;
8346
8347   /* sample-to-chunk atom */
8348   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8349     goto corrupt_file;
8350
8351   /* copy atom data into a new buffer for later use */
8352   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8353
8354   /* skip version + flags */
8355   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8356       !gst_byte_reader_get_uint32_be (&stream->stsc,
8357           &stream->n_samples_per_chunk))
8358     goto corrupt_file;
8359
8360   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8361       stream->n_samples_per_chunk);
8362
8363   /* make sure there's enough data */
8364   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8365           12))
8366     goto corrupt_file;
8367
8368
8369   /* chunk offset */
8370   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8371     stream->co_size = sizeof (guint32);
8372   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8373           &stream->stco))
8374     stream->co_size = sizeof (guint64);
8375   else
8376     goto corrupt_file;
8377
8378   /* copy atom data into a new buffer for later use */
8379   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8380
8381   /* skip version + flags */
8382   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8383     goto corrupt_file;
8384
8385   /* chunks_are_samples == TRUE means treat chunks as samples */
8386   stream->chunks_are_samples = stream->sample_size
8387       && !CUR_STREAM (stream)->sampled;
8388   if (stream->chunks_are_samples) {
8389     /* treat chunks as samples */
8390     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8391       goto corrupt_file;
8392   } else {
8393     /* skip number of entries */
8394     if (!gst_byte_reader_skip (&stream->stco, 4))
8395       goto corrupt_file;
8396
8397     /* make sure there are enough data in the stsz atom */
8398     if (!stream->sample_size) {
8399       /* different sizes for each sample */
8400       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8401         goto corrupt_file;
8402     }
8403   }
8404
8405   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8406       stream->n_samples, (guint) sizeof (QtDemuxSample),
8407       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8408
8409   if (stream->n_samples >=
8410       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8411     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8412         "be larger than %uMB (broken file?)", stream->n_samples,
8413         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8414     return FALSE;
8415   }
8416
8417   g_assert (stream->samples == NULL);
8418   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8419   if (!stream->samples) {
8420     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8421         stream->n_samples);
8422     return FALSE;
8423   }
8424
8425   /* composition time-to-sample */
8426   if ((stream->ctts_present =
8427           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8428               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8429     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8430
8431     /* copy atom data into a new buffer for later use */
8432     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8433
8434     /* skip version + flags */
8435     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8436         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8437             &stream->n_composition_times))
8438       goto corrupt_file;
8439
8440     /* make sure there's enough data */
8441     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8442             4 + 4))
8443       goto corrupt_file;
8444
8445     /* This is optional, if missing we iterate the ctts */
8446     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8447       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8448           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8449         g_free ((gpointer) cslg.data);
8450         goto corrupt_file;
8451       }
8452     } else {
8453       gint32 cslg_least = 0;
8454       guint num_entries, pos;
8455       gint i;
8456
8457       pos = gst_byte_reader_get_pos (&stream->ctts);
8458       num_entries = stream->n_composition_times;
8459
8460       stream->cslg_shift = 0;
8461
8462       for (i = 0; i < num_entries; i++) {
8463         gint32 offset;
8464
8465         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8466         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8467
8468         if (offset < cslg_least)
8469           cslg_least = offset;
8470       }
8471
8472       if (cslg_least < 0)
8473         stream->cslg_shift = ABS (cslg_least);
8474       else
8475         stream->cslg_shift = 0;
8476
8477       /* reset the reader so we can generate sample table */
8478       gst_byte_reader_set_pos (&stream->ctts, pos);
8479     }
8480   } else {
8481     /* Ensure the cslg_shift value is consistent so we can use it
8482      * unconditionnally to produce TS and Segment */
8483     stream->cslg_shift = 0;
8484   }
8485
8486   return TRUE;
8487
8488 corrupt_file:
8489   {
8490     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8491         (_("This file is corrupt and cannot be played.")), (NULL));
8492     return FALSE;
8493   }
8494 no_samples:
8495   {
8496     gst_qtdemux_stbl_free (stream);
8497     if (!qtdemux->fragmented) {
8498       /* not quite good */
8499       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8500       return FALSE;
8501     } else {
8502       /* may pick up samples elsewhere */
8503       return TRUE;
8504     }
8505   }
8506 }
8507
8508 /* collect samples from the next sample to be parsed up to sample @n for @stream
8509  * by reading the info from @stbl
8510  *
8511  * This code can be executed from both the streaming thread and the seeking
8512  * thread so it takes the object lock to protect itself
8513  */
8514 static gboolean
8515 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8516 {
8517   gint i, j, k;
8518   QtDemuxSample *samples, *first, *cur, *last;
8519   guint32 n_samples_per_chunk;
8520   guint32 n_samples;
8521
8522   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8523       GST_FOURCC_FORMAT ", pad %s",
8524       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8525       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8526
8527   n_samples = stream->n_samples;
8528
8529   if (n >= n_samples)
8530     goto out_of_samples;
8531
8532   GST_OBJECT_LOCK (qtdemux);
8533   if (n <= stream->stbl_index)
8534     goto already_parsed;
8535
8536   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8537
8538   if (!stream->stsz.data) {
8539     /* so we already parsed and passed all the moov samples;
8540      * onto fragmented ones */
8541     g_assert (qtdemux->fragmented);
8542     goto done;
8543   }
8544
8545   /* pointer to the sample table */
8546   samples = stream->samples;
8547
8548   /* starts from -1, moves to the next sample index to parse */
8549   stream->stbl_index++;
8550
8551   /* keep track of the first and last sample to fill */
8552   first = &samples[stream->stbl_index];
8553   last = &samples[n];
8554
8555   if (!stream->chunks_are_samples) {
8556     /* set the sample sizes */
8557     if (stream->sample_size == 0) {
8558       /* different sizes for each sample */
8559       for (cur = first; cur <= last; cur++) {
8560         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8561         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8562             (guint) (cur - samples), cur->size);
8563       }
8564     } else {
8565       /* samples have the same size */
8566       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8567       for (cur = first; cur <= last; cur++)
8568         cur->size = stream->sample_size;
8569     }
8570   }
8571
8572   n_samples_per_chunk = stream->n_samples_per_chunk;
8573   cur = first;
8574
8575   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8576     guint32 last_chunk;
8577
8578     if (stream->stsc_chunk_index >= stream->last_chunk
8579         || stream->stsc_chunk_index < stream->first_chunk) {
8580       stream->first_chunk =
8581           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8582       stream->samples_per_chunk =
8583           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8584       /* starts from 1 */
8585       stream->stsd_sample_description_id =
8586           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8587
8588       /* chunk numbers are counted from 1 it seems */
8589       if (G_UNLIKELY (stream->first_chunk == 0))
8590         goto corrupt_file;
8591
8592       --stream->first_chunk;
8593
8594       /* the last chunk of each entry is calculated by taking the first chunk
8595        * of the next entry; except if there is no next, where we fake it with
8596        * INT_MAX */
8597       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8598         stream->last_chunk = G_MAXUINT32;
8599       } else {
8600         stream->last_chunk =
8601             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8602         if (G_UNLIKELY (stream->last_chunk == 0))
8603           goto corrupt_file;
8604
8605         --stream->last_chunk;
8606       }
8607
8608       GST_LOG_OBJECT (qtdemux,
8609           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8610           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8611           stream->samples_per_chunk, stream->stsd_sample_description_id);
8612
8613       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8614         goto corrupt_file;
8615
8616       if (stream->last_chunk != G_MAXUINT32) {
8617         if (!qt_atom_parser_peek_sub (&stream->stco,
8618                 stream->first_chunk * stream->co_size,
8619                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8620                 &stream->co_chunk))
8621           goto corrupt_file;
8622
8623       } else {
8624         stream->co_chunk = stream->stco;
8625         if (!gst_byte_reader_skip (&stream->co_chunk,
8626                 stream->first_chunk * stream->co_size))
8627           goto corrupt_file;
8628       }
8629
8630       stream->stsc_chunk_index = stream->first_chunk;
8631     }
8632
8633     last_chunk = stream->last_chunk;
8634
8635     if (stream->chunks_are_samples) {
8636       cur = &samples[stream->stsc_chunk_index];
8637
8638       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8639         if (j > n) {
8640           /* save state */
8641           stream->stsc_chunk_index = j;
8642           goto done;
8643         }
8644
8645         cur->offset =
8646             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8647             stream->co_size);
8648
8649         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8650             "%" G_GUINT64_FORMAT, j, cur->offset);
8651
8652         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8653             CUR_STREAM (stream)->bytes_per_frame > 0) {
8654           cur->size =
8655               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8656               CUR_STREAM (stream)->samples_per_frame *
8657               CUR_STREAM (stream)->bytes_per_frame;
8658         } else {
8659           cur->size = stream->samples_per_chunk;
8660         }
8661
8662         GST_DEBUG_OBJECT (qtdemux,
8663             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8664             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8665                     stream->stco_sample_index)), cur->size);
8666
8667         cur->timestamp = stream->stco_sample_index;
8668         cur->duration = stream->samples_per_chunk;
8669         cur->keyframe = TRUE;
8670         cur++;
8671
8672         stream->stco_sample_index += stream->samples_per_chunk;
8673       }
8674       stream->stsc_chunk_index = j;
8675     } else {
8676       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8677         guint32 samples_per_chunk;
8678         guint64 chunk_offset;
8679
8680         if (!stream->stsc_sample_index
8681             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8682                 &stream->chunk_offset))
8683           goto corrupt_file;
8684
8685         samples_per_chunk = stream->samples_per_chunk;
8686         chunk_offset = stream->chunk_offset;
8687
8688         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8689           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8690               G_GUINT64_FORMAT " and size %d",
8691               (guint) (cur - samples), chunk_offset, cur->size);
8692
8693           cur->offset = chunk_offset;
8694           chunk_offset += cur->size;
8695           cur++;
8696
8697           if (G_UNLIKELY (cur > last)) {
8698             /* save state */
8699             stream->stsc_sample_index = k + 1;
8700             stream->chunk_offset = chunk_offset;
8701             stream->stsc_chunk_index = j;
8702             goto done2;
8703           }
8704         }
8705         stream->stsc_sample_index = 0;
8706       }
8707       stream->stsc_chunk_index = j;
8708     }
8709     stream->stsc_index++;
8710   }
8711
8712   if (stream->chunks_are_samples)
8713     goto ctts;
8714 done2:
8715   {
8716     guint32 n_sample_times;
8717
8718     n_sample_times = stream->n_sample_times;
8719     cur = first;
8720
8721     for (i = stream->stts_index; i < n_sample_times; i++) {
8722       guint32 stts_samples;
8723       gint32 stts_duration;
8724       gint64 stts_time;
8725
8726       if (stream->stts_sample_index >= stream->stts_samples
8727           || !stream->stts_sample_index) {
8728
8729         stream->stts_samples =
8730             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8731         stream->stts_duration =
8732             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8733
8734         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8735             i, stream->stts_samples, stream->stts_duration);
8736
8737         stream->stts_sample_index = 0;
8738       }
8739
8740       stts_samples = stream->stts_samples;
8741       stts_duration = stream->stts_duration;
8742       stts_time = stream->stts_time;
8743
8744       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8745         GST_DEBUG_OBJECT (qtdemux,
8746             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8747             (guint) (cur - samples), j,
8748             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8749
8750         cur->timestamp = stts_time;
8751         cur->duration = stts_duration;
8752
8753         /* avoid 32-bit wrap-around,
8754          * but still mind possible 'negative' duration */
8755         stts_time += (gint64) stts_duration;
8756         cur++;
8757
8758         if (G_UNLIKELY (cur > last)) {
8759           /* save values */
8760           stream->stts_time = stts_time;
8761           stream->stts_sample_index = j + 1;
8762           if (stream->stts_sample_index >= stream->stts_samples)
8763             stream->stts_index++;
8764           goto done3;
8765         }
8766       }
8767       stream->stts_sample_index = 0;
8768       stream->stts_time = stts_time;
8769       stream->stts_index++;
8770     }
8771     /* fill up empty timestamps with the last timestamp, this can happen when
8772      * the last samples do not decode and so we don't have timestamps for them.
8773      * We however look at the last timestamp to estimate the track length so we
8774      * need something in here. */
8775     for (; cur < last; cur++) {
8776       GST_DEBUG_OBJECT (qtdemux,
8777           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8778           (guint) (cur - samples),
8779           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8780       cur->timestamp = stream->stts_time;
8781       cur->duration = -1;
8782     }
8783   }
8784 done3:
8785   {
8786     /* sample sync, can be NULL */
8787     if (stream->stss_present == TRUE) {
8788       guint32 n_sample_syncs;
8789
8790       n_sample_syncs = stream->n_sample_syncs;
8791
8792       if (!n_sample_syncs) {
8793         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8794         stream->all_keyframe = TRUE;
8795       } else {
8796         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8797           /* note that the first sample is index 1, not 0 */
8798           guint32 index;
8799
8800           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8801
8802           if (G_LIKELY (index > 0 && index <= n_samples)) {
8803             index -= 1;
8804             samples[index].keyframe = TRUE;
8805             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8806             /* and exit if we have enough samples */
8807             if (G_UNLIKELY (index >= n)) {
8808               i++;
8809               break;
8810             }
8811           }
8812         }
8813         /* save state */
8814         stream->stss_index = i;
8815       }
8816
8817       /* stps marks partial sync frames like open GOP I-Frames */
8818       if (stream->stps_present == TRUE) {
8819         guint32 n_sample_partial_syncs;
8820
8821         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8822
8823         /* if there are no entries, the stss table contains the real
8824          * sync samples */
8825         if (n_sample_partial_syncs) {
8826           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8827             /* note that the first sample is index 1, not 0 */
8828             guint32 index;
8829
8830             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8831
8832             if (G_LIKELY (index > 0 && index <= n_samples)) {
8833               index -= 1;
8834               samples[index].keyframe = TRUE;
8835               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8836               /* and exit if we have enough samples */
8837               if (G_UNLIKELY (index >= n)) {
8838                 i++;
8839                 break;
8840               }
8841             }
8842           }
8843           /* save state */
8844           stream->stps_index = i;
8845         }
8846       }
8847     } else {
8848       /* no stss, all samples are keyframes */
8849       stream->all_keyframe = TRUE;
8850       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8851     }
8852   }
8853
8854 ctts:
8855   /* composition time to sample */
8856   if (stream->ctts_present == TRUE) {
8857     guint32 n_composition_times;
8858     guint32 ctts_count;
8859     gint32 ctts_soffset;
8860
8861     /* Fill in the pts_offsets */
8862     cur = first;
8863     n_composition_times = stream->n_composition_times;
8864
8865     for (i = stream->ctts_index; i < n_composition_times; i++) {
8866       if (stream->ctts_sample_index >= stream->ctts_count
8867           || !stream->ctts_sample_index) {
8868         stream->ctts_count =
8869             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8870         stream->ctts_soffset =
8871             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8872         stream->ctts_sample_index = 0;
8873       }
8874
8875       ctts_count = stream->ctts_count;
8876       ctts_soffset = stream->ctts_soffset;
8877
8878       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8879         cur->pts_offset = ctts_soffset;
8880         cur++;
8881
8882         if (G_UNLIKELY (cur > last)) {
8883           /* save state */
8884           stream->ctts_sample_index = j + 1;
8885           goto done;
8886         }
8887       }
8888       stream->ctts_sample_index = 0;
8889       stream->ctts_index++;
8890     }
8891   }
8892 done:
8893   stream->stbl_index = n;
8894   /* if index has been completely parsed, free data that is no-longer needed */
8895   if (n + 1 == stream->n_samples) {
8896     gst_qtdemux_stbl_free (stream);
8897     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8898     if (qtdemux->pullbased) {
8899       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8900       while (n + 1 == stream->n_samples)
8901         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8902           break;
8903     }
8904   }
8905   GST_OBJECT_UNLOCK (qtdemux);
8906
8907   return TRUE;
8908
8909   /* SUCCESS */
8910 already_parsed:
8911   {
8912     GST_LOG_OBJECT (qtdemux,
8913         "Tried to parse up to sample %u but this sample has already been parsed",
8914         n);
8915     /* if fragmented, there may be more */
8916     if (qtdemux->fragmented && n == stream->stbl_index)
8917       goto done;
8918     GST_OBJECT_UNLOCK (qtdemux);
8919     return TRUE;
8920   }
8921   /* ERRORS */
8922 out_of_samples:
8923   {
8924     GST_LOG_OBJECT (qtdemux,
8925         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8926         stream->n_samples);
8927     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8928         (_("This file is corrupt and cannot be played.")), (NULL));
8929     return FALSE;
8930   }
8931 corrupt_file:
8932   {
8933     GST_OBJECT_UNLOCK (qtdemux);
8934     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8935         (_("This file is corrupt and cannot be played.")), (NULL));
8936     return FALSE;
8937   }
8938 }
8939
8940 /* collect all segment info for @stream.
8941  */
8942 static gboolean
8943 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8944     GNode * trak)
8945 {
8946   GNode *edts;
8947   /* accept edts if they contain gaps at start and there is only
8948    * one media segment */
8949   gboolean allow_pushbased_edts = TRUE;
8950   gint media_segments_count = 0;
8951
8952   /* parse and prepare segment info from the edit list */
8953   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8954   stream->n_segments = 0;
8955   stream->segments = NULL;
8956   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8957     GNode *elst;
8958     gint n_segments;
8959     gint i, count, entry_size;
8960     guint64 time;
8961     GstClockTime stime;
8962     const guint8 *buffer;
8963     guint8 version;
8964     guint32 size;
8965
8966     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8967     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8968       goto done;
8969
8970     buffer = elst->data;
8971
8972     size = QT_UINT32 (buffer);
8973     /* version, flags, n_segments */
8974     if (size < 16) {
8975       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8976       goto done;
8977     }
8978     version = QT_UINT8 (buffer + 8);
8979     entry_size = (version == 1) ? 20 : 12;
8980
8981     n_segments = QT_UINT32 (buffer + 12);
8982
8983     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
8984       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8985       goto done;
8986     }
8987
8988     /* we might allocate a bit too much, at least allocate 1 segment */
8989     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8990
8991     /* segments always start from 0 */
8992     time = 0;
8993     stime = 0;
8994     count = 0;
8995     buffer += 16;
8996     for (i = 0; i < n_segments; i++) {
8997       guint64 duration;
8998       guint64 media_time;
8999       gboolean time_valid = TRUE;
9000       QtDemuxSegment *segment;
9001       guint32 rate_int;
9002       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9003
9004       if (version == 1) {
9005         media_time = QT_UINT64 (buffer + 8);
9006         duration = QT_UINT64 (buffer);
9007         if (media_time == G_MAXUINT64)
9008           time_valid = FALSE;
9009       } else {
9010         media_time = QT_UINT32 (buffer + 4);
9011         duration = QT_UINT32 (buffer);
9012         if (media_time == G_MAXUINT32)
9013           time_valid = FALSE;
9014       }
9015
9016       if (time_valid)
9017         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9018
9019       segment = &stream->segments[count++];
9020
9021       /* time and duration expressed in global timescale */
9022       segment->time = stime;
9023       /* add non scaled values so we don't cause roundoff errors */
9024       if (duration || media_start == GST_CLOCK_TIME_NONE) {
9025         time += duration;
9026         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9027         segment->duration = stime - segment->time;
9028       } else {
9029         /* zero duration does not imply media_start == media_stop
9030          * but, only specify media_start.*/
9031         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9032         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9033             && stime >= media_start) {
9034           segment->duration = stime - media_start;
9035         } else {
9036           segment->duration = GST_CLOCK_TIME_NONE;
9037         }
9038       }
9039       segment->stop_time = stime;
9040
9041       segment->trak_media_start = media_time;
9042       /* media_time expressed in stream timescale */
9043       if (time_valid) {
9044         segment->media_start = media_start;
9045         segment->media_stop = segment->media_start + segment->duration;
9046         media_segments_count++;
9047       } else {
9048         segment->media_start = GST_CLOCK_TIME_NONE;
9049         segment->media_stop = GST_CLOCK_TIME_NONE;
9050       }
9051       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9052
9053       if (rate_int <= 1) {
9054         /* 0 is not allowed, some programs write 1 instead of the floating point
9055          * value */
9056         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9057             rate_int);
9058         segment->rate = 1;
9059       } else {
9060         segment->rate = rate_int / 65536.0;
9061       }
9062
9063       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9064           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9065           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9066           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9067           i, GST_TIME_ARGS (segment->time),
9068           GST_TIME_ARGS (segment->duration),
9069           GST_TIME_ARGS (segment->media_start), media_time,
9070           GST_TIME_ARGS (segment->media_stop),
9071           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9072           stream->timescale);
9073       if (segment->stop_time > qtdemux->segment.stop) {
9074         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9075             " extends to %" GST_TIME_FORMAT
9076             " past the end of the file duration %" GST_TIME_FORMAT
9077             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9078             GST_TIME_ARGS (qtdemux->segment.stop));
9079         qtdemux->segment.stop = segment->stop_time;
9080       }
9081
9082       buffer += entry_size;
9083     }
9084     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9085     stream->n_segments = count;
9086     if (media_segments_count != 1)
9087       allow_pushbased_edts = FALSE;
9088   }
9089 done:
9090
9091   /* push based does not handle segments, so act accordingly here,
9092    * and warn if applicable */
9093   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9094     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9095     /* remove and use default one below, we stream like it anyway */
9096     g_free (stream->segments);
9097     stream->segments = NULL;
9098     stream->n_segments = 0;
9099   }
9100
9101   /* no segments, create one to play the complete trak */
9102   if (stream->n_segments == 0) {
9103     GstClockTime stream_duration =
9104         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9105
9106     if (stream->segments == NULL)
9107       stream->segments = g_new (QtDemuxSegment, 1);
9108
9109     /* represent unknown our way */
9110     if (stream_duration == 0)
9111       stream_duration = GST_CLOCK_TIME_NONE;
9112
9113     stream->segments[0].time = 0;
9114     stream->segments[0].stop_time = stream_duration;
9115     stream->segments[0].duration = stream_duration;
9116     stream->segments[0].media_start = 0;
9117     stream->segments[0].media_stop = stream_duration;
9118     stream->segments[0].rate = 1.0;
9119     stream->segments[0].trak_media_start = 0;
9120
9121     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9122         GST_TIME_ARGS (stream_duration));
9123     stream->n_segments = 1;
9124     stream->dummy_segment = TRUE;
9125   }
9126   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9127
9128   return TRUE;
9129 }
9130
9131 /*
9132  * Parses the stsd atom of a svq3 trak looking for
9133  * the SMI and gama atoms.
9134  */
9135 static void
9136 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9137     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9138 {
9139   const guint8 *_gamma = NULL;
9140   GstBuffer *_seqh = NULL;
9141   const guint8 *stsd_data = stsd_entry_data;
9142   guint32 length = QT_UINT32 (stsd_data);
9143   guint16 version;
9144
9145   if (length < 32) {
9146     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9147     goto end;
9148   }
9149
9150   stsd_data += 16;
9151   length -= 16;
9152   version = QT_UINT16 (stsd_data);
9153   if (version == 3) {
9154     if (length >= 70) {
9155       length -= 70;
9156       stsd_data += 70;
9157       while (length > 8) {
9158         guint32 fourcc, size;
9159         const guint8 *data;
9160         size = QT_UINT32 (stsd_data);
9161         fourcc = QT_FOURCC (stsd_data + 4);
9162         data = stsd_data + 8;
9163
9164         if (size == 0) {
9165           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9166               "svq3 atom parsing");
9167           goto end;
9168         }
9169
9170         switch (fourcc) {
9171           case FOURCC_gama:{
9172             if (size == 12) {
9173               _gamma = data;
9174             } else {
9175               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9176                   " for gama atom, expected 12", size);
9177             }
9178             break;
9179           }
9180           case FOURCC_SMI_:{
9181             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9182               guint32 seqh_size;
9183               if (_seqh != NULL) {
9184                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9185                     " found, ignoring");
9186               } else {
9187                 seqh_size = QT_UINT32 (data + 4);
9188                 if (seqh_size > 0) {
9189                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9190                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9191                 }
9192               }
9193             }
9194             break;
9195           }
9196           default:{
9197             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9198                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9199           }
9200         }
9201
9202         if (size <= length) {
9203           length -= size;
9204           stsd_data += size;
9205         }
9206       }
9207     } else {
9208       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9209     }
9210   } else {
9211     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9212         G_GUINT16_FORMAT, version);
9213     goto end;
9214   }
9215
9216 end:
9217   if (gamma) {
9218     *gamma = _gamma;
9219   }
9220   if (seqh) {
9221     *seqh = _seqh;
9222   } else if (_seqh) {
9223     gst_buffer_unref (_seqh);
9224   }
9225 }
9226
9227 static gchar *
9228 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9229 {
9230   GNode *dinf;
9231   GstByteReader dref;
9232   gchar *uri = NULL;
9233
9234   /*
9235    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9236    * atom that might contain a 'data' atom with the rtsp uri.
9237    * This case was reported in bug #597497, some info about
9238    * the hndl atom can be found in TN1195
9239    */
9240   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9241   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9242
9243   if (dinf) {
9244     guint32 dref_num_entries = 0;
9245     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9246         gst_byte_reader_skip (&dref, 4) &&
9247         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9248       gint i;
9249
9250       /* search dref entries for hndl atom */
9251       for (i = 0; i < dref_num_entries; i++) {
9252         guint32 size = 0, type;
9253         guint8 string_len = 0;
9254         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9255             qt_atom_parser_get_fourcc (&dref, &type)) {
9256           if (type == FOURCC_hndl) {
9257             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9258
9259             /* skip data reference handle bytes and the
9260              * following pascal string and some extra 4
9261              * bytes I have no idea what are */
9262             if (!gst_byte_reader_skip (&dref, 4) ||
9263                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9264                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9265               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9266               break;
9267             }
9268
9269             /* iterate over the atoms to find the data atom */
9270             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9271               guint32 atom_size;
9272               guint32 atom_type;
9273
9274               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9275                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9276                 if (atom_type == FOURCC_data) {
9277                   const guint8 *uri_aux = NULL;
9278
9279                   /* found the data atom that might contain the rtsp uri */
9280                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9281                       "hndl atom, interpreting it as an URI");
9282                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9283                           &uri_aux)) {
9284                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9285                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9286                     else
9287                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9288                           "didn't contain a rtsp address");
9289                   } else {
9290                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9291                         "atom contents");
9292                   }
9293                   break;
9294                 }
9295                 /* skipping to the next entry */
9296                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9297                   break;
9298               } else {
9299                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9300                     "atom header");
9301                 break;
9302               }
9303             }
9304             break;
9305           }
9306           /* skip to the next entry */
9307           if (!gst_byte_reader_skip (&dref, size - 8))
9308             break;
9309         } else {
9310           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9311         }
9312       }
9313       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9314     }
9315   }
9316   return uri;
9317 }
9318
9319 #define AMR_NB_ALL_MODES        0x81ff
9320 #define AMR_WB_ALL_MODES        0x83ff
9321 static guint
9322 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9323 {
9324   /* The 'damr' atom is of the form:
9325    *
9326    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9327    *    32 b       8 b          16 b           8 b                 8 b
9328    *
9329    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9330    * represents the highest mode used in the stream (and thus the maximum
9331    * bitrate), with a couple of special cases as seen below.
9332    */
9333
9334   /* Map of frame type ID -> bitrate */
9335   static const guint nb_bitrates[] = {
9336     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9337   };
9338   static const guint wb_bitrates[] = {
9339     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9340   };
9341   GstMapInfo map;
9342   gsize max_mode;
9343   guint16 mode_set;
9344
9345   gst_buffer_map (buf, &map, GST_MAP_READ);
9346
9347   if (map.size != 0x11) {
9348     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9349     goto bad_data;
9350   }
9351
9352   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9353     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9354         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9355     goto bad_data;
9356   }
9357
9358   mode_set = QT_UINT16 (map.data + 13);
9359
9360   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9361     max_mode = 7 + (wb ? 1 : 0);
9362   else
9363     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9364     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9365
9366   if (max_mode == -1) {
9367     GST_DEBUG ("No mode indication was found (mode set) = %x",
9368         (guint) mode_set);
9369     goto bad_data;
9370   }
9371
9372   gst_buffer_unmap (buf, &map);
9373   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9374
9375 bad_data:
9376   gst_buffer_unmap (buf, &map);
9377   return 0;
9378 }
9379
9380 static gboolean
9381 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9382     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9383 {
9384   /*
9385    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9386    * [0 1 2]
9387    * [3 4 5]
9388    * [6 7 8]
9389    */
9390
9391   if (gst_byte_reader_get_remaining (reader) < 36)
9392     return FALSE;
9393
9394   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9395   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9396   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9397   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9398   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9399   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9400   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9401   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9402   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9403
9404   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9405   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9406       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9407       matrix[2] & 0xFF);
9408   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9409       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9410       matrix[5] & 0xFF);
9411   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9412       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9413       matrix[8] & 0xFF);
9414
9415   return TRUE;
9416 }
9417
9418 static void
9419 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9420     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9421 {
9422
9423 /* [a b c]
9424  * [d e f]
9425  * [g h i]
9426  *
9427  * This macro will only compare value abdegh, it expects cfi to have already
9428  * been checked
9429  */
9430 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9431                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9432
9433   /* only handle the cases where the last column has standard values */
9434   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9435     const gchar *rotation_tag = NULL;
9436
9437     /* no rotation needed */
9438     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9439       /* NOP */
9440     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9441       rotation_tag = "rotate-90";
9442     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9443       rotation_tag = "rotate-180";
9444     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9445       rotation_tag = "rotate-270";
9446     } else {
9447       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9448     }
9449
9450     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9451         rotation_tag);
9452     if (rotation_tag != NULL) {
9453       if (*taglist == NULL)
9454         *taglist = gst_tag_list_new_empty ();
9455       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9456           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9457     }
9458   } else {
9459     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9460   }
9461 }
9462
9463 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9464  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9465  * Common Encryption (cenc), the function will also parse the tenc box (defined
9466  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9467  * (typically an enc[v|a|t|s] sample entry); the function will set
9468  * @original_fmt to the fourcc of the original unencrypted stream format.
9469  * Returns TRUE if successful; FALSE otherwise. */
9470 static gboolean
9471 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9472     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9473 {
9474   GNode *sinf;
9475   GNode *frma;
9476   GNode *schm;
9477   GNode *schi;
9478
9479   g_return_val_if_fail (qtdemux != NULL, FALSE);
9480   g_return_val_if_fail (stream != NULL, FALSE);
9481   g_return_val_if_fail (container != NULL, FALSE);
9482   g_return_val_if_fail (original_fmt != NULL, FALSE);
9483
9484   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9485   if (G_UNLIKELY (!sinf)) {
9486     if (stream->protection_scheme_type == FOURCC_cenc) {
9487       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9488           "mandatory for Common Encryption");
9489       return FALSE;
9490     }
9491     return TRUE;
9492   }
9493
9494   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9495   if (G_UNLIKELY (!frma)) {
9496     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9497     return FALSE;
9498   }
9499
9500   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9501   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9502       GST_FOURCC_ARGS (*original_fmt));
9503
9504   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9505   if (!schm) {
9506     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9507     return FALSE;
9508   }
9509   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9510   stream->protection_scheme_version =
9511       QT_UINT32 ((const guint8 *) schm->data + 16);
9512
9513   GST_DEBUG_OBJECT (qtdemux,
9514       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9515       "protection_scheme_version: %#010x",
9516       GST_FOURCC_ARGS (stream->protection_scheme_type),
9517       stream->protection_scheme_version);
9518
9519   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9520   if (!schi) {
9521     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9522     return FALSE;
9523   }
9524   if (stream->protection_scheme_type == FOURCC_cenc) {
9525     QtDemuxCencSampleSetInfo *info;
9526     GNode *tenc;
9527     const guint8 *tenc_data;
9528     guint32 isEncrypted;
9529     guint8 iv_size;
9530     const guint8 *default_kid;
9531     GstBuffer *kid_buf;
9532
9533     if (G_UNLIKELY (!stream->protection_scheme_info))
9534       stream->protection_scheme_info =
9535           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9536
9537     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9538
9539     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9540     if (!tenc) {
9541       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9542           "which is mandatory for Common Encryption");
9543       return FALSE;
9544     }
9545     tenc_data = (const guint8 *) tenc->data + 12;
9546     isEncrypted = QT_UINT24 (tenc_data);
9547     iv_size = QT_UINT8 (tenc_data + 3);
9548     default_kid = (tenc_data + 4);
9549     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9550     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9551     if (info->default_properties)
9552       gst_structure_free (info->default_properties);
9553     info->default_properties =
9554         gst_structure_new ("application/x-cenc",
9555         "iv_size", G_TYPE_UINT, iv_size,
9556         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9557         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9558     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9559         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9560     gst_buffer_unref (kid_buf);
9561   }
9562   return TRUE;
9563 }
9564
9565 /* parse the traks.
9566  * With each track we associate a new QtDemuxStream that contains all the info
9567  * about the trak.
9568  * traks that do not decode to something (like strm traks) will not have a pad.
9569  */
9570 static gboolean
9571 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9572 {
9573   GstByteReader tkhd;
9574   int offset;
9575   GNode *mdia;
9576   GNode *mdhd;
9577   GNode *hdlr;
9578   GNode *minf;
9579   GNode *stbl;
9580   GNode *stsd;
9581   GNode *mp4a;
9582   GNode *mp4v;
9583   GNode *wave;
9584   GNode *esds;
9585   GNode *pasp;
9586   GNode *colr;
9587   GNode *tref;
9588   GNode *udta;
9589   GNode *svmi;
9590   GNode *fiel;
9591
9592   QtDemuxStream *stream = NULL;
9593   gboolean new_stream = FALSE;
9594   gchar *codec = NULL;
9595   const guint8 *stsd_data;
9596   const guint8 *stsd_entry_data;
9597   guint remaining_stsd_len;
9598   guint stsd_entry_count;
9599   guint stsd_index;
9600   guint16 lang_code;            /* quicktime lang code or packed iso code */
9601   guint32 version;
9602   guint32 tkhd_flags = 0;
9603   guint8 tkhd_version = 0;
9604   guint32 w = 0, h = 0;
9605   guint32 fourcc;
9606   guint value_size, stsd_len, len;
9607   guint32 track_id;
9608   guint32 dummy;
9609
9610   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9611
9612   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9613       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9614       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9615     goto corrupt_file;
9616
9617   /* pick between 64 or 32 bits */
9618   value_size = tkhd_version == 1 ? 8 : 4;
9619   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9620       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9621     goto corrupt_file;
9622
9623   if (!qtdemux->got_moov) {
9624     if (qtdemux_find_stream (qtdemux, track_id))
9625       goto existing_stream;
9626     stream = _create_stream ();
9627     stream->track_id = track_id;
9628     new_stream = TRUE;
9629   } else {
9630     stream = qtdemux_find_stream (qtdemux, track_id);
9631     if (!stream) {
9632       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9633       goto skip_track;
9634     }
9635
9636     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
9637
9638     /* flush samples data from this track from previous moov */
9639     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9640     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9641   }
9642   /* need defaults for fragments */
9643   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9644
9645   if ((tkhd_flags & 1) == 0)
9646     stream->disabled = TRUE;
9647
9648   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9649       tkhd_version, tkhd_flags, stream->track_id);
9650
9651   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9652     goto corrupt_file;
9653
9654   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9655     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9656     if (qtdemux->major_brand != FOURCC_mjp2 ||
9657         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9658       goto corrupt_file;
9659   }
9660
9661   len = QT_UINT32 ((guint8 *) mdhd->data);
9662   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9663   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9664   if (version == 0x01000000) {
9665     if (len < 38)
9666       goto corrupt_file;
9667     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9668     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9669     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9670   } else {
9671     if (len < 30)
9672       goto corrupt_file;
9673     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9674     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9675     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9676   }
9677
9678   if (lang_code < 0x400) {
9679     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9680   } else if (lang_code == 0x7fff) {
9681     stream->lang_id[0] = 0;     /* unspecified */
9682   } else {
9683     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9684     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9685     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9686     stream->lang_id[3] = 0;
9687   }
9688
9689   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9690       stream->timescale);
9691   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9692       stream->duration);
9693   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9694       lang_code, stream->lang_id);
9695
9696   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9697     goto corrupt_file;
9698
9699   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9700     /* chapters track reference */
9701     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9702     if (chap) {
9703       gsize length = GST_READ_UINT32_BE (chap->data);
9704       if (qtdemux->chapters_track_id)
9705         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9706
9707       if (length >= 12) {
9708         qtdemux->chapters_track_id =
9709             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9710       }
9711     }
9712   }
9713
9714   /* fragmented files may have bogus duration in moov */
9715   if (!qtdemux->fragmented &&
9716       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9717     guint64 tdur1, tdur2;
9718
9719     /* don't overflow */
9720     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9721     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9722
9723     /* HACK:
9724      * some of those trailers, nowadays, have prologue images that are
9725      * themselves video tracks as well. I haven't really found a way to
9726      * identify those yet, except for just looking at their duration. */
9727     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9728       GST_WARNING_OBJECT (qtdemux,
9729           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9730           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9731           "found, assuming preview image or something; skipping track",
9732           stream->duration, stream->timescale, qtdemux->duration,
9733           qtdemux->timescale);
9734       if (new_stream)
9735         gst_qtdemux_stream_free (qtdemux, stream);
9736       return TRUE;
9737     }
9738   }
9739
9740   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9741     goto corrupt_file;
9742
9743   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9744       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9745
9746   len = QT_UINT32 ((guint8 *) hdlr->data);
9747   if (len >= 20)
9748     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9749   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9750       GST_FOURCC_ARGS (stream->subtype));
9751
9752   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9753     goto corrupt_file;
9754
9755   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9756     goto corrupt_file;
9757
9758   /*parse svmi header if existing */
9759   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9760   if (svmi) {
9761     len = QT_UINT32 ((guint8 *) svmi->data);
9762     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9763     if (!version) {
9764       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9765       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9766       guint8 frame_type, frame_layout;
9767
9768       /* MPEG-A stereo video */
9769       if (qtdemux->major_brand == FOURCC_ss02)
9770         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9771
9772       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9773       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9774       switch (frame_type) {
9775         case 0:
9776           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9777           break;
9778         case 1:
9779           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9780           break;
9781         case 2:
9782           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9783           break;
9784         case 3:
9785           /* mode 3 is primary/secondary view sequence, ie
9786            * left/right views in separate tracks. See section 7.2
9787            * of ISO/IEC 23000-11:2009 */
9788           GST_FIXME_OBJECT (qtdemux,
9789               "Implement stereo video in separate streams");
9790       }
9791
9792       if ((frame_layout & 0x1) == 0)
9793         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9794
9795       GST_LOG_OBJECT (qtdemux,
9796           "StereoVideo: composition type: %u, is_left_first: %u",
9797           frame_type, frame_layout);
9798       stream->multiview_mode = mode;
9799       stream->multiview_flags = flags;
9800     }
9801   }
9802
9803   /* parse rest of tkhd */
9804   if (stream->subtype == FOURCC_vide) {
9805     guint32 matrix[9];
9806
9807     /* version 1 uses some 64-bit ints */
9808     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9809       goto corrupt_file;
9810
9811     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9812       goto corrupt_file;
9813
9814     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9815         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9816       goto corrupt_file;
9817
9818     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9819         &stream->stream_tags);
9820   }
9821
9822   /* parse stsd */
9823   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9824     goto corrupt_file;
9825   stsd_data = (const guint8 *) stsd->data;
9826
9827   /* stsd should at least have one entry */
9828   stsd_len = QT_UINT32 (stsd_data);
9829   if (stsd_len < 24) {
9830     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9831     if (stream->subtype == FOURCC_vivo) {
9832       if (new_stream)
9833         gst_qtdemux_stream_free (qtdemux, stream);
9834       return TRUE;
9835     } else {
9836       goto corrupt_file;
9837     }
9838   }
9839
9840   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9841   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9842   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9843   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9844
9845   stsd_entry_data = stsd_data + 16;
9846   remaining_stsd_len = stsd_len - 16;
9847   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9848     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9849
9850     /* and that entry should fit within stsd */
9851     len = QT_UINT32 (stsd_entry_data);
9852     if (len > remaining_stsd_len)
9853       goto corrupt_file;
9854
9855     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9856     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9857         GST_FOURCC_ARGS (entry->fourcc));
9858     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9859
9860     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9861       goto error_encrypted;
9862
9863     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9864       /* FIXME this looks wrong, there might be multiple children
9865        * with the same type */
9866       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9867       stream->protected = TRUE;
9868       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9869         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9870     }
9871
9872     if (stream->subtype == FOURCC_vide) {
9873       gboolean gray;
9874       gint depth, palette_size, palette_count;
9875       guint32 *palette_data = NULL;
9876
9877       entry->sampled = TRUE;
9878
9879       stream->display_width = w >> 16;
9880       stream->display_height = h >> 16;
9881
9882       offset = 16;
9883       if (len < 86)             /* TODO verify */
9884         goto corrupt_file;
9885
9886       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
9887       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
9888       entry->fps_n = 0;         /* this is filled in later */
9889       entry->fps_d = 0;         /* this is filled in later */
9890       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
9891       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
9892
9893       /* if color_table_id is 0, ctab atom must follow; however some files
9894        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9895        * if color table is not present we'll correct the value */
9896       if (entry->color_table_id == 0 &&
9897           (len < 90
9898               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
9899         entry->color_table_id = -1;
9900       }
9901
9902       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9903           entry->width, entry->height, entry->bits_per_sample,
9904           entry->color_table_id);
9905
9906       depth = entry->bits_per_sample;
9907
9908       /* more than 32 bits means grayscale */
9909       gray = (depth > 32);
9910       /* low 32 bits specify the depth  */
9911       depth &= 0x1F;
9912
9913       /* different number of palette entries is determined by depth. */
9914       palette_count = 0;
9915       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9916         palette_count = (1 << depth);
9917       palette_size = palette_count * 4;
9918
9919       if (entry->color_table_id) {
9920         switch (palette_count) {
9921           case 0:
9922             break;
9923           case 2:
9924             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9925             break;
9926           case 4:
9927             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9928             break;
9929           case 16:
9930             if (gray)
9931               palette_data =
9932                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
9933             else
9934               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9935             break;
9936           case 256:
9937             if (gray)
9938               palette_data =
9939                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
9940             else
9941               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9942             break;
9943           default:
9944             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9945                 (_("The video in this file might not play correctly.")),
9946                 ("unsupported palette depth %d", depth));
9947             break;
9948         }
9949       } else {
9950         gint i, j, start, end;
9951
9952         if (len < 94)
9953           goto corrupt_file;
9954
9955         /* read table */
9956         start = QT_UINT32 (stsd_entry_data + offset + 70);
9957         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
9958         end = QT_UINT16 (stsd_entry_data + offset + 76);
9959
9960         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9961             start, end, palette_count);
9962
9963         if (end > 255)
9964           end = 255;
9965         if (start > end)
9966           start = end;
9967
9968         if (len < 94 + (end - start) * 8)
9969           goto corrupt_file;
9970
9971         /* palette is always the same size */
9972         palette_data = g_malloc0 (256 * 4);
9973         palette_size = 256 * 4;
9974
9975         for (j = 0, i = start; i <= end; j++, i++) {
9976           guint32 a, r, g, b;
9977
9978           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
9979           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
9980           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
9981           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
9982
9983           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9984               (g & 0xff00) | (b >> 8);
9985         }
9986       }
9987
9988       if (entry->caps)
9989         gst_caps_unref (entry->caps);
9990
9991       entry->caps =
9992           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
9993           &codec);
9994       if (G_UNLIKELY (!entry->caps)) {
9995         g_free (palette_data);
9996         goto unknown_stream;
9997       }
9998
9999       if (codec) {
10000         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10001             GST_TAG_VIDEO_CODEC, codec, NULL);
10002         g_free (codec);
10003         codec = NULL;
10004       }
10005
10006       if (palette_data) {
10007         GstStructure *s;
10008
10009         if (entry->rgb8_palette)
10010           gst_memory_unref (entry->rgb8_palette);
10011         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10012             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10013
10014         s = gst_caps_get_structure (entry->caps, 0);
10015
10016         /* non-raw video has a palette_data property. raw video has the palette as
10017          * an extra plane that we append to the output buffers before we push
10018          * them*/
10019         if (!gst_structure_has_name (s, "video/x-raw")) {
10020           GstBuffer *palette;
10021
10022           palette = gst_buffer_new ();
10023           gst_buffer_append_memory (palette, entry->rgb8_palette);
10024           entry->rgb8_palette = NULL;
10025
10026           gst_caps_set_simple (entry->caps, "palette_data",
10027               GST_TYPE_BUFFER, palette, NULL);
10028           gst_buffer_unref (palette);
10029         }
10030       } else if (palette_count != 0) {
10031         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10032             (NULL), ("Unsupported palette depth %d", depth));
10033       }
10034
10035       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10036           QT_UINT16 (stsd_entry_data + offset + 32));
10037
10038       esds = NULL;
10039       pasp = NULL;
10040       colr = NULL;
10041       fiel = NULL;
10042       /* pick 'the' stsd child */
10043       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10044       if (!stream->protected) {
10045         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10046           mp4v = NULL;
10047         }
10048       } else {
10049         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10050           mp4v = NULL;
10051         }
10052       }
10053
10054       if (mp4v) {
10055         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10056         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10057         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10058         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10059       }
10060
10061       if (pasp) {
10062         const guint8 *pasp_data = (const guint8 *) pasp->data;
10063         gint len = QT_UINT32 (pasp_data);
10064
10065         if (len == 16) {
10066           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10067           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10068         } else {
10069           CUR_STREAM (stream)->par_w = 0;
10070           CUR_STREAM (stream)->par_h = 0;
10071         }
10072       } else {
10073         CUR_STREAM (stream)->par_w = 0;
10074         CUR_STREAM (stream)->par_h = 0;
10075       }
10076
10077       if (fiel) {
10078         const guint8 *fiel_data = (const guint8 *) fiel->data;
10079         gint len = QT_UINT32 (fiel_data);
10080
10081         if (len == 10) {
10082           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10083           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10084         }
10085       }
10086
10087       if (colr) {
10088         const guint8 *colr_data = (const guint8 *) colr->data;
10089         gint len = QT_UINT32 (colr_data);
10090
10091         if (len == 19 || len == 18) {
10092           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10093
10094           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10095             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10096             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10097             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10098             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10099
10100             switch (primaries) {
10101               case 1:
10102                 CUR_STREAM (stream)->colorimetry.primaries =
10103                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10104                 break;
10105               case 5:
10106                 CUR_STREAM (stream)->colorimetry.primaries =
10107                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10108                 break;
10109               case 6:
10110                 CUR_STREAM (stream)->colorimetry.primaries =
10111                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10112                 break;
10113               case 9:
10114                 CUR_STREAM (stream)->colorimetry.primaries =
10115                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10116                 break;
10117               default:
10118                 break;
10119             }
10120
10121             switch (transfer_function) {
10122               case 1:
10123                 CUR_STREAM (stream)->colorimetry.transfer =
10124                     GST_VIDEO_TRANSFER_BT709;
10125                 break;
10126               case 7:
10127                 CUR_STREAM (stream)->colorimetry.transfer =
10128                     GST_VIDEO_TRANSFER_SMPTE240M;
10129                 break;
10130               default:
10131                 break;
10132             }
10133
10134             switch (matrix) {
10135               case 1:
10136                 CUR_STREAM (stream)->colorimetry.matrix =
10137                     GST_VIDEO_COLOR_MATRIX_BT709;
10138                 break;
10139               case 6:
10140                 CUR_STREAM (stream)->colorimetry.matrix =
10141                     GST_VIDEO_COLOR_MATRIX_BT601;
10142                 break;
10143               case 7:
10144                 CUR_STREAM (stream)->colorimetry.matrix =
10145                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10146                 break;
10147               case 9:
10148                 CUR_STREAM (stream)->colorimetry.matrix =
10149                     GST_VIDEO_COLOR_MATRIX_BT2020;
10150                 break;
10151               default:
10152                 break;
10153             }
10154
10155             CUR_STREAM (stream)->colorimetry.range =
10156                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10157                 GST_VIDEO_COLOR_RANGE_16_235;
10158           } else {
10159             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10160           }
10161         } else {
10162           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10163         }
10164       }
10165
10166       if (esds) {
10167         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10168             stream->stream_tags);
10169       } else {
10170         switch (fourcc) {
10171           case FOURCC_H264:
10172           case FOURCC_avc1:
10173           case FOURCC_avc3:
10174           {
10175             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10176             const guint8 *avc_data = stsd_entry_data + 0x56;
10177
10178             /* find avcC */
10179             while (len >= 0x8) {
10180               gint size;
10181
10182               if (QT_UINT32 (avc_data) <= len)
10183                 size = QT_UINT32 (avc_data) - 0x8;
10184               else
10185                 size = len - 0x8;
10186
10187               if (size < 1)
10188                 /* No real data, so break out */
10189                 break;
10190
10191               switch (QT_FOURCC (avc_data + 0x4)) {
10192                 case FOURCC_avcC:
10193                 {
10194                   /* parse, if found */
10195                   GstBuffer *buf;
10196
10197                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10198
10199                   /* First 4 bytes are the length of the atom, the next 4 bytes
10200                    * are the fourcc, the next 1 byte is the version, and the
10201                    * subsequent bytes are profile_tier_level structure like data. */
10202                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10203                       avc_data + 8 + 1, size - 1);
10204                   buf = gst_buffer_new_and_alloc (size);
10205                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10206                   gst_caps_set_simple (entry->caps,
10207                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10208                   gst_buffer_unref (buf);
10209
10210                   break;
10211                 }
10212                 case FOURCC_strf:
10213                 {
10214                   GstBuffer *buf;
10215
10216                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10217
10218                   /* First 4 bytes are the length of the atom, the next 4 bytes
10219                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10220                    * next 1 byte is the version, and the
10221                    * subsequent bytes are sequence parameter set like data. */
10222
10223                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10224                   if (size > 1) {
10225                     gst_codec_utils_h264_caps_set_level_and_profile
10226                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10227
10228                     buf = gst_buffer_new_and_alloc (size);
10229                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10230                     gst_caps_set_simple (entry->caps,
10231                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10232                     gst_buffer_unref (buf);
10233                   }
10234                   break;
10235                 }
10236                 case FOURCC_btrt:
10237                 {
10238                   guint avg_bitrate, max_bitrate;
10239
10240                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10241                   if (size < 12)
10242                     break;
10243
10244                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10245                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10246
10247                   if (!max_bitrate && !avg_bitrate)
10248                     break;
10249
10250                   /* Some muxers seem to swap the average and maximum bitrates
10251                    * (I'm looking at you, YouTube), so we swap for sanity. */
10252                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10253                     guint temp = avg_bitrate;
10254
10255                     avg_bitrate = max_bitrate;
10256                     max_bitrate = temp;
10257                   }
10258
10259                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10260                     gst_tag_list_add (stream->stream_tags,
10261                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10262                         max_bitrate, NULL);
10263                   }
10264                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10265                     gst_tag_list_add (stream->stream_tags,
10266                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10267                         NULL);
10268                   }
10269
10270                   break;
10271                 }
10272
10273                 default:
10274                   break;
10275               }
10276
10277               len -= size + 8;
10278               avc_data += size + 8;
10279             }
10280
10281             break;
10282           }
10283           case FOURCC_H265:
10284           case FOURCC_hvc1:
10285           case FOURCC_hev1:
10286           {
10287             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10288             const guint8 *hevc_data = stsd_entry_data + 0x56;
10289
10290             /* find hevc */
10291             while (len >= 0x8) {
10292               gint size;
10293
10294               if (QT_UINT32 (hevc_data) <= len)
10295                 size = QT_UINT32 (hevc_data) - 0x8;
10296               else
10297                 size = len - 0x8;
10298
10299               if (size < 1)
10300                 /* No real data, so break out */
10301                 break;
10302
10303               switch (QT_FOURCC (hevc_data + 0x4)) {
10304                 case FOURCC_hvcC:
10305                 {
10306                   /* parse, if found */
10307                   GstBuffer *buf;
10308
10309                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10310
10311                   /* First 4 bytes are the length of the atom, the next 4 bytes
10312                    * are the fourcc, the next 1 byte is the version, and the
10313                    * subsequent bytes are sequence parameter set like data. */
10314                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10315                       (entry->caps, hevc_data + 8 + 1, size - 1);
10316
10317                   buf = gst_buffer_new_and_alloc (size);
10318                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10319                   gst_caps_set_simple (entry->caps,
10320                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10321                   gst_buffer_unref (buf);
10322                   break;
10323                 }
10324                 default:
10325                   break;
10326               }
10327               len -= size + 8;
10328               hevc_data += size + 8;
10329             }
10330             break;
10331           }
10332           case FOURCC_mp4v:
10333           case FOURCC_MP4V:
10334           case FOURCC_fmp4:
10335           case FOURCC_FMP4:
10336           case FOURCC_xvid:
10337           case FOURCC_XVID:
10338           {
10339             GNode *glbl;
10340
10341             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10342                 GST_FOURCC_ARGS (fourcc));
10343
10344             /* codec data might be in glbl extension atom */
10345             glbl = mp4v ?
10346                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10347             if (glbl) {
10348               guint8 *data;
10349               GstBuffer *buf;
10350               gint len;
10351
10352               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10353               data = glbl->data;
10354               len = QT_UINT32 (data);
10355               if (len > 0x8) {
10356                 len -= 0x8;
10357                 buf = gst_buffer_new_and_alloc (len);
10358                 gst_buffer_fill (buf, 0, data + 8, len);
10359                 gst_caps_set_simple (entry->caps,
10360                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10361                 gst_buffer_unref (buf);
10362               }
10363             }
10364             break;
10365           }
10366           case FOURCC_mjp2:
10367           {
10368             /* see annex I of the jpeg2000 spec */
10369             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10370             const guint8 *data;
10371             const gchar *colorspace = NULL;
10372             gint ncomp = 0;
10373             guint32 ncomp_map = 0;
10374             gint32 *comp_map = NULL;
10375             guint32 nchan_def = 0;
10376             gint32 *chan_def = NULL;
10377
10378             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10379             /* some required atoms */
10380             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10381             if (!mjp2)
10382               break;
10383             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10384             if (!jp2h)
10385               break;
10386
10387             /* number of components; redundant with info in codestream, but useful
10388                to a muxer */
10389             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10390             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10391               break;
10392             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10393
10394             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10395             if (!colr)
10396               break;
10397             GST_DEBUG_OBJECT (qtdemux, "found colr");
10398             /* extract colour space info */
10399             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10400               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10401                 case 16:
10402                   colorspace = "sRGB";
10403                   break;
10404                 case 17:
10405                   colorspace = "GRAY";
10406                   break;
10407                 case 18:
10408                   colorspace = "sYUV";
10409                   break;
10410                 default:
10411                   colorspace = NULL;
10412                   break;
10413               }
10414             }
10415             if (!colorspace)
10416               /* colr is required, and only values 16, 17, and 18 are specified,
10417                  so error if we have no colorspace */
10418               break;
10419
10420             /* extract component mapping */
10421             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10422             if (cmap) {
10423               guint32 cmap_len = 0;
10424               int i;
10425               cmap_len = QT_UINT32 (cmap->data);
10426               if (cmap_len >= 8) {
10427                 /* normal box, subtract off header */
10428                 cmap_len -= 8;
10429                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10430                 if (cmap_len % 4 == 0) {
10431                   ncomp_map = (cmap_len / 4);
10432                   comp_map = g_new0 (gint32, ncomp_map);
10433                   for (i = 0; i < ncomp_map; i++) {
10434                     guint16 cmp;
10435                     guint8 mtyp, pcol;
10436                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10437                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10438                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10439                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10440                   }
10441                 }
10442               }
10443             }
10444             /* extract channel definitions */
10445             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10446             if (cdef) {
10447               guint32 cdef_len = 0;
10448               int i;
10449               cdef_len = QT_UINT32 (cdef->data);
10450               if (cdef_len >= 10) {
10451                 /* normal box, subtract off header and len */
10452                 cdef_len -= 10;
10453                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10454                 if (cdef_len % 6 == 0) {
10455                   nchan_def = (cdef_len / 6);
10456                   chan_def = g_new0 (gint32, nchan_def);
10457                   for (i = 0; i < nchan_def; i++)
10458                     chan_def[i] = -1;
10459                   for (i = 0; i < nchan_def; i++) {
10460                     guint16 cn, typ, asoc;
10461                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10462                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10463                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10464                     if (cn < nchan_def) {
10465                       switch (typ) {
10466                         case 0:
10467                           chan_def[cn] = asoc;
10468                           break;
10469                         case 1:
10470                           chan_def[cn] = 0;     /* alpha */
10471                           break;
10472                         default:
10473                           chan_def[cn] = -typ;
10474                       }
10475                     }
10476                   }
10477                 }
10478               }
10479             }
10480
10481             gst_caps_set_simple (entry->caps,
10482                 "num-components", G_TYPE_INT, ncomp, NULL);
10483             gst_caps_set_simple (entry->caps,
10484                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10485
10486             if (comp_map) {
10487               GValue arr = { 0, };
10488               GValue elt = { 0, };
10489               int i;
10490               g_value_init (&arr, GST_TYPE_ARRAY);
10491               g_value_init (&elt, G_TYPE_INT);
10492               for (i = 0; i < ncomp_map; i++) {
10493                 g_value_set_int (&elt, comp_map[i]);
10494                 gst_value_array_append_value (&arr, &elt);
10495               }
10496               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10497                   "component-map", &arr);
10498               g_value_unset (&elt);
10499               g_value_unset (&arr);
10500               g_free (comp_map);
10501             }
10502
10503             if (chan_def) {
10504               GValue arr = { 0, };
10505               GValue elt = { 0, };
10506               int i;
10507               g_value_init (&arr, GST_TYPE_ARRAY);
10508               g_value_init (&elt, G_TYPE_INT);
10509               for (i = 0; i < nchan_def; i++) {
10510                 g_value_set_int (&elt, chan_def[i]);
10511                 gst_value_array_append_value (&arr, &elt);
10512               }
10513               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10514                   "channel-definitions", &arr);
10515               g_value_unset (&elt);
10516               g_value_unset (&arr);
10517               g_free (chan_def);
10518             }
10519
10520             /* some optional atoms */
10521             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10522             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10523
10524             /* indicate possible fields in caps */
10525             if (field) {
10526               data = (guint8 *) field->data + 8;
10527               if (*data != 1)
10528                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10529                     (gint) * data, NULL);
10530             }
10531             /* add codec_data if provided */
10532             if (prefix) {
10533               GstBuffer *buf;
10534               gint len;
10535
10536               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10537               data = prefix->data;
10538               len = QT_UINT32 (data);
10539               if (len > 0x8) {
10540                 len -= 0x8;
10541                 buf = gst_buffer_new_and_alloc (len);
10542                 gst_buffer_fill (buf, 0, data + 8, len);
10543                 gst_caps_set_simple (entry->caps,
10544                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10545                 gst_buffer_unref (buf);
10546               }
10547             }
10548             break;
10549           }
10550           case FOURCC_SVQ3:
10551           case FOURCC_VP31:
10552           {
10553             GstBuffer *buf;
10554             GstBuffer *seqh = NULL;
10555             const guint8 *gamma_data = NULL;
10556             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10557
10558             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10559                 &seqh);
10560             if (gamma_data) {
10561               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10562                   QT_FP32 (gamma_data), NULL);
10563             }
10564             if (seqh) {
10565               /* sorry for the bad name, but we don't know what this is, other
10566                * than its own fourcc */
10567               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10568                   NULL);
10569               gst_buffer_unref (seqh);
10570             }
10571
10572             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10573             buf = gst_buffer_new_and_alloc (len);
10574             gst_buffer_fill (buf, 0, stsd_data, len);
10575             gst_caps_set_simple (entry->caps,
10576                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10577             gst_buffer_unref (buf);
10578             break;
10579           }
10580           case FOURCC_jpeg:
10581           {
10582             /* https://developer.apple.com/standards/qtff-2001.pdf,
10583              * page 92, "Video Sample Description", under table 3.1 */
10584             GstByteReader br;
10585
10586             const gint compressor_offset =
10587                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10588             const gint min_size = compressor_offset + 32 + 2 + 2;
10589             GNode *jpeg;
10590             guint32 len;
10591             guint16 color_table_id = 0;
10592             gboolean ok;
10593
10594             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10595
10596             /* recover information on interlaced/progressive */
10597             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10598             if (!jpeg)
10599               break;
10600
10601             len = QT_UINT32 (jpeg->data);
10602             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10603                 min_size);
10604             if (len >= min_size) {
10605               gst_byte_reader_init (&br, jpeg->data, len);
10606
10607               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10608               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10609               if (color_table_id != 0) {
10610                 /* the spec says there can be concatenated chunks in the data, and we want
10611                  * to find one called field. Walk through them. */
10612                 gint offset = min_size;
10613                 while (offset + 8 < len) {
10614                   guint32 size = 0, tag;
10615                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10616                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10617                   if (!ok || size < 8) {
10618                     GST_WARNING_OBJECT (qtdemux,
10619                         "Failed to walk optional chunk list");
10620                     break;
10621                   }
10622                   GST_DEBUG_OBJECT (qtdemux,
10623                       "Found optional %4.4s chunk, size %u",
10624                       (const char *) &tag, size);
10625                   if (tag == FOURCC_fiel) {
10626                     guint8 n_fields = 0, ordering = 0;
10627                     gst_byte_reader_get_uint8 (&br, &n_fields);
10628                     gst_byte_reader_get_uint8 (&br, &ordering);
10629                     if (n_fields == 1 || n_fields == 2) {
10630                       GST_DEBUG_OBJECT (qtdemux,
10631                           "Found fiel tag with %u fields, ordering %u",
10632                           n_fields, ordering);
10633                       if (n_fields == 2)
10634                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10635                             "interlace-mode", G_TYPE_STRING, "interleaved",
10636                             NULL);
10637                     } else {
10638                       GST_WARNING_OBJECT (qtdemux,
10639                           "Found fiel tag with invalid fields (%u)", n_fields);
10640                     }
10641                   }
10642                   offset += size;
10643                 }
10644               } else {
10645                 GST_DEBUG_OBJECT (qtdemux,
10646                     "Color table ID is 0, not trying to get interlacedness");
10647               }
10648             } else {
10649               GST_WARNING_OBJECT (qtdemux,
10650                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10651             }
10652
10653             break;
10654           }
10655           case FOURCC_rle_:
10656           case FOURCC_WRLE:
10657           {
10658             gst_caps_set_simple (entry->caps,
10659                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
10660                 NULL);
10661             break;
10662           }
10663           case FOURCC_XiTh:
10664           {
10665             GNode *xith, *xdxt;
10666
10667             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10668             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10669             if (!xith)
10670               break;
10671
10672             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10673             if (!xdxt)
10674               break;
10675
10676             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10677             /* collect the headers and store them in a stream list so that we can
10678              * send them out first */
10679             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10680             break;
10681           }
10682           case FOURCC_ovc1:
10683           {
10684             GNode *ovc1;
10685             guint8 *ovc1_data;
10686             guint ovc1_len;
10687             GstBuffer *buf;
10688
10689             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10690             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10691             if (!ovc1)
10692               break;
10693             ovc1_data = ovc1->data;
10694             ovc1_len = QT_UINT32 (ovc1_data);
10695             if (ovc1_len <= 198) {
10696               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10697               break;
10698             }
10699             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10700             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10701             gst_caps_set_simple (entry->caps,
10702                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10703             gst_buffer_unref (buf);
10704             break;
10705           }
10706           case FOURCC_vc_1:
10707           {
10708             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10709             const guint8 *vc1_data = stsd_entry_data + 0x56;
10710
10711             /* find dvc1 */
10712             while (len >= 8) {
10713               gint size;
10714
10715               if (QT_UINT32 (vc1_data) <= len)
10716                 size = QT_UINT32 (vc1_data) - 8;
10717               else
10718                 size = len - 8;
10719
10720               if (size < 1)
10721                 /* No real data, so break out */
10722                 break;
10723
10724               switch (QT_FOURCC (vc1_data + 0x4)) {
10725                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10726                 {
10727                   GstBuffer *buf;
10728
10729                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10730                   buf = gst_buffer_new_and_alloc (size);
10731                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10732                   gst_caps_set_simple (entry->caps,
10733                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10734                   gst_buffer_unref (buf);
10735                   break;
10736                 }
10737                 default:
10738                   break;
10739               }
10740               len -= size + 8;
10741               vc1_data += size + 8;
10742             }
10743             break;
10744           }
10745           default:
10746             break;
10747         }
10748       }
10749
10750       GST_INFO_OBJECT (qtdemux,
10751           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10752           GST_FOURCC_ARGS (fourcc), entry->caps);
10753
10754     } else if (stream->subtype == FOURCC_soun) {
10755       int version, samplesize;
10756       guint16 compression_id;
10757       gboolean amrwb = FALSE;
10758
10759       offset = 16;
10760       /* sample description entry (16) + sound sample description v0 (20) */
10761       if (len < 36)
10762         goto corrupt_file;
10763
10764       version = QT_UINT32 (stsd_entry_data + offset);
10765       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10766       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10767       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10768       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10769
10770       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10771       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10772           QT_UINT32 (stsd_entry_data + offset + 4));
10773       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10774       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10775       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10776       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10777           QT_UINT16 (stsd_entry_data + offset + 14));
10778       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10779
10780       if (compression_id == 0xfffe)
10781         entry->sampled = TRUE;
10782
10783       /* first assume uncompressed audio */
10784       entry->bytes_per_sample = samplesize / 8;
10785       entry->samples_per_frame = entry->n_channels;
10786       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10787       entry->samples_per_packet = entry->samples_per_frame;
10788       entry->bytes_per_packet = entry->bytes_per_sample;
10789
10790       offset = 36;
10791       switch (fourcc) {
10792           /* Yes, these have to be hard-coded */
10793         case FOURCC_MAC6:
10794         {
10795           entry->samples_per_packet = 6;
10796           entry->bytes_per_packet = 1;
10797           entry->bytes_per_frame = 1 * entry->n_channels;
10798           entry->bytes_per_sample = 1;
10799           entry->samples_per_frame = 6 * entry->n_channels;
10800           break;
10801         }
10802         case FOURCC_MAC3:
10803         {
10804           entry->samples_per_packet = 3;
10805           entry->bytes_per_packet = 1;
10806           entry->bytes_per_frame = 1 * entry->n_channels;
10807           entry->bytes_per_sample = 1;
10808           entry->samples_per_frame = 3 * entry->n_channels;
10809           break;
10810         }
10811         case FOURCC_ima4:
10812         {
10813           entry->samples_per_packet = 64;
10814           entry->bytes_per_packet = 34;
10815           entry->bytes_per_frame = 34 * entry->n_channels;
10816           entry->bytes_per_sample = 2;
10817           entry->samples_per_frame = 64 * entry->n_channels;
10818           break;
10819         }
10820         case FOURCC_ulaw:
10821         case FOURCC_alaw:
10822         {
10823           entry->samples_per_packet = 1;
10824           entry->bytes_per_packet = 1;
10825           entry->bytes_per_frame = 1 * entry->n_channels;
10826           entry->bytes_per_sample = 1;
10827           entry->samples_per_frame = 1 * entry->n_channels;
10828           break;
10829         }
10830         case FOURCC_agsm:
10831         {
10832           entry->samples_per_packet = 160;
10833           entry->bytes_per_packet = 33;
10834           entry->bytes_per_frame = 33 * entry->n_channels;
10835           entry->bytes_per_sample = 2;
10836           entry->samples_per_frame = 160 * entry->n_channels;
10837           break;
10838         }
10839         default:
10840           break;
10841       }
10842
10843       if (version == 0x00010000) {
10844         /* sample description entry (16) + sound sample description v1 (20+16) */
10845         if (len < 52)
10846           goto corrupt_file;
10847
10848         switch (fourcc) {
10849           case FOURCC_twos:
10850           case FOURCC_sowt:
10851           case FOURCC_raw_:
10852             break;
10853           default:
10854           {
10855             /* only parse extra decoding config for non-pcm audio */
10856             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10857             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10858             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10859             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10860
10861             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10862                 entry->samples_per_packet);
10863             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10864                 entry->bytes_per_packet);
10865             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10866                 entry->bytes_per_frame);
10867             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10868                 entry->bytes_per_sample);
10869
10870             if (!entry->sampled && entry->bytes_per_packet) {
10871               entry->samples_per_frame = (entry->bytes_per_frame /
10872                   entry->bytes_per_packet) * entry->samples_per_packet;
10873               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10874                   entry->samples_per_frame);
10875             }
10876             break;
10877           }
10878         }
10879       } else if (version == 0x00020000) {
10880         union
10881         {
10882           gdouble fp;
10883           guint64 val;
10884         } qtfp;
10885
10886         /* sample description entry (16) + sound sample description v2 (56) */
10887         if (len < 72)
10888           goto corrupt_file;
10889
10890         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
10891         entry->rate = qtfp.fp;
10892         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
10893
10894         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10895         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
10896         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
10897         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10898             QT_UINT32 (stsd_entry_data + offset + 20));
10899         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10900             QT_UINT32 (stsd_entry_data + offset + 24));
10901         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10902             QT_UINT32 (stsd_entry_data + offset + 28));
10903         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10904             QT_UINT32 (stsd_entry_data + offset + 32));
10905       } else if (version != 0x00000) {
10906         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
10907             version);
10908       }
10909
10910       if (entry->caps)
10911         gst_caps_unref (entry->caps);
10912
10913       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
10914           stsd_entry_data + 32, len - 16, &codec);
10915
10916       switch (fourcc) {
10917         case FOURCC_in24:
10918         {
10919           GNode *enda;
10920           GNode *in24;
10921
10922           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10923
10924           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10925           if (!enda) {
10926             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10927             if (wave)
10928               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10929           }
10930           if (enda) {
10931             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10932             gst_caps_set_simple (entry->caps,
10933                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
10934                 NULL);
10935           }
10936           break;
10937         }
10938         case FOURCC_owma:
10939         {
10940           const guint8 *owma_data;
10941           const gchar *codec_name = NULL;
10942           guint owma_len;
10943           GstBuffer *buf;
10944           gint version = 1;
10945           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10946           /* FIXME this should also be gst_riff_strf_auds,
10947            * but the latter one is actually missing bits-per-sample :( */
10948           typedef struct
10949           {
10950             gint16 wFormatTag;
10951             gint16 nChannels;
10952             gint32 nSamplesPerSec;
10953             gint32 nAvgBytesPerSec;
10954             gint16 nBlockAlign;
10955             gint16 wBitsPerSample;
10956             gint16 cbSize;
10957           } WAVEFORMATEX;
10958           WAVEFORMATEX *wfex;
10959
10960           GST_DEBUG_OBJECT (qtdemux, "parse owma");
10961           owma_data = stsd_entry_data;
10962           owma_len = QT_UINT32 (owma_data);
10963           if (owma_len <= 54) {
10964             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10965             break;
10966           }
10967           wfex = (WAVEFORMATEX *) (owma_data + 36);
10968           buf = gst_buffer_new_and_alloc (owma_len - 54);
10969           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10970           if (wfex->wFormatTag == 0x0161) {
10971             codec_name = "Windows Media Audio";
10972             version = 2;
10973           } else if (wfex->wFormatTag == 0x0162) {
10974             codec_name = "Windows Media Audio 9 Pro";
10975             version = 3;
10976           } else if (wfex->wFormatTag == 0x0163) {
10977             codec_name = "Windows Media Audio 9 Lossless";
10978             /* is that correct? gstffmpegcodecmap.c is missing it, but
10979              * fluendo codec seems to support it */
10980             version = 4;
10981           }
10982
10983           gst_caps_set_simple (entry->caps,
10984               "codec_data", GST_TYPE_BUFFER, buf,
10985               "wmaversion", G_TYPE_INT, version,
10986               "block_align", G_TYPE_INT,
10987               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
10988               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
10989               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
10990               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
10991           gst_buffer_unref (buf);
10992
10993           if (codec_name) {
10994             g_free (codec);
10995             codec = g_strdup (codec_name);
10996           }
10997           break;
10998         }
10999         case FOURCC_wma_:
11000         {
11001           gint len = QT_UINT32 (stsd_entry_data) - offset;
11002           const guint8 *wfex_data = stsd_entry_data + offset;
11003           const gchar *codec_name = NULL;
11004           gint version = 1;
11005           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11006           /* FIXME this should also be gst_riff_strf_auds,
11007            * but the latter one is actually missing bits-per-sample :( */
11008           typedef struct
11009           {
11010             gint16 wFormatTag;
11011             gint16 nChannels;
11012             gint32 nSamplesPerSec;
11013             gint32 nAvgBytesPerSec;
11014             gint16 nBlockAlign;
11015             gint16 wBitsPerSample;
11016             gint16 cbSize;
11017           } WAVEFORMATEX;
11018           WAVEFORMATEX wfex;
11019
11020           /* FIXME: unify with similar wavformatex parsing code above */
11021           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11022
11023           /* find wfex */
11024           while (len >= 8) {
11025             gint size;
11026
11027             if (QT_UINT32 (wfex_data) <= len)
11028               size = QT_UINT32 (wfex_data) - 8;
11029             else
11030               size = len - 8;
11031
11032             if (size < 1)
11033               /* No real data, so break out */
11034               break;
11035
11036             switch (QT_FOURCC (wfex_data + 4)) {
11037               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11038               {
11039                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11040
11041                 if (size < 8 + 18)
11042                   break;
11043
11044                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11045                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11046                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11047                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11048                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11049                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11050                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11051
11052                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11053                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11054                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11055                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11056                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11057                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11058
11059                 if (wfex.wFormatTag == 0x0161) {
11060                   codec_name = "Windows Media Audio";
11061                   version = 2;
11062                 } else if (wfex.wFormatTag == 0x0162) {
11063                   codec_name = "Windows Media Audio 9 Pro";
11064                   version = 3;
11065                 } else if (wfex.wFormatTag == 0x0163) {
11066                   codec_name = "Windows Media Audio 9 Lossless";
11067                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11068                    * fluendo codec seems to support it */
11069                   version = 4;
11070                 }
11071
11072                 gst_caps_set_simple (entry->caps,
11073                     "wmaversion", G_TYPE_INT, version,
11074                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11075                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11076                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11077                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11078
11079                 if (size > wfex.cbSize) {
11080                   GstBuffer *buf;
11081
11082                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11083                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11084                       size - wfex.cbSize);
11085                   gst_caps_set_simple (entry->caps,
11086                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11087                   gst_buffer_unref (buf);
11088                 } else {
11089                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11090                 }
11091
11092                 if (codec_name) {
11093                   g_free (codec);
11094                   codec = g_strdup (codec_name);
11095                 }
11096                 break;
11097               }
11098               default:
11099                 break;
11100             }
11101             len -= size + 8;
11102             wfex_data += size + 8;
11103           }
11104           break;
11105         }
11106         case FOURCC_opus:
11107         {
11108           const guint8 *opus_data;
11109           guint8 *channel_mapping = NULL;
11110           guint32 rate;
11111           guint8 channels;
11112           guint8 channel_mapping_family;
11113           guint8 stream_count;
11114           guint8 coupled_count;
11115           guint8 i;
11116
11117           opus_data = stsd_entry_data;
11118
11119           channels = GST_READ_UINT8 (opus_data + 45);
11120           rate = GST_READ_UINT32_LE (opus_data + 48);
11121           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11122           stream_count = GST_READ_UINT8 (opus_data + 55);
11123           coupled_count = GST_READ_UINT8 (opus_data + 56);
11124
11125           if (channels > 0) {
11126             channel_mapping = g_malloc (channels * sizeof (guint8));
11127             for (i = 0; i < channels; i++)
11128               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11129           }
11130
11131           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11132               channel_mapping_family, stream_count, coupled_count,
11133               channel_mapping);
11134           break;
11135         }
11136         default:
11137           break;
11138       }
11139
11140       if (codec) {
11141         GstStructure *s;
11142         gint bitrate = 0;
11143
11144         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11145             GST_TAG_AUDIO_CODEC, codec, NULL);
11146         g_free (codec);
11147         codec = NULL;
11148
11149         /* some bitrate info may have ended up in caps */
11150         s = gst_caps_get_structure (entry->caps, 0);
11151         gst_structure_get_int (s, "bitrate", &bitrate);
11152         if (bitrate > 0)
11153           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11154               GST_TAG_BITRATE, bitrate, NULL);
11155       }
11156
11157       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11158       if (!stream->protected) {
11159       } else {
11160         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11161           mp4v = NULL;
11162         }
11163       }
11164       if (stream->protected && fourcc == FOURCC_mp4a) {
11165         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11166           mp4a = NULL;
11167         }
11168       } else {
11169         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11170           mp4a = NULL;
11171         }
11172       }
11173
11174       wave = NULL;
11175       esds = NULL;
11176       if (mp4a) {
11177         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11178         if (wave)
11179           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11180         if (!esds)
11181           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11182       }
11183
11184
11185       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11186          16 bits is a byte-swapped wave-style codec identifier,
11187          and we can find a WAVE header internally to a 'wave' atom here.
11188          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11189          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11190          is big-endian).
11191        */
11192       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11193         if (len < offset + 20) {
11194           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11195         } else {
11196           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11197           const guint8 *data = stsd_entry_data + offset + 16;
11198           GNode *wavenode;
11199           GNode *waveheadernode;
11200
11201           wavenode = g_node_new ((guint8 *) data);
11202           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11203             const guint8 *waveheader;
11204             guint32 headerlen;
11205
11206             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11207             if (waveheadernode) {
11208               waveheader = (const guint8 *) waveheadernode->data;
11209               headerlen = QT_UINT32 (waveheader);
11210
11211               if (headerlen > 8) {
11212                 gst_riff_strf_auds *header = NULL;
11213                 GstBuffer *headerbuf;
11214                 GstBuffer *extra;
11215
11216                 waveheader += 8;
11217                 headerlen -= 8;
11218
11219                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11220                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11221
11222                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11223                         headerbuf, &header, &extra)) {
11224                   gst_caps_unref (entry->caps);
11225                   /* FIXME: Need to do something with the channel reorder map */
11226                   entry->caps =
11227                       gst_riff_create_audio_caps (header->format, NULL, header,
11228                       extra, NULL, NULL, NULL);
11229
11230                   if (extra)
11231                     gst_buffer_unref (extra);
11232                   g_free (header);
11233                 }
11234               }
11235             } else
11236               GST_DEBUG ("Didn't find waveheadernode for this codec");
11237           }
11238           g_node_destroy (wavenode);
11239         }
11240       } else if (esds) {
11241         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11242             stream->stream_tags);
11243       } else {
11244         switch (fourcc) {
11245 #if 0
11246             /* FIXME: what is in the chunk? */
11247           case FOURCC_QDMC:
11248           {
11249             gint len = QT_UINT32 (stsd_data);
11250
11251             /* seems to be always = 116 = 0x74 */
11252             break;
11253           }
11254 #endif
11255           case FOURCC_QDM2:
11256           {
11257             gint len = QT_UINT32 (stsd_entry_data);
11258
11259             if (len > 0x3C) {
11260               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11261
11262               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11263               gst_caps_set_simple (entry->caps,
11264                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11265               gst_buffer_unref (buf);
11266             }
11267             gst_caps_set_simple (entry->caps,
11268                 "samplesize", G_TYPE_INT, samplesize, NULL);
11269             break;
11270           }
11271           case FOURCC_alac:
11272           {
11273             GNode *alac, *wave = NULL;
11274
11275             /* apparently, m4a has this atom appended directly in the stsd entry,
11276              * while mov has it in a wave atom */
11277             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11278             if (alac) {
11279               /* alac now refers to stsd entry atom */
11280               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11281               if (wave)
11282                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11283               else
11284                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11285             }
11286             if (alac) {
11287               const guint8 *alac_data = alac->data;
11288               gint len = QT_UINT32 (alac->data);
11289               GstBuffer *buf;
11290
11291               if (len < 36) {
11292                 GST_DEBUG_OBJECT (qtdemux,
11293                     "discarding alac atom with unexpected len %d", len);
11294               } else {
11295                 /* codec-data contains alac atom size and prefix,
11296                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11297                 buf = gst_buffer_new_and_alloc (len);
11298                 gst_buffer_fill (buf, 0, alac->data, len);
11299                 gst_caps_set_simple (entry->caps,
11300                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11301                 gst_buffer_unref (buf);
11302
11303                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11304                 entry->n_channels = QT_UINT8 (alac_data + 21);
11305                 entry->rate = QT_UINT32 (alac_data + 32);
11306               }
11307             }
11308             gst_caps_set_simple (entry->caps,
11309                 "samplesize", G_TYPE_INT, samplesize, NULL);
11310             break;
11311           }
11312           case FOURCC_fLaC:
11313           {
11314             /* The codingname of the sample entry is 'fLaC' */
11315             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11316
11317             if (flac) {
11318               /* The 'dfLa' box is added to the sample entry to convey
11319                  initializing information for the decoder. */
11320               const GNode *dfla =
11321                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11322
11323               if (dfla) {
11324                 const guint32 len = QT_UINT32 (dfla->data);
11325
11326                 /* Must contain at least dfLa box header (12),
11327                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11328                 if (len < 50) {
11329                   GST_DEBUG_OBJECT (qtdemux,
11330                       "discarding dfla atom with unexpected len %d", len);
11331                 } else {
11332                   /* skip dfLa header to get the METADATA_BLOCKs */
11333                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11334                   const guint32 metadata_blocks_len = len - 12;
11335
11336                   gchar *stream_marker = g_strdup ("fLaC");
11337                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11338                       strlen (stream_marker));
11339
11340                   guint32 index = 0;
11341                   guint32 remainder = 0;
11342                   guint32 block_size = 0;
11343                   gboolean is_last = FALSE;
11344
11345                   GValue array = G_VALUE_INIT;
11346                   GValue value = G_VALUE_INIT;
11347
11348                   g_value_init (&array, GST_TYPE_ARRAY);
11349                   g_value_init (&value, GST_TYPE_BUFFER);
11350
11351                   gst_value_set_buffer (&value, block);
11352                   gst_value_array_append_value (&array, &value);
11353                   g_value_reset (&value);
11354
11355                   gst_buffer_unref (block);
11356
11357                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11358                    * of data, and we haven't already finished parsing */
11359                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11360                     remainder = metadata_blocks_len - index;
11361
11362                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11363                     block_size = 4 +
11364                         (metadata_blocks[index + 1] << 16) +
11365                         (metadata_blocks[index + 2] << 8) +
11366                         metadata_blocks[index + 3];
11367
11368                     /* be careful not to read off end of box */
11369                     if (block_size > remainder) {
11370                       break;
11371                     }
11372
11373                     is_last = metadata_blocks[index] >> 7;
11374
11375                     block = gst_buffer_new_and_alloc (block_size);
11376
11377                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11378                         block_size);
11379
11380                     gst_value_set_buffer (&value, block);
11381                     gst_value_array_append_value (&array, &value);
11382                     g_value_reset (&value);
11383
11384                     gst_buffer_unref (block);
11385
11386                     index += block_size;
11387                   }
11388
11389                   /* only append the metadata if we successfully read all of it */
11390                   if (is_last) {
11391                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11392                             (stream)->caps, 0), "streamheader", &array);
11393                   } else {
11394                     GST_WARNING_OBJECT (qtdemux,
11395                         "discarding all METADATA_BLOCKs due to invalid "
11396                         "block_size %d at idx %d, rem %d", block_size, index,
11397                         remainder);
11398                   }
11399
11400                   g_value_unset (&value);
11401                   g_value_unset (&array);
11402
11403                   /* The sample rate obtained from the stsd may not be accurate
11404                    * since it cannot represent rates greater than 65535Hz, so
11405                    * override that value with the sample rate from the
11406                    * METADATA_BLOCK_STREAMINFO block */
11407                   CUR_STREAM (stream)->rate =
11408                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11409                 }
11410               }
11411             }
11412             break;
11413           }
11414           case FOURCC_sawb:
11415             /* Fallthrough! */
11416             amrwb = TRUE;
11417           case FOURCC_samr:
11418           {
11419             gint len = QT_UINT32 (stsd_entry_data);
11420
11421             if (len > 0x24) {
11422               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11423               guint bitrate;
11424
11425               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11426
11427               /* If we have enough data, let's try to get the 'damr' atom. See
11428                * the 3GPP container spec (26.244) for more details. */
11429               if ((len - 0x34) > 8 &&
11430                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11431                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11432                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11433               }
11434
11435               gst_caps_set_simple (entry->caps,
11436                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11437               gst_buffer_unref (buf);
11438             }
11439             break;
11440           }
11441           case FOURCC_mp4a:
11442           {
11443             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11444             gint len = QT_UINT32 (stsd_entry_data);
11445
11446             if (len >= 34) {
11447               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11448
11449               if (sound_version == 1) {
11450                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11451                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11452                 guint8 codec_data[2];
11453                 GstBuffer *buf;
11454                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11455
11456                 gint sample_rate_index =
11457                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11458
11459                 /* build AAC codec data */
11460                 codec_data[0] = profile << 3;
11461                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11462                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11463                 codec_data[1] |= (channels & 0xF) << 3;
11464
11465                 buf = gst_buffer_new_and_alloc (2);
11466                 gst_buffer_fill (buf, 0, codec_data, 2);
11467                 gst_caps_set_simple (entry->caps,
11468                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11469                 gst_buffer_unref (buf);
11470               }
11471             }
11472             break;
11473           }
11474           default:
11475             GST_INFO_OBJECT (qtdemux,
11476                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11477             break;
11478         }
11479       }
11480       GST_INFO_OBJECT (qtdemux,
11481           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11482           GST_FOURCC_ARGS (fourcc), entry->caps);
11483
11484     } else if (stream->subtype == FOURCC_strm) {
11485       if (fourcc == FOURCC_rtsp) {
11486         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11487       } else {
11488         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11489             GST_FOURCC_ARGS (fourcc));
11490         goto unknown_stream;
11491       }
11492       entry->sampled = TRUE;
11493     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11494         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11495
11496       entry->sampled = TRUE;
11497       entry->sparse = TRUE;
11498
11499       entry->caps =
11500           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11501           &codec);
11502       if (codec) {
11503         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11504             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11505         g_free (codec);
11506         codec = NULL;
11507       }
11508
11509       /* hunt for sort-of codec data */
11510       switch (fourcc) {
11511         case FOURCC_mp4s:
11512         {
11513           GNode *mp4s = NULL;
11514           GNode *esds = NULL;
11515
11516           /* look for palette in a stsd->mp4s->esds sub-atom */
11517           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11518           if (mp4s)
11519             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11520           if (esds == NULL) {
11521             /* Invalid STSD */
11522             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11523             break;
11524           }
11525
11526           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11527               stream->stream_tags);
11528           break;
11529         }
11530         default:
11531           GST_INFO_OBJECT (qtdemux,
11532               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11533           break;
11534       }
11535       GST_INFO_OBJECT (qtdemux,
11536           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11537           GST_FOURCC_ARGS (fourcc), entry->caps);
11538     } else {
11539       /* everything in 1 sample */
11540       entry->sampled = TRUE;
11541
11542       entry->caps =
11543           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11544           &codec);
11545
11546       if (entry->caps == NULL)
11547         goto unknown_stream;
11548
11549       if (codec) {
11550         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11551             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11552         g_free (codec);
11553         codec = NULL;
11554       }
11555     }
11556
11557     /* promote to sampled format */
11558     if (entry->fourcc == FOURCC_samr) {
11559       /* force mono 8000 Hz for AMR */
11560       entry->sampled = TRUE;
11561       entry->n_channels = 1;
11562       entry->rate = 8000;
11563     } else if (entry->fourcc == FOURCC_sawb) {
11564       /* force mono 16000 Hz for AMR-WB */
11565       entry->sampled = TRUE;
11566       entry->n_channels = 1;
11567       entry->rate = 16000;
11568     } else if (entry->fourcc == FOURCC_mp4a) {
11569       entry->sampled = TRUE;
11570     }
11571
11572
11573     stsd_entry_data += len;
11574     remaining_stsd_len -= len;
11575
11576   }
11577
11578   /* collect sample information */
11579   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11580     goto samples_failed;
11581
11582   if (qtdemux->fragmented) {
11583     guint64 offset;
11584
11585     /* need all moov samples as basis; probably not many if any at all */
11586     /* prevent moof parsing taking of at this time */
11587     offset = qtdemux->moof_offset;
11588     qtdemux->moof_offset = 0;
11589     if (stream->n_samples &&
11590         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11591       qtdemux->moof_offset = offset;
11592       goto samples_failed;
11593     }
11594     qtdemux->moof_offset = 0;
11595     /* movie duration more reliable in this case (e.g. mehd) */
11596     if (qtdemux->segment.duration &&
11597         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11598       stream->duration =
11599           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11600   }
11601
11602   /* configure segments */
11603   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11604     goto segments_failed;
11605
11606   /* add some language tag, if useful */
11607   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11608       strcmp (stream->lang_id, "und")) {
11609     const gchar *lang_code;
11610
11611     /* convert ISO 639-2 code to ISO 639-1 */
11612     lang_code = gst_tag_get_language_code (stream->lang_id);
11613     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11614         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11615   }
11616
11617   /* Check for UDTA tags */
11618   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11619     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11620   }
11621
11622   /* now we are ready to add the stream */
11623   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11624     goto too_many_streams;
11625
11626   if (!qtdemux->got_moov) {
11627     qtdemux->streams[qtdemux->n_streams] = stream;
11628     qtdemux->n_streams++;
11629     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11630   }
11631
11632   return TRUE;
11633
11634 /* ERRORS */
11635 skip_track:
11636   {
11637     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11638     if (new_stream)
11639       gst_qtdemux_stream_free (qtdemux, stream);
11640     return TRUE;
11641   }
11642 corrupt_file:
11643   {
11644     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11645         (_("This file is corrupt and cannot be played.")), (NULL));
11646     if (new_stream)
11647       gst_qtdemux_stream_free (qtdemux, stream);
11648     return FALSE;
11649   }
11650 error_encrypted:
11651   {
11652     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11653     if (new_stream)
11654       gst_qtdemux_stream_free (qtdemux, stream);
11655     return FALSE;
11656   }
11657 samples_failed:
11658 segments_failed:
11659   {
11660     /* we posted an error already */
11661     /* free stbl sub-atoms */
11662     gst_qtdemux_stbl_free (stream);
11663     if (new_stream)
11664       gst_qtdemux_stream_free (qtdemux, stream);
11665     return FALSE;
11666   }
11667 existing_stream:
11668   {
11669     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11670         track_id);
11671     if (new_stream)
11672       gst_qtdemux_stream_free (qtdemux, stream);
11673     return TRUE;
11674   }
11675 unknown_stream:
11676   {
11677     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11678         GST_FOURCC_ARGS (stream->subtype));
11679     if (new_stream)
11680       gst_qtdemux_stream_free (qtdemux, stream);
11681     return TRUE;
11682   }
11683 too_many_streams:
11684   {
11685     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11686         (_("This file contains too many streams. Only playing first %d"),
11687             GST_QTDEMUX_MAX_STREAMS), (NULL));
11688     return TRUE;
11689   }
11690 }
11691
11692 /* If we can estimate the overall bitrate, and don't have information about the
11693  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11694  * the overall bitrate minus the sum of the bitrates of all other streams. This
11695  * should be useful for the common case where we have one audio and one video
11696  * stream and can estimate the bitrate of one, but not the other. */
11697 static void
11698 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11699 {
11700   QtDemuxStream *stream = NULL;
11701   gint64 size, sys_bitrate, sum_bitrate = 0;
11702   GstClockTime duration;
11703   gint i;
11704   guint bitrate;
11705
11706   if (qtdemux->fragmented)
11707     return;
11708
11709   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11710
11711   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11712       || size <= 0) {
11713     GST_DEBUG_OBJECT (qtdemux,
11714         "Size in bytes of the stream not known - bailing");
11715     return;
11716   }
11717
11718   /* Subtract the header size */
11719   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11720       size, qtdemux->header_size);
11721
11722   if (size < qtdemux->header_size)
11723     return;
11724
11725   size = size - qtdemux->header_size;
11726
11727   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11728     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11729     return;
11730   }
11731
11732   for (i = 0; i < qtdemux->n_streams; i++) {
11733     switch (qtdemux->streams[i]->subtype) {
11734       case FOURCC_soun:
11735       case FOURCC_vide:
11736         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11737             CUR_STREAM (qtdemux->streams[i])->caps);
11738         /* retrieve bitrate, prefer avg then max */
11739         bitrate = 0;
11740         if (qtdemux->streams[i]->stream_tags) {
11741           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11742               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11743           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11744           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11745               GST_TAG_NOMINAL_BITRATE, &bitrate);
11746           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11747           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11748               GST_TAG_BITRATE, &bitrate);
11749           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11750         }
11751         if (bitrate)
11752           sum_bitrate += bitrate;
11753         else {
11754           if (stream) {
11755             GST_DEBUG_OBJECT (qtdemux,
11756                 ">1 stream with unknown bitrate - bailing");
11757             return;
11758           } else
11759             stream = qtdemux->streams[i];
11760         }
11761
11762       default:
11763         /* For other subtypes, we assume no significant impact on bitrate */
11764         break;
11765     }
11766   }
11767
11768   if (!stream) {
11769     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11770     return;
11771   }
11772
11773   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11774
11775   if (sys_bitrate < sum_bitrate) {
11776     /* This can happen, since sum_bitrate might be derived from maximum
11777      * bitrates and not average bitrates */
11778     GST_DEBUG_OBJECT (qtdemux,
11779         "System bitrate less than sum bitrate - bailing");
11780     return;
11781   }
11782
11783   bitrate = sys_bitrate - sum_bitrate;
11784   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11785       ", Stream bitrate = %u", sys_bitrate, bitrate);
11786
11787   if (!stream->stream_tags)
11788     stream->stream_tags = gst_tag_list_new_empty ();
11789   else
11790     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11791
11792   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11793       GST_TAG_BITRATE, bitrate, NULL);
11794 }
11795
11796 static GstFlowReturn
11797 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11798 {
11799   gint i;
11800   GstFlowReturn ret = GST_FLOW_OK;
11801
11802   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11803
11804   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11805     QtDemuxStream *stream = qtdemux->streams[i];
11806     guint32 sample_num = 0;
11807
11808     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11809         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11810
11811     if (qtdemux->fragmented) {
11812       /* need all moov samples first */
11813       GST_OBJECT_LOCK (qtdemux);
11814       while (stream->n_samples == 0)
11815         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11816           break;
11817       GST_OBJECT_UNLOCK (qtdemux);
11818     } else {
11819       /* discard any stray moof */
11820       qtdemux->moof_offset = 0;
11821     }
11822
11823     /* prepare braking */
11824     if (ret != GST_FLOW_ERROR)
11825       ret = GST_FLOW_OK;
11826
11827     /* in pull mode, we should have parsed some sample info by now;
11828      * and quite some code will not handle no samples.
11829      * in push mode, we'll just have to deal with it */
11830     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11831       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11832       gst_qtdemux_remove_stream (qtdemux, i);
11833       i--;
11834       continue;
11835     }
11836
11837     /* parse the initial sample for use in setting the frame rate cap */
11838     while (sample_num == 0 && sample_num < stream->n_samples) {
11839       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11840         break;
11841       ++sample_num;
11842     }
11843     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11844       stream->first_duration = stream->samples[0].duration;
11845       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11846           stream->track_id, stream->first_duration);
11847     }
11848   }
11849
11850   return ret;
11851 }
11852
11853 static GstFlowReturn
11854 qtdemux_expose_streams (GstQTDemux * qtdemux)
11855 {
11856   gint i;
11857   GSList *oldpads = NULL;
11858   GSList *iter;
11859
11860   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11861
11862   for (i = 0; i < qtdemux->n_streams; i++) {
11863     QtDemuxStream *stream = qtdemux->streams[i];
11864     GstPad *oldpad = stream->pad;
11865     GstTagList *list;
11866
11867     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11868         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11869
11870     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11871         stream->track_id == qtdemux->chapters_track_id) {
11872       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11873          so that it doesn't look like a subtitle track */
11874       gst_qtdemux_remove_stream (qtdemux, i);
11875       i--;
11876       continue;
11877     }
11878
11879     /* now we have all info and can expose */
11880     list = stream->stream_tags;
11881     stream->stream_tags = NULL;
11882     if (oldpad)
11883       oldpads = g_slist_prepend (oldpads, oldpad);
11884     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11885       return GST_FLOW_ERROR;
11886   }
11887
11888   gst_qtdemux_guess_bitrate (qtdemux);
11889
11890   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11891
11892   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11893     GstPad *oldpad = iter->data;
11894     GstEvent *event;
11895
11896     event = gst_event_new_eos ();
11897     if (qtdemux->segment_seqnum)
11898       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11899
11900     gst_pad_push_event (oldpad, event);
11901     gst_pad_set_active (oldpad, FALSE);
11902     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11903     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11904     gst_object_unref (oldpad);
11905   }
11906
11907   /* check if we should post a redirect in case there is a single trak
11908    * and it is a redirecting trak */
11909   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11910     GstMessage *m;
11911
11912     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11913         "an external content");
11914     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11915         gst_structure_new ("redirect",
11916             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11917             NULL));
11918     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11919     qtdemux->posted_redirect = TRUE;
11920   }
11921
11922   for (i = 0; i < qtdemux->n_streams; i++) {
11923     QtDemuxStream *stream = qtdemux->streams[i];
11924
11925     qtdemux_do_allocation (qtdemux, stream);
11926   }
11927
11928   qtdemux->exposed = TRUE;
11929   return GST_FLOW_OK;
11930 }
11931
11932 /* check if major or compatible brand is 3GP */
11933 static inline gboolean
11934 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11935 {
11936   if (major) {
11937     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11938         FOURCC_3g__);
11939   } else if (qtdemux->comp_brands != NULL) {
11940     GstMapInfo map;
11941     guint8 *data;
11942     gsize size;
11943     gboolean res = FALSE;
11944
11945     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11946     data = map.data;
11947     size = map.size;
11948     while (size >= 4) {
11949       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11950           FOURCC_3g__);
11951       data += 4;
11952       size -= 4;
11953     }
11954     gst_buffer_unmap (qtdemux->comp_brands, &map);
11955     return res;
11956   } else {
11957     return FALSE;
11958   }
11959 }
11960
11961 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11962 static inline gboolean
11963 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11964 {
11965   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11966       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11967       || fourcc == FOURCC_albm;
11968 }
11969
11970 static void
11971 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11972     const char *tag, const char *dummy, GNode * node)
11973 {
11974   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11975   int offset;
11976   char *name;
11977   gchar *data;
11978   gdouble longitude, latitude, altitude;
11979   gint len;
11980
11981   len = QT_UINT32 (node->data);
11982   if (len <= 14)
11983     goto short_read;
11984
11985   data = node->data;
11986   offset = 14;
11987
11988   /* TODO: language code skipped */
11989
11990   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11991
11992   if (!name) {
11993     /* do not alarm in trivial case, but bail out otherwise */
11994     if (*(data + offset) != 0) {
11995       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11996           "giving up", tag);
11997     }
11998   } else {
11999     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12000         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12001     offset += strlen (name);
12002     g_free (name);
12003   }
12004
12005   if (len < offset + 2 + 4 + 4 + 4)
12006     goto short_read;
12007
12008   /* +1 +1 = skip null-terminator and location role byte */
12009   offset += 1 + 1;
12010   /* table in spec says unsigned, semantics say negative has meaning ... */
12011   longitude = QT_SFP32 (data + offset);
12012
12013   offset += 4;
12014   latitude = QT_SFP32 (data + offset);
12015
12016   offset += 4;
12017   altitude = QT_SFP32 (data + offset);
12018
12019   /* one invalid means all are invalid */
12020   if (longitude >= -180.0 && longitude <= 180.0 &&
12021       latitude >= -90.0 && latitude <= 90.0) {
12022     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12023         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12024         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12025         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12026   }
12027
12028   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12029
12030   return;
12031
12032   /* ERRORS */
12033 short_read:
12034   {
12035     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12036     return;
12037   }
12038 }
12039
12040
12041 static void
12042 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12043     const char *tag, const char *dummy, GNode * node)
12044 {
12045   guint16 y;
12046   GDate *date;
12047   gint len;
12048
12049   len = QT_UINT32 (node->data);
12050   if (len < 14)
12051     return;
12052
12053   y = QT_UINT16 ((guint8 *) node->data + 12);
12054   if (y == 0) {
12055     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12056     return;
12057   }
12058   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12059
12060   date = g_date_new_dmy (1, 1, y);
12061   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12062   g_date_free (date);
12063 }
12064
12065 static void
12066 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12067     const char *tag, const char *dummy, GNode * node)
12068 {
12069   int offset;
12070   char *tag_str = NULL;
12071   guint8 *entity;
12072   guint16 table;
12073   gint len;
12074
12075   len = QT_UINT32 (node->data);
12076   if (len <= 20)
12077     goto short_read;
12078
12079   offset = 12;
12080   entity = (guint8 *) node->data + offset;
12081   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12082     GST_DEBUG_OBJECT (qtdemux,
12083         "classification info: %c%c%c%c invalid classification entity",
12084         entity[0], entity[1], entity[2], entity[3]);
12085     return;
12086   }
12087
12088   offset += 4;
12089   table = QT_UINT16 ((guint8 *) node->data + offset);
12090
12091   /* Language code skipped */
12092
12093   offset += 4;
12094
12095   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12096    * XXXX: classification entity, fixed length 4 chars.
12097    * Y[YYYY]: classification table, max 5 chars.
12098    */
12099   tag_str = g_strdup_printf ("----://%u/%s",
12100       table, (char *) node->data + offset);
12101
12102   /* memcpy To be sure we're preserving byte order */
12103   memcpy (tag_str, entity, 4);
12104   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12105
12106   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12107
12108   g_free (tag_str);
12109
12110   return;
12111
12112   /* ERRORS */
12113 short_read:
12114   {
12115     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12116     return;
12117   }
12118 }
12119
12120 static gboolean
12121 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12122     const char *tag, const char *dummy, GNode * node)
12123 {
12124   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12125   GNode *data;
12126   char *s;
12127   int len;
12128   guint32 type;
12129   int offset;
12130   gboolean ret = TRUE;
12131   const gchar *charset = NULL;
12132
12133   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12134   if (data) {
12135     len = QT_UINT32 (data->data);
12136     type = QT_UINT32 ((guint8 *) data->data + 8);
12137     if (type == 0x00000001 && len > 16) {
12138       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12139           env_vars);
12140       if (s) {
12141         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12142         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12143         g_free (s);
12144       } else {
12145         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12146       }
12147     }
12148   } else {
12149     len = QT_UINT32 (node->data);
12150     type = QT_UINT32 ((guint8 *) node->data + 4);
12151     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12152       gint str_len;
12153       gint lang_code;
12154
12155       /* Type starts with the (C) symbol, so the next data is a list
12156        * of (string size(16), language code(16), string) */
12157
12158       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12159       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12160
12161       /* the string + fourcc + size + 2 16bit fields,
12162        * means that there are more tags in this atom */
12163       if (len > str_len + 8 + 4) {
12164         /* TODO how to represent the same tag in different languages? */
12165         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12166             "text alternatives, reading only first one");
12167       }
12168
12169       offset = 12;
12170       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12171       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12172
12173       if (lang_code < 0x800) {  /* MAC encoded string */
12174         charset = "mac";
12175       }
12176     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12177             QT_FOURCC ((guint8 *) node->data + 4))) {
12178       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12179
12180       /* we go for 3GP style encoding if major brands claims so,
12181        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12182       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12183           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12184               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12185         offset = 14;
12186         /* 16-bit Language code is ignored here as well */
12187         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12188       } else {
12189         goto normal;
12190       }
12191     } else {
12192     normal:
12193       offset = 8;
12194       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12195       ret = FALSE;              /* may have to fallback */
12196     }
12197     if (charset) {
12198       GError *err = NULL;
12199
12200       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12201           charset, NULL, NULL, &err);
12202       if (err) {
12203         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12204             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12205             err->message);
12206         g_error_free (err);
12207       }
12208     } else {
12209       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12210           len - offset, env_vars);
12211     }
12212     if (s) {
12213       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12214       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12215       g_free (s);
12216       ret = TRUE;
12217     } else {
12218       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12219     }
12220   }
12221   return ret;
12222 }
12223
12224 static void
12225 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12226     const char *tag, const char *dummy, GNode * node)
12227 {
12228   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12229 }
12230
12231 static void
12232 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12233     const char *tag, const char *dummy, GNode * node)
12234 {
12235   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12236   guint8 *data;
12237   char *s, *t, *k = NULL;
12238   int len;
12239   int offset;
12240   int count;
12241
12242   /* first try normal string tag if major brand not 3GP */
12243   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12244     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12245       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12246        * let's try it 3gpp way after minor safety check */
12247       data = node->data;
12248       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12249         return;
12250     } else
12251       return;
12252   }
12253
12254   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12255
12256   data = node->data;
12257
12258   len = QT_UINT32 (data);
12259   if (len < 15)
12260     goto short_read;
12261
12262   count = QT_UINT8 (data + 14);
12263   offset = 15;
12264   for (; count; count--) {
12265     gint slen;
12266
12267     if (offset + 1 > len)
12268       goto short_read;
12269     slen = QT_UINT8 (data + offset);
12270     offset += 1;
12271     if (offset + slen > len)
12272       goto short_read;
12273     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12274         slen, env_vars);
12275     if (s) {
12276       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12277       if (k) {
12278         t = g_strjoin (",", k, s, NULL);
12279         g_free (s);
12280         g_free (k);
12281         k = t;
12282       } else {
12283         k = s;
12284       }
12285     } else {
12286       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12287     }
12288     offset += slen;
12289   }
12290
12291 done:
12292   if (k) {
12293     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12294     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12295   }
12296   g_free (k);
12297
12298   return;
12299
12300   /* ERRORS */
12301 short_read:
12302   {
12303     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12304     goto done;
12305   }
12306 }
12307
12308 static void
12309 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12310     const char *tag1, const char *tag2, GNode * node)
12311 {
12312   GNode *data;
12313   int len;
12314   int type;
12315   int n1, n2;
12316
12317   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12318   if (data) {
12319     len = QT_UINT32 (data->data);
12320     type = QT_UINT32 ((guint8 *) data->data + 8);
12321     if (type == 0x00000000 && len >= 22) {
12322       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12323       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12324       if (n1 > 0) {
12325         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12326         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12327       }
12328       if (n2 > 0) {
12329         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12330         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12331       }
12332     }
12333   }
12334 }
12335
12336 static void
12337 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12338     const char *tag1, const char *dummy, GNode * node)
12339 {
12340   GNode *data;
12341   int len;
12342   int type;
12343   int n1;
12344
12345   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12346   if (data) {
12347     len = QT_UINT32 (data->data);
12348     type = QT_UINT32 ((guint8 *) data->data + 8);
12349     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12350     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12351     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12352       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12353       if (n1) {
12354         /* do not add bpm=0 */
12355         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12356         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12357             NULL);
12358       }
12359     }
12360   }
12361 }
12362
12363 static void
12364 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12365     const char *tag1, const char *dummy, GNode * node)
12366 {
12367   GNode *data;
12368   int len;
12369   int type;
12370   guint32 num;
12371
12372   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12373   if (data) {
12374     len = QT_UINT32 (data->data);
12375     type = QT_UINT32 ((guint8 *) data->data + 8);
12376     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12377     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12378     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12379       num = QT_UINT32 ((guint8 *) data->data + 16);
12380       if (num) {
12381         /* do not add num=0 */
12382         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12383         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12384       }
12385     }
12386   }
12387 }
12388
12389 static void
12390 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12391     const char *tag1, const char *dummy, GNode * node)
12392 {
12393   GNode *data;
12394   int len;
12395   int type;
12396   GstSample *sample;
12397
12398   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12399   if (data) {
12400     len = QT_UINT32 (data->data);
12401     type = QT_UINT32 ((guint8 *) data->data + 8);
12402     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12403     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12404       GstTagImageType image_type;
12405
12406       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12407         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12408       else
12409         image_type = GST_TAG_IMAGE_TYPE_NONE;
12410
12411       if ((sample =
12412               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12413                   len - 16, image_type))) {
12414         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12415         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12416         gst_sample_unref (sample);
12417       }
12418     }
12419   }
12420 }
12421
12422 static void
12423 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12424     const char *tag, const char *dummy, GNode * node)
12425 {
12426   GNode *data;
12427   char *s;
12428   int len;
12429   int type;
12430
12431   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12432   if (data) {
12433     len = QT_UINT32 (data->data);
12434     type = QT_UINT32 ((guint8 *) data->data + 8);
12435     if (type == 0x00000001 && len > 16) {
12436       guint y, m = 1, d = 1;
12437       gint ret;
12438
12439       s = g_strndup ((char *) data->data + 16, len - 16);
12440       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12441       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12442       if (ret >= 1 && y > 1500 && y < 3000) {
12443         GDate *date;
12444
12445         date = g_date_new_dmy (d, m, y);
12446         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12447         g_date_free (date);
12448       } else {
12449         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12450       }
12451       g_free (s);
12452     }
12453   }
12454 }
12455
12456 static void
12457 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12458     const char *tag, const char *dummy, GNode * node)
12459 {
12460   GNode *data;
12461
12462   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12463
12464   /* re-route to normal string tag if major brand says so
12465    * or no data atom and compatible brand suggests so */
12466   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12467       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12468     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12469     return;
12470   }
12471
12472   if (data) {
12473     guint len, type, n;
12474
12475     len = QT_UINT32 (data->data);
12476     type = QT_UINT32 ((guint8 *) data->data + 8);
12477     if (type == 0x00000000 && len >= 18) {
12478       n = QT_UINT16 ((guint8 *) data->data + 16);
12479       if (n > 0) {
12480         const gchar *genre;
12481
12482         genre = gst_tag_id3_genre_get (n - 1);
12483         if (genre != NULL) {
12484           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12485           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12486         }
12487       }
12488     }
12489   }
12490 }
12491
12492 static void
12493 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12494     const gchar * tag, guint8 * data, guint32 datasize)
12495 {
12496   gdouble value;
12497   gchar *datacopy;
12498
12499   /* make a copy to have \0 at the end */
12500   datacopy = g_strndup ((gchar *) data, datasize);
12501
12502   /* convert the str to double */
12503   if (sscanf (datacopy, "%lf", &value) == 1) {
12504     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12505     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12506   } else {
12507     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12508         datacopy);
12509   }
12510   g_free (datacopy);
12511 }
12512
12513
12514 static void
12515 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12516     const char *tag, const char *tag_bis, GNode * node)
12517 {
12518   GNode *mean;
12519   GNode *name;
12520   GNode *data;
12521   guint32 meansize;
12522   guint32 namesize;
12523   guint32 datatype;
12524   guint32 datasize;
12525   const gchar *meanstr;
12526   const gchar *namestr;
12527
12528   /* checking the whole ---- atom size for consistency */
12529   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12530     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12531     return;
12532   }
12533
12534   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12535   if (!mean) {
12536     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12537     return;
12538   }
12539
12540   meansize = QT_UINT32 (mean->data);
12541   if (meansize <= 12) {
12542     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12543     return;
12544   }
12545   meanstr = ((gchar *) mean->data) + 12;
12546   meansize -= 12;
12547
12548   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12549   if (!name) {
12550     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12551     return;
12552   }
12553
12554   namesize = QT_UINT32 (name->data);
12555   if (namesize <= 12) {
12556     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12557     return;
12558   }
12559   namestr = ((gchar *) name->data) + 12;
12560   namesize -= 12;
12561
12562   /*
12563    * Data atom is:
12564    * uint32 - size
12565    * uint32 - name
12566    * uint8  - version
12567    * uint24 - data type
12568    * uint32 - all 0
12569    * rest   - the data
12570    */
12571   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12572   if (!data) {
12573     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12574     return;
12575   }
12576   datasize = QT_UINT32 (data->data);
12577   if (datasize <= 16) {
12578     GST_WARNING_OBJECT (demux, "Data atom too small");
12579     return;
12580   }
12581   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12582
12583   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12584       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12585     static const struct
12586     {
12587       const gchar name[28];
12588       const gchar tag[28];
12589     } tags[] = {
12590       {
12591       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12592       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12593       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12594       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12595       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12596       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12597       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12598       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12599     };
12600     int i;
12601
12602     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12603       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12604         switch (gst_tag_get_type (tags[i].tag)) {
12605           case G_TYPE_DOUBLE:
12606             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12607                 ((guint8 *) data->data) + 16, datasize - 16);
12608             break;
12609           case G_TYPE_STRING:
12610             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12611             break;
12612           default:
12613             /* not reached */
12614             break;
12615         }
12616         break;
12617       }
12618     }
12619     if (i == G_N_ELEMENTS (tags))
12620       goto unknown_tag;
12621   } else {
12622     goto unknown_tag;
12623   }
12624
12625   return;
12626
12627 /* errors */
12628 unknown_tag:
12629 #ifndef GST_DISABLE_GST_DEBUG
12630   {
12631     gchar *namestr_dbg;
12632     gchar *meanstr_dbg;
12633
12634     meanstr_dbg = g_strndup (meanstr, meansize);
12635     namestr_dbg = g_strndup (namestr, namesize);
12636
12637     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12638         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12639
12640     g_free (namestr_dbg);
12641     g_free (meanstr_dbg);
12642   }
12643 #endif
12644   return;
12645 }
12646
12647 static void
12648 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12649     const char *tag_bis, GNode * node)
12650 {
12651   guint8 *data;
12652   GstBuffer *buf;
12653   guint len;
12654   GstTagList *id32_taglist = NULL;
12655
12656   GST_LOG_OBJECT (demux, "parsing ID32");
12657
12658   data = node->data;
12659   len = GST_READ_UINT32_BE (data);
12660
12661   /* need at least full box and language tag */
12662   if (len < 12 + 2)
12663     return;
12664
12665   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12666   gst_buffer_fill (buf, 0, data + 14, len - 14);
12667
12668   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12669   if (id32_taglist) {
12670     GST_LOG_OBJECT (demux, "parsing ok");
12671     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12672     gst_tag_list_unref (id32_taglist);
12673   } else {
12674     GST_LOG_OBJECT (demux, "parsing failed");
12675   }
12676
12677   gst_buffer_unref (buf);
12678 }
12679
12680 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12681     const char *tag, const char *tag_bis, GNode * node);
12682
12683 /* unmapped tags
12684 FOURCC_pcst -> if media is a podcast -> bool
12685 FOURCC_cpil -> if media is part of a compilation -> bool
12686 FOURCC_pgap -> if media is part of a gapless context -> bool
12687 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12688 */
12689
12690 static const struct
12691 {
12692   guint32 fourcc;
12693   const gchar *gst_tag;
12694   const gchar *gst_tag_bis;
12695   const GstQTDemuxAddTagFunc func;
12696 } add_funcs[] = {
12697   {
12698   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12699   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12700   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12701   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12702   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12703   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12704   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12705   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12706   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12707   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12708   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12709   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12710   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12711   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12712   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12713   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12714   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12715   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12716   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12717   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12718   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12719   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12720   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12721         qtdemux_tag_add_num}, {
12722   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12723         qtdemux_tag_add_num}, {
12724   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12725   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12726   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12727   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12728   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12729   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12730   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12731   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12732   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12733   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12734   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12735   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12736   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12737   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12738   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12739   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12740   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12741   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12742         qtdemux_tag_add_classification}, {
12743   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12744   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12745   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12746
12747     /* This is a special case, some tags are stored in this
12748      * 'reverse dns naming', according to:
12749      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12750      * bug #614471
12751      */
12752   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12753     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12754   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12755 };
12756
12757 struct _GstQtDemuxTagList
12758 {
12759   GstQTDemux *demux;
12760   GstTagList *taglist;
12761 };
12762 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12763
12764 static void
12765 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12766 {
12767   gint len;
12768   guint8 *data;
12769   GstBuffer *buf;
12770   gchar *media_type;
12771   const gchar *style;
12772   GstSample *sample;
12773   GstStructure *s;
12774   guint i;
12775   guint8 ndata[4];
12776   GstQTDemux *demux = qtdemuxtaglist->demux;
12777   GstTagList *taglist = qtdemuxtaglist->taglist;
12778
12779   data = node->data;
12780   len = QT_UINT32 (data);
12781   buf = gst_buffer_new_and_alloc (len);
12782   gst_buffer_fill (buf, 0, data, len);
12783
12784   /* heuristic to determine style of tag */
12785   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12786       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12787     style = "itunes";
12788   else if (demux->major_brand == FOURCC_qt__)
12789     style = "quicktime";
12790   /* fall back to assuming iso/3gp tag style */
12791   else
12792     style = "iso";
12793
12794   /* santize the name for the caps. */
12795   for (i = 0; i < 4; i++) {
12796     guint8 d = data[4 + i];
12797     if (g_ascii_isalnum (d))
12798       ndata[i] = g_ascii_tolower (d);
12799     else
12800       ndata[i] = '_';
12801   }
12802
12803   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12804       ndata[0], ndata[1], ndata[2], ndata[3]);
12805   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12806
12807   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12808   sample = gst_sample_new (buf, NULL, NULL, s);
12809   gst_buffer_unref (buf);
12810   g_free (media_type);
12811
12812   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12813       len, s);
12814
12815   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12816       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12817
12818   gst_sample_unref (sample);
12819 }
12820
12821 static void
12822 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12823 {
12824   GNode *meta;
12825   GNode *ilst;
12826   GNode *xmp_;
12827   GNode *node;
12828   gint i;
12829   GstQtDemuxTagList demuxtaglist;
12830
12831   demuxtaglist.demux = qtdemux;
12832   demuxtaglist.taglist = taglist;
12833
12834   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12835   if (meta != NULL) {
12836     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12837     if (ilst == NULL) {
12838       GST_LOG_OBJECT (qtdemux, "no ilst");
12839       return;
12840     }
12841   } else {
12842     ilst = udta;
12843     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12844   }
12845
12846   i = 0;
12847   while (i < G_N_ELEMENTS (add_funcs)) {
12848     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12849     if (node) {
12850       gint len;
12851
12852       len = QT_UINT32 (node->data);
12853       if (len < 12) {
12854         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12855             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12856       } else {
12857         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12858             add_funcs[i].gst_tag_bis, node);
12859       }
12860       g_node_destroy (node);
12861     } else {
12862       i++;
12863     }
12864   }
12865
12866   /* parsed nodes have been removed, pass along remainder as blob */
12867   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12868       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12869
12870   /* parse up XMP_ node if existing */
12871   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12872   if (xmp_ != NULL) {
12873     GstBuffer *buf;
12874     GstTagList *xmptaglist;
12875
12876     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12877         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12878     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12879     gst_buffer_unref (buf);
12880
12881     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12882   } else {
12883     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12884   }
12885 }
12886
12887 typedef struct
12888 {
12889   GstStructure *structure;      /* helper for sort function */
12890   gchar *location;
12891   guint min_req_bitrate;
12892   guint min_req_qt_version;
12893 } GstQtReference;
12894
12895 static gint
12896 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12897 {
12898   GstQtReference *ref_a = (GstQtReference *) a;
12899   GstQtReference *ref_b = (GstQtReference *) b;
12900
12901   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12902     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12903
12904   /* known bitrates go before unknown; higher bitrates go first */
12905   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12906 }
12907
12908 /* sort the redirects and post a message for the application.
12909  */
12910 static void
12911 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12912 {
12913   GstQtReference *best;
12914   GstStructure *s;
12915   GstMessage *msg;
12916   GValue list_val = { 0, };
12917   GList *l;
12918
12919   g_assert (references != NULL);
12920
12921   references = g_list_sort (references, qtdemux_redirects_sort_func);
12922
12923   best = (GstQtReference *) references->data;
12924
12925   g_value_init (&list_val, GST_TYPE_LIST);
12926
12927   for (l = references; l != NULL; l = l->next) {
12928     GstQtReference *ref = (GstQtReference *) l->data;
12929     GValue struct_val = { 0, };
12930
12931     ref->structure = gst_structure_new ("redirect",
12932         "new-location", G_TYPE_STRING, ref->location, NULL);
12933
12934     if (ref->min_req_bitrate > 0) {
12935       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12936           ref->min_req_bitrate, NULL);
12937     }
12938
12939     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12940     g_value_set_boxed (&struct_val, ref->structure);
12941     gst_value_list_append_value (&list_val, &struct_val);
12942     g_value_unset (&struct_val);
12943     /* don't free anything here yet, since we need best->structure below */
12944   }
12945
12946   g_assert (best != NULL);
12947   s = gst_structure_copy (best->structure);
12948
12949   if (g_list_length (references) > 1) {
12950     gst_structure_set_value (s, "locations", &list_val);
12951   }
12952
12953   g_value_unset (&list_val);
12954
12955   for (l = references; l != NULL; l = l->next) {
12956     GstQtReference *ref = (GstQtReference *) l->data;
12957
12958     gst_structure_free (ref->structure);
12959     g_free (ref->location);
12960     g_free (ref);
12961   }
12962   g_list_free (references);
12963
12964   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12965   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12966   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12967   qtdemux->posted_redirect = TRUE;
12968 }
12969
12970 /* look for redirect nodes, collect all redirect information and
12971  * process it.
12972  */
12973 static gboolean
12974 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12975 {
12976   GNode *rmra, *rmda, *rdrf;
12977
12978   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12979   if (rmra) {
12980     GList *redirects = NULL;
12981
12982     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12983     while (rmda) {
12984       GstQtReference ref = { NULL, NULL, 0, 0 };
12985       GNode *rmdr, *rmvc;
12986
12987       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12988         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12989         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12990             ref.min_req_bitrate);
12991       }
12992
12993       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12994         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12995         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12996
12997 #ifndef GST_DISABLE_GST_DEBUG
12998         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12999 #endif
13000         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13001
13002         GST_LOG_OBJECT (qtdemux,
13003             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13004             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13005             bitmask, check_type);
13006         if (package == FOURCC_qtim && check_type == 0) {
13007           ref.min_req_qt_version = version;
13008         }
13009       }
13010
13011       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13012       if (rdrf) {
13013         guint32 ref_type;
13014         guint8 *ref_data;
13015         guint ref_len;
13016
13017         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13018         if (ref_len > 20) {
13019           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13020           ref_data = (guint8 *) rdrf->data + 20;
13021           if (ref_type == FOURCC_alis) {
13022             guint record_len, record_version, fn_len;
13023
13024             if (ref_len > 70) {
13025               /* MacOSX alias record, google for alias-layout.txt */
13026               record_len = QT_UINT16 (ref_data + 4);
13027               record_version = QT_UINT16 (ref_data + 4 + 2);
13028               fn_len = QT_UINT8 (ref_data + 50);
13029               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13030                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13031               }
13032             } else {
13033               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13034                   ref_len);
13035             }
13036           } else if (ref_type == FOURCC_url_) {
13037             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13038           } else {
13039             GST_DEBUG_OBJECT (qtdemux,
13040                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13041                 GST_FOURCC_ARGS (ref_type));
13042           }
13043           if (ref.location != NULL) {
13044             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13045             redirects =
13046                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13047           } else {
13048             GST_WARNING_OBJECT (qtdemux,
13049                 "Failed to extract redirect location from rdrf atom");
13050           }
13051         } else {
13052           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13053         }
13054       }
13055
13056       /* look for others */
13057       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13058     }
13059
13060     if (redirects != NULL) {
13061       qtdemux_process_redirects (qtdemux, redirects);
13062     }
13063   }
13064   return TRUE;
13065 }
13066
13067 static GstTagList *
13068 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13069 {
13070   const gchar *fmt;
13071
13072   if (tags == NULL) {
13073     tags = gst_tag_list_new_empty ();
13074     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13075   }
13076
13077   if (qtdemux->major_brand == FOURCC_mjp2)
13078     fmt = "Motion JPEG 2000";
13079   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13080     fmt = "3GP";
13081   else if (qtdemux->major_brand == FOURCC_qt__)
13082     fmt = "Quicktime";
13083   else if (qtdemux->fragmented)
13084     fmt = "ISO fMP4";
13085   else
13086     fmt = "ISO MP4/M4A";
13087
13088   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13089       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13090
13091   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13092       fmt, NULL);
13093
13094   return tags;
13095 }
13096
13097 /* we have read the complete moov node now.
13098  * This function parses all of the relevant info, creates the traks and
13099  * prepares all data structures for playback
13100  */
13101 static gboolean
13102 qtdemux_parse_tree (GstQTDemux * qtdemux)
13103 {
13104   GNode *mvhd;
13105   GNode *trak;
13106   GNode *udta;
13107   GNode *mvex;
13108   GstClockTime duration;
13109   GNode *pssh;
13110   guint64 creation_time;
13111   GstDateTime *datetime = NULL;
13112   gint version;
13113
13114   /* make sure we have a usable taglist */
13115   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13116
13117   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13118   if (mvhd == NULL) {
13119     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13120     return qtdemux_parse_redirects (qtdemux);
13121   }
13122
13123   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13124   if (version == 1) {
13125     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13126     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13127     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13128   } else if (version == 0) {
13129     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13130     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13131     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13132   } else {
13133     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13134     return FALSE;
13135   }
13136
13137   /* Moving qt creation time (secs since 1904) to unix time */
13138   if (creation_time != 0) {
13139     /* Try to use epoch first as it should be faster and more commonly found */
13140     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13141       GTimeVal now;
13142
13143       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13144       /* some data cleansing sanity */
13145       g_get_current_time (&now);
13146       if (now.tv_sec + 24 * 3600 < creation_time) {
13147         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13148       } else {
13149         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13150       }
13151     } else {
13152       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13153       GDateTime *dt, *dt_local;
13154
13155       dt = g_date_time_add_seconds (base_dt, creation_time);
13156       dt_local = g_date_time_to_local (dt);
13157       datetime = gst_date_time_new_from_g_date_time (dt_local);
13158
13159       g_date_time_unref (base_dt);
13160       g_date_time_unref (dt);
13161     }
13162   }
13163   if (datetime) {
13164     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13165     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13166         datetime, NULL);
13167     gst_date_time_unref (datetime);
13168   }
13169
13170   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13171   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13172
13173   /* check for fragmented file and get some (default) data */
13174   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13175   if (mvex) {
13176     GNode *mehd;
13177     GstByteReader mehd_data;
13178
13179     /* let track parsing or anyone know weird stuff might happen ... */
13180     qtdemux->fragmented = TRUE;
13181
13182     /* compensate for total duration */
13183     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13184     if (mehd)
13185       qtdemux_parse_mehd (qtdemux, &mehd_data);
13186   }
13187
13188   /* set duration in the segment info */
13189   gst_qtdemux_get_duration (qtdemux, &duration);
13190   if (duration) {
13191     qtdemux->segment.duration = duration;
13192     /* also do not exceed duration; stop is set that way post seek anyway,
13193      * and segment activation falls back to duration,
13194      * whereas loop only checks stop, so let's align this here as well */
13195     qtdemux->segment.stop = duration;
13196   }
13197
13198   /* parse all traks */
13199   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13200   while (trak) {
13201     qtdemux_parse_trak (qtdemux, trak);
13202     /* iterate all siblings */
13203     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13204   }
13205
13206   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13207
13208   /* find tags */
13209   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13210   if (udta) {
13211     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13212   } else {
13213     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13214   }
13215
13216   /* maybe also some tags in meta box */
13217   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13218   if (udta) {
13219     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13220     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13221   } else {
13222     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13223   }
13224
13225   /* parse any protection system info */
13226   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13227   while (pssh) {
13228     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13229     qtdemux_parse_pssh (qtdemux, pssh);
13230     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13231   }
13232
13233   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13234
13235   return TRUE;
13236 }
13237
13238 /* taken from ffmpeg */
13239 static int
13240 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13241 {
13242   int count = 4;
13243   int len = 0;
13244
13245   while (count--) {
13246     int c;
13247
13248     if (ptr >= end)
13249       return -1;
13250
13251     c = *ptr++;
13252     len = (len << 7) | (c & 0x7f);
13253     if (!(c & 0x80))
13254       break;
13255   }
13256   *end_out = ptr;
13257   return len;
13258 }
13259
13260 /* this can change the codec originally present in @list */
13261 static void
13262 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13263     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13264 {
13265   int len = QT_UINT32 (esds->data);
13266   guint8 *ptr = esds->data;
13267   guint8 *end = ptr + len;
13268   int tag;
13269   guint8 *data_ptr = NULL;
13270   int data_len = 0;
13271   guint8 object_type_id = 0;
13272   const char *codec_name = NULL;
13273   GstCaps *caps = NULL;
13274
13275   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13276   ptr += 8;
13277   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13278   ptr += 4;
13279   while (ptr + 1 < end) {
13280     tag = QT_UINT8 (ptr);
13281     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13282     ptr++;
13283     len = read_descr_size (ptr, end, &ptr);
13284     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13285
13286     /* Check the stated amount of data is available for reading */
13287     if (len < 0 || ptr + len > end)
13288       break;
13289
13290     switch (tag) {
13291       case ES_DESCRIPTOR_TAG:
13292         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13293         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13294         ptr += 3;
13295         break;
13296       case DECODER_CONFIG_DESC_TAG:{
13297         guint max_bitrate, avg_bitrate;
13298
13299         object_type_id = QT_UINT8 (ptr);
13300         max_bitrate = QT_UINT32 (ptr + 5);
13301         avg_bitrate = QT_UINT32 (ptr + 9);
13302         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13303         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13304         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13305         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13306         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13307         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13308           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13309               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13310         }
13311         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13312           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13313               avg_bitrate, NULL);
13314         }
13315         ptr += 13;
13316         break;
13317       }
13318       case DECODER_SPECIFIC_INFO_TAG:
13319         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13320         if (object_type_id == 0xe0 && len == 0x40) {
13321           guint8 *data;
13322           GstStructure *s;
13323           guint32 clut[16];
13324           gint i;
13325
13326           GST_DEBUG_OBJECT (qtdemux,
13327               "Have VOBSUB palette. Creating palette event");
13328           /* move to decConfigDescr data and read palette */
13329           data = ptr;
13330           for (i = 0; i < 16; i++) {
13331             clut[i] = QT_UINT32 (data);
13332             data += 4;
13333           }
13334
13335           s = gst_structure_new ("application/x-gst-dvd", "event",
13336               G_TYPE_STRING, "dvd-spu-clut-change",
13337               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13338               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13339               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13340               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13341               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13342               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13343               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13344               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13345               NULL);
13346
13347           /* store event and trigger custom processing */
13348           stream->pending_event =
13349               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13350         } else {
13351           /* Generic codec_data handler puts it on the caps */
13352           data_ptr = ptr;
13353           data_len = len;
13354         }
13355
13356         ptr += len;
13357         break;
13358       case SL_CONFIG_DESC_TAG:
13359         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13360         ptr += 1;
13361         break;
13362       default:
13363         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13364             tag);
13365         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13366         ptr += len;
13367         break;
13368     }
13369   }
13370
13371   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13372    * in use, and should also be used to override some other parameters for some
13373    * codecs. */
13374   switch (object_type_id) {
13375     case 0x20:                 /* MPEG-4 */
13376       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13377        * profile_and_level_indication */
13378       if (data_ptr != NULL && data_len >= 5 &&
13379           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13380         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13381             data_ptr + 4, data_len - 4);
13382       }
13383       break;                    /* Nothing special needed here */
13384     case 0x21:                 /* H.264 */
13385       codec_name = "H.264 / AVC";
13386       caps = gst_caps_new_simple ("video/x-h264",
13387           "stream-format", G_TYPE_STRING, "avc",
13388           "alignment", G_TYPE_STRING, "au", NULL);
13389       break;
13390     case 0x40:                 /* AAC (any) */
13391     case 0x66:                 /* AAC Main */
13392     case 0x67:                 /* AAC LC */
13393     case 0x68:                 /* AAC SSR */
13394       /* Override channels and rate based on the codec_data, as it's often
13395        * wrong. */
13396       /* Only do so for basic setup without HE-AAC extension */
13397       if (data_ptr && data_len == 2) {
13398         guint channels, rate;
13399
13400         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13401         if (channels > 0)
13402           entry->n_channels = channels;
13403
13404         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13405         if (rate > 0)
13406           entry->rate = rate;
13407       }
13408
13409       /* Set level and profile if possible */
13410       if (data_ptr != NULL && data_len >= 2) {
13411         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13412             data_ptr, data_len);
13413       } else {
13414         const gchar *profile_str = NULL;
13415         GstBuffer *buffer;
13416         GstMapInfo map;
13417         guint8 *codec_data;
13418         gint rate_idx, profile;
13419
13420         /* No codec_data, let's invent something.
13421          * FIXME: This is wrong for SBR! */
13422
13423         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13424
13425         buffer = gst_buffer_new_and_alloc (2);
13426         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13427         codec_data = map.data;
13428
13429         rate_idx =
13430             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13431             (stream)->rate);
13432
13433         switch (object_type_id) {
13434           case 0x66:
13435             profile_str = "main";
13436             profile = 0;
13437             break;
13438           case 0x67:
13439             profile_str = "lc";
13440             profile = 1;
13441             break;
13442           case 0x68:
13443             profile_str = "ssr";
13444             profile = 2;
13445             break;
13446           default:
13447             profile = 3;
13448             break;
13449         }
13450
13451         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13452         codec_data[1] =
13453             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13454
13455         gst_buffer_unmap (buffer, &map);
13456         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13457             GST_TYPE_BUFFER, buffer, NULL);
13458         gst_buffer_unref (buffer);
13459
13460         if (profile_str) {
13461           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13462               G_TYPE_STRING, profile_str, NULL);
13463         }
13464       }
13465       break;
13466     case 0x60:                 /* MPEG-2, various profiles */
13467     case 0x61:
13468     case 0x62:
13469     case 0x63:
13470     case 0x64:
13471     case 0x65:
13472       codec_name = "MPEG-2 video";
13473       caps = gst_caps_new_simple ("video/mpeg",
13474           "mpegversion", G_TYPE_INT, 2,
13475           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13476       break;
13477     case 0x69:                 /* MPEG-2 BC audio */
13478     case 0x6B:                 /* MPEG-1 audio */
13479       caps = gst_caps_new_simple ("audio/mpeg",
13480           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13481       codec_name = "MPEG-1 audio";
13482       break;
13483     case 0x6A:                 /* MPEG-1 */
13484       codec_name = "MPEG-1 video";
13485       caps = gst_caps_new_simple ("video/mpeg",
13486           "mpegversion", G_TYPE_INT, 1,
13487           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13488       break;
13489     case 0x6C:                 /* MJPEG */
13490       caps =
13491           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13492           NULL);
13493       codec_name = "Motion-JPEG";
13494       break;
13495     case 0x6D:                 /* PNG */
13496       caps =
13497           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13498           NULL);
13499       codec_name = "PNG still images";
13500       break;
13501     case 0x6E:                 /* JPEG2000 */
13502       codec_name = "JPEG-2000";
13503       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13504       break;
13505     case 0xA4:                 /* Dirac */
13506       codec_name = "Dirac";
13507       caps = gst_caps_new_empty_simple ("video/x-dirac");
13508       break;
13509     case 0xA5:                 /* AC3 */
13510       codec_name = "AC-3 audio";
13511       caps = gst_caps_new_simple ("audio/x-ac3",
13512           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13513       break;
13514     case 0xA9:                 /* AC3 */
13515       codec_name = "DTS audio";
13516       caps = gst_caps_new_simple ("audio/x-dts",
13517           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13518       break;
13519     case 0xE1:                 /* QCELP */
13520       /* QCELP, the codec_data is a riff tag (little endian) with
13521        * 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). */
13522       caps = gst_caps_new_empty_simple ("audio/qcelp");
13523       codec_name = "QCELP";
13524       break;
13525     default:
13526       break;
13527   }
13528
13529   /* If we have a replacement caps, then change our caps for this stream */
13530   if (caps) {
13531     gst_caps_unref (entry->caps);
13532     entry->caps = caps;
13533   }
13534
13535   if (codec_name && list)
13536     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13537         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13538
13539   /* Add the codec_data attribute to caps, if we have it */
13540   if (data_ptr) {
13541     GstBuffer *buffer;
13542
13543     buffer = gst_buffer_new_and_alloc (data_len);
13544     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13545
13546     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13547     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13548
13549     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13550         buffer, NULL);
13551     gst_buffer_unref (buffer);
13552   }
13553
13554 }
13555
13556 static inline GstCaps *
13557 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13558 {
13559   GstCaps *caps;
13560   guint i;
13561   char *s, fourstr[5];
13562
13563   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13564   for (i = 0; i < 4; i++) {
13565     if (!g_ascii_isalnum (fourstr[i]))
13566       fourstr[i] = '_';
13567   }
13568   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13569   caps = gst_caps_new_empty_simple (s);
13570   g_free (s);
13571   return caps;
13572 }
13573
13574 #define _codec(name) \
13575   do { \
13576     if (codec_name) { \
13577       *codec_name = g_strdup (name); \
13578     } \
13579   } while (0)
13580
13581 static GstCaps *
13582 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13583     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13584     const guint8 * stsd_entry_data, gchar ** codec_name)
13585 {
13586   GstCaps *caps = NULL;
13587   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13588
13589   switch (fourcc) {
13590     case FOURCC_png:
13591       _codec ("PNG still images");
13592       caps = gst_caps_new_empty_simple ("image/png");
13593       break;
13594     case FOURCC_jpeg:
13595       _codec ("JPEG still images");
13596       caps =
13597           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13598           NULL);
13599       break;
13600     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13601     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13602     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13603     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13604       _codec ("Motion-JPEG");
13605       caps =
13606           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13607           NULL);
13608       break;
13609     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13610       _codec ("Motion-JPEG format B");
13611       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13612       break;
13613     case FOURCC_mjp2:
13614       _codec ("JPEG-2000");
13615       /* override to what it should be according to spec, avoid palette_data */
13616       entry->bits_per_sample = 24;
13617       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13618       break;
13619     case FOURCC_SVQ3:
13620       _codec ("Sorensen video v.3");
13621       caps = gst_caps_new_simple ("video/x-svq",
13622           "svqversion", G_TYPE_INT, 3, NULL);
13623       break;
13624     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13625     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13626       _codec ("Sorensen video v.1");
13627       caps = gst_caps_new_simple ("video/x-svq",
13628           "svqversion", G_TYPE_INT, 1, NULL);
13629       break;
13630     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13631       caps = gst_caps_new_empty_simple ("video/x-raw");
13632       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13633       _codec ("Windows Raw RGB");
13634       stream->alignment = 32;
13635       break;
13636     case FOURCC_raw_:
13637     {
13638       guint16 bps;
13639
13640       bps = QT_UINT16 (stsd_entry_data + 82);
13641       switch (bps) {
13642         case 15:
13643           format = GST_VIDEO_FORMAT_RGB15;
13644           break;
13645         case 16:
13646           format = GST_VIDEO_FORMAT_RGB16;
13647           break;
13648         case 24:
13649           format = GST_VIDEO_FORMAT_RGB;
13650           break;
13651         case 32:
13652           format = GST_VIDEO_FORMAT_ARGB;
13653           break;
13654         default:
13655           /* unknown */
13656           break;
13657       }
13658       break;
13659     }
13660     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13661       format = GST_VIDEO_FORMAT_I420;
13662       break;
13663     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13664     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13665       format = GST_VIDEO_FORMAT_I420;
13666       break;
13667     case FOURCC_2vuy:
13668     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13669       format = GST_VIDEO_FORMAT_UYVY;
13670       break;
13671     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13672       format = GST_VIDEO_FORMAT_v308;
13673       break;
13674     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13675       format = GST_VIDEO_FORMAT_v216;
13676       break;
13677     case FOURCC_v210:
13678       format = GST_VIDEO_FORMAT_v210;
13679       break;
13680     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13681       format = GST_VIDEO_FORMAT_r210;
13682       break;
13683       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13684          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13685          format = GST_VIDEO_FORMAT_v410;
13686          break;
13687        */
13688       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13689        * but different order than AYUV
13690        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13691        format = GST_VIDEO_FORMAT_v408;
13692        break;
13693        */
13694     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13695     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13696       _codec ("MPEG-1 video");
13697       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13698           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13699       break;
13700     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13701     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13702     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13703     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13704     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13705     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13706     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13707     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13708     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13709     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13710     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13711     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13712     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13713     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13714     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13715     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13716     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13717     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13718     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13719     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13720     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13721     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13722     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13723     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13724     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13725     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13726     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13727     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13728     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13729     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13730     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13731     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13732     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13733     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13734     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13735     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13736     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13737     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13738     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13739     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13740     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13741     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13742     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13743     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13744     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13745     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13746     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13747       _codec ("MPEG-2 video");
13748       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13749           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13750       break;
13751     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13752       _codec ("GIF still images");
13753       caps = gst_caps_new_empty_simple ("image/gif");
13754       break;
13755     case FOURCC_h263:
13756     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13757     case FOURCC_s263:
13758     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13759       _codec ("H.263");
13760       /* ffmpeg uses the height/width props, don't know why */
13761       caps = gst_caps_new_simple ("video/x-h263",
13762           "variant", G_TYPE_STRING, "itu", NULL);
13763       break;
13764     case FOURCC_mp4v:
13765     case FOURCC_MP4V:
13766       _codec ("MPEG-4 video");
13767       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13768           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13769       break;
13770     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13771     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13772       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13773       caps = gst_caps_new_simple ("video/x-msmpeg",
13774           "msmpegversion", G_TYPE_INT, 43, NULL);
13775       break;
13776     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13777       _codec ("DivX 3");
13778       caps = gst_caps_new_simple ("video/x-divx",
13779           "divxversion", G_TYPE_INT, 3, NULL);
13780       break;
13781     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13782     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13783       _codec ("DivX 4");
13784       caps = gst_caps_new_simple ("video/x-divx",
13785           "divxversion", G_TYPE_INT, 4, NULL);
13786       break;
13787     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13788       _codec ("DivX 5");
13789       caps = gst_caps_new_simple ("video/x-divx",
13790           "divxversion", G_TYPE_INT, 5, NULL);
13791       break;
13792
13793     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13794       _codec ("FFV1");
13795       caps = gst_caps_new_simple ("video/x-ffv",
13796           "ffvversion", G_TYPE_INT, 1, NULL);
13797       break;
13798
13799     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13800     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13801     case FOURCC_XVID:
13802     case FOURCC_xvid:
13803     case FOURCC_FMP4:
13804     case FOURCC_fmp4:
13805     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13806       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13807           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13808       _codec ("MPEG-4");
13809       break;
13810
13811     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13812       _codec ("Cinepak");
13813       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13814       break;
13815     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13816       _codec ("Apple QuickDraw");
13817       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13818       break;
13819     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13820       _codec ("Apple video");
13821       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13822       break;
13823     case FOURCC_H264:
13824     case FOURCC_avc1:
13825       _codec ("H.264 / AVC");
13826       caps = gst_caps_new_simple ("video/x-h264",
13827           "stream-format", G_TYPE_STRING, "avc",
13828           "alignment", G_TYPE_STRING, "au", NULL);
13829       break;
13830     case FOURCC_avc3:
13831       _codec ("H.264 / AVC");
13832       caps = gst_caps_new_simple ("video/x-h264",
13833           "stream-format", G_TYPE_STRING, "avc3",
13834           "alignment", G_TYPE_STRING, "au", NULL);
13835       break;
13836     case FOURCC_H265:
13837     case FOURCC_hvc1:
13838       _codec ("H.265 / HEVC");
13839       caps = gst_caps_new_simple ("video/x-h265",
13840           "stream-format", G_TYPE_STRING, "hvc1",
13841           "alignment", G_TYPE_STRING, "au", NULL);
13842       break;
13843     case FOURCC_hev1:
13844       _codec ("H.265 / HEVC");
13845       caps = gst_caps_new_simple ("video/x-h265",
13846           "stream-format", G_TYPE_STRING, "hev1",
13847           "alignment", G_TYPE_STRING, "au", NULL);
13848       break;
13849     case FOURCC_rle_:
13850       _codec ("Run-length encoding");
13851       caps = gst_caps_new_simple ("video/x-rle",
13852           "layout", G_TYPE_STRING, "quicktime", NULL);
13853       break;
13854     case FOURCC_WRLE:
13855       _codec ("Run-length encoding");
13856       caps = gst_caps_new_simple ("video/x-rle",
13857           "layout", G_TYPE_STRING, "microsoft", NULL);
13858       break;
13859     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13860     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13861       _codec ("Indeo Video 3");
13862       caps = gst_caps_new_simple ("video/x-indeo",
13863           "indeoversion", G_TYPE_INT, 3, NULL);
13864       break;
13865     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13866     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13867       _codec ("Intel Video 4");
13868       caps = gst_caps_new_simple ("video/x-indeo",
13869           "indeoversion", G_TYPE_INT, 4, NULL);
13870       break;
13871     case FOURCC_dvcp:
13872     case FOURCC_dvc_:
13873     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13874     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13875     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13876     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13877     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13878     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13879       _codec ("DV Video");
13880       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13881           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13882       break;
13883     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13884     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13885       _codec ("DVCPro50 Video");
13886       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13887           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13888       break;
13889     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13890     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13891       _codec ("DVCProHD Video");
13892       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13893           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13894       break;
13895     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13896       _codec ("Apple Graphics (SMC)");
13897       caps = gst_caps_new_empty_simple ("video/x-smc");
13898       break;
13899     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13900       _codec ("VP3");
13901       caps = gst_caps_new_empty_simple ("video/x-vp3");
13902       break;
13903     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13904       _codec ("VP6 Flash");
13905       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13906       break;
13907     case FOURCC_XiTh:
13908       _codec ("Theora");
13909       caps = gst_caps_new_empty_simple ("video/x-theora");
13910       /* theora uses one byte of padding in the data stream because it does not
13911        * allow 0 sized packets while theora does */
13912       entry->padding = 1;
13913       break;
13914     case FOURCC_drac:
13915       _codec ("Dirac");
13916       caps = gst_caps_new_empty_simple ("video/x-dirac");
13917       break;
13918     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13919       _codec ("TIFF still images");
13920       caps = gst_caps_new_empty_simple ("image/tiff");
13921       break;
13922     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13923       _codec ("Apple Intermediate Codec");
13924       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13925       break;
13926     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13927       _codec ("AVID DNxHD");
13928       caps = gst_caps_from_string ("video/x-dnxhd");
13929       break;
13930     case FOURCC_VP80:
13931       _codec ("On2 VP8");
13932       caps = gst_caps_from_string ("video/x-vp8");
13933       break;
13934     case FOURCC_apcs:
13935       _codec ("Apple ProRes LT");
13936       caps =
13937           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13938           NULL);
13939       break;
13940     case FOURCC_apch:
13941       _codec ("Apple ProRes HQ");
13942       caps =
13943           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13944           NULL);
13945       break;
13946     case FOURCC_apcn:
13947       _codec ("Apple ProRes");
13948       caps =
13949           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13950           "standard", NULL);
13951       break;
13952     case FOURCC_apco:
13953       _codec ("Apple ProRes Proxy");
13954       caps =
13955           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13956           "proxy", NULL);
13957       break;
13958     case FOURCC_ap4h:
13959       _codec ("Apple ProRes 4444");
13960       caps =
13961           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13962           "4444", NULL);
13963       break;
13964     case FOURCC_ap4x:
13965       _codec ("Apple ProRes 4444 XQ");
13966       caps =
13967           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13968           "4444xq", NULL);
13969       break;
13970     case FOURCC_cfhd:
13971       _codec ("GoPro CineForm");
13972       caps = gst_caps_from_string ("video/x-cineform");
13973       break;
13974     case FOURCC_vc_1:
13975     case FOURCC_ovc1:
13976       _codec ("VC-1");
13977       caps = gst_caps_new_simple ("video/x-wmv",
13978           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13979       break;
13980     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13981     default:
13982     {
13983       caps = _get_unknown_codec_name ("video", fourcc);
13984       break;
13985     }
13986   }
13987
13988   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13989     GstVideoInfo info;
13990
13991     gst_video_info_init (&info);
13992     gst_video_info_set_format (&info, format, entry->width, entry->height);
13993
13994     caps = gst_video_info_to_caps (&info);
13995     *codec_name = gst_pb_utils_get_codec_description (caps);
13996
13997     /* enable clipping for raw video streams */
13998     stream->need_clip = TRUE;
13999     stream->alignment = 32;
14000   }
14001
14002   return caps;
14003 }
14004
14005 static guint
14006 round_up_pow2 (guint n)
14007 {
14008   n = n - 1;
14009   n = n | (n >> 1);
14010   n = n | (n >> 2);
14011   n = n | (n >> 4);
14012   n = n | (n >> 8);
14013   n = n | (n >> 16);
14014   return n + 1;
14015 }
14016
14017 static GstCaps *
14018 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14019     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14020     int len, gchar ** codec_name)
14021 {
14022   GstCaps *caps;
14023   const GstStructure *s;
14024   const gchar *name;
14025   gint endian = 0;
14026   GstAudioFormat format = 0;
14027   gint depth;
14028
14029   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14030
14031   depth = entry->bytes_per_packet * 8;
14032
14033   switch (fourcc) {
14034     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14035     case FOURCC_raw_:
14036       /* 8-bit audio is unsigned */
14037       if (depth == 8)
14038         format = GST_AUDIO_FORMAT_U8;
14039       /* otherwise it's signed and big-endian just like 'twos' */
14040     case FOURCC_twos:
14041       endian = G_BIG_ENDIAN;
14042       /* fall-through */
14043     case FOURCC_sowt:
14044     {
14045       gchar *str;
14046
14047       if (!endian)
14048         endian = G_LITTLE_ENDIAN;
14049
14050       if (!format)
14051         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14052
14053       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14054       _codec (str);
14055       g_free (str);
14056
14057       caps = gst_caps_new_simple ("audio/x-raw",
14058           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14059           "layout", G_TYPE_STRING, "interleaved", NULL);
14060       stream->alignment = GST_ROUND_UP_8 (depth);
14061       stream->alignment = round_up_pow2 (stream->alignment);
14062       break;
14063     }
14064     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14065       _codec ("Raw 64-bit floating-point audio");
14066       caps = gst_caps_new_simple ("audio/x-raw",
14067           "format", G_TYPE_STRING, "F64BE",
14068           "layout", G_TYPE_STRING, "interleaved", NULL);
14069       stream->alignment = 8;
14070       break;
14071     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14072       _codec ("Raw 32-bit floating-point audio");
14073       caps = gst_caps_new_simple ("audio/x-raw",
14074           "format", G_TYPE_STRING, "F32BE",
14075           "layout", G_TYPE_STRING, "interleaved", NULL);
14076       stream->alignment = 4;
14077       break;
14078     case FOURCC_in24:
14079       _codec ("Raw 24-bit PCM audio");
14080       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14081        * endian later */
14082       caps = gst_caps_new_simple ("audio/x-raw",
14083           "format", G_TYPE_STRING, "S24BE",
14084           "layout", G_TYPE_STRING, "interleaved", NULL);
14085       stream->alignment = 4;
14086       break;
14087     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14088       _codec ("Raw 32-bit PCM audio");
14089       caps = gst_caps_new_simple ("audio/x-raw",
14090           "format", G_TYPE_STRING, "S32BE",
14091           "layout", G_TYPE_STRING, "interleaved", NULL);
14092       stream->alignment = 4;
14093       break;
14094     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14095       _codec ("Raw 16-bit PCM audio");
14096       caps = gst_caps_new_simple ("audio/x-raw",
14097           "format", G_TYPE_STRING, "S16LE",
14098           "layout", G_TYPE_STRING, "interleaved", NULL);
14099       stream->alignment = 2;
14100       break;
14101     case FOURCC_ulaw:
14102       _codec ("Mu-law audio");
14103       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14104       break;
14105     case FOURCC_alaw:
14106       _codec ("A-law audio");
14107       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14108       break;
14109     case 0x0200736d:
14110     case 0x6d730002:
14111       _codec ("Microsoft ADPCM");
14112       /* Microsoft ADPCM-ACM code 2 */
14113       caps = gst_caps_new_simple ("audio/x-adpcm",
14114           "layout", G_TYPE_STRING, "microsoft", NULL);
14115       break;
14116     case 0x1100736d:
14117     case 0x6d730011:
14118       _codec ("DVI/IMA ADPCM");
14119       caps = gst_caps_new_simple ("audio/x-adpcm",
14120           "layout", G_TYPE_STRING, "dvi", NULL);
14121       break;
14122     case 0x1700736d:
14123     case 0x6d730017:
14124       _codec ("DVI/Intel IMA ADPCM");
14125       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14126       caps = gst_caps_new_simple ("audio/x-adpcm",
14127           "layout", G_TYPE_STRING, "quicktime", NULL);
14128       break;
14129     case 0x5500736d:
14130     case 0x6d730055:
14131       /* MPEG layer 3, CBR only (pre QT4.1) */
14132     case FOURCC__mp3:
14133       _codec ("MPEG-1 layer 3");
14134       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14135       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14136           "mpegversion", G_TYPE_INT, 1, NULL);
14137       break;
14138     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14139       _codec ("MPEG-1 layer 2");
14140       /* MPEG layer 2 */
14141       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14142           "mpegversion", G_TYPE_INT, 1, NULL);
14143       break;
14144     case 0x20736d:
14145     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14146       _codec ("EAC-3 audio");
14147       caps = gst_caps_new_simple ("audio/x-eac3",
14148           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14149       entry->sampled = TRUE;
14150       break;
14151     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14152     case FOURCC_ac_3:
14153       _codec ("AC-3 audio");
14154       caps = gst_caps_new_simple ("audio/x-ac3",
14155           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14156       entry->sampled = TRUE;
14157       break;
14158     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14159     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14160       _codec ("DTS audio");
14161       caps = gst_caps_new_simple ("audio/x-dts",
14162           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14163       entry->sampled = TRUE;
14164       break;
14165     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14166     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14167       _codec ("DTS-HD audio");
14168       caps = gst_caps_new_simple ("audio/x-dts",
14169           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14170       entry->sampled = TRUE;
14171       break;
14172     case FOURCC_MAC3:
14173       _codec ("MACE-3");
14174       caps = gst_caps_new_simple ("audio/x-mace",
14175           "maceversion", G_TYPE_INT, 3, NULL);
14176       break;
14177     case FOURCC_MAC6:
14178       _codec ("MACE-6");
14179       caps = gst_caps_new_simple ("audio/x-mace",
14180           "maceversion", G_TYPE_INT, 6, NULL);
14181       break;
14182     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14183       /* ogg/vorbis */
14184       caps = gst_caps_new_empty_simple ("application/ogg");
14185       break;
14186     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14187       _codec ("DV audio");
14188       caps = gst_caps_new_empty_simple ("audio/x-dv");
14189       break;
14190     case FOURCC_mp4a:
14191       _codec ("MPEG-4 AAC audio");
14192       caps = gst_caps_new_simple ("audio/mpeg",
14193           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14194           "stream-format", G_TYPE_STRING, "raw", NULL);
14195       break;
14196     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14197       _codec ("QDesign Music");
14198       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14199       break;
14200     case FOURCC_QDM2:
14201       _codec ("QDesign Music v.2");
14202       /* FIXME: QDesign music version 2 (no constant) */
14203       if (FALSE && data) {
14204         caps = gst_caps_new_simple ("audio/x-qdm2",
14205             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14206             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14207             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14208       } else {
14209         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14210       }
14211       break;
14212     case FOURCC_agsm:
14213       _codec ("GSM audio");
14214       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14215       break;
14216     case FOURCC_samr:
14217       _codec ("AMR audio");
14218       caps = gst_caps_new_empty_simple ("audio/AMR");
14219       break;
14220     case FOURCC_sawb:
14221       _codec ("AMR-WB audio");
14222       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14223       break;
14224     case FOURCC_ima4:
14225       _codec ("Quicktime IMA ADPCM");
14226       caps = gst_caps_new_simple ("audio/x-adpcm",
14227           "layout", G_TYPE_STRING, "quicktime", NULL);
14228       break;
14229     case FOURCC_alac:
14230       _codec ("Apple lossless audio");
14231       caps = gst_caps_new_empty_simple ("audio/x-alac");
14232       break;
14233     case FOURCC_fLaC:
14234       _codec ("Free Lossless Audio Codec");
14235       caps = gst_caps_new_simple ("audio/x-flac",
14236           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14237       break;
14238     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14239       _codec ("QualComm PureVoice");
14240       caps = gst_caps_from_string ("audio/qcelp");
14241       break;
14242     case FOURCC_wma_:
14243     case FOURCC_owma:
14244       _codec ("WMA");
14245       caps = gst_caps_new_empty_simple ("audio/x-wma");
14246       break;
14247     case FOURCC_opus:
14248       _codec ("Opus");
14249       caps = gst_caps_new_empty_simple ("audio/x-opus");
14250       break;
14251     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
14252     {
14253       guint32 flags = 0;
14254       guint32 depth = 0;
14255       guint32 width = 0;
14256       GstAudioFormat format;
14257       enum
14258       {
14259         FLAG_IS_FLOAT = 0x1,
14260         FLAG_IS_BIG_ENDIAN = 0x2,
14261         FLAG_IS_SIGNED = 0x4,
14262         FLAG_IS_PACKED = 0x8,
14263         FLAG_IS_ALIGNED_HIGH = 0x10,
14264         FLAG_IS_NON_INTERLEAVED = 0x20
14265       };
14266       _codec ("Raw LPCM audio");
14267
14268       if (data && len >= 56) {
14269         depth = QT_UINT32 (data + 40);
14270         flags = QT_UINT32 (data + 44);
14271         width = QT_UINT32 (data + 48) * 8 / entry->n_channels;
14272       }
14273       if ((flags & FLAG_IS_FLOAT) == 0) {
14274         if (depth == 0)
14275           depth = 16;
14276         if (width == 0)
14277           width = 16;
14278         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14279             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14280             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14281         caps = gst_caps_new_simple ("audio/x-raw",
14282             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14283             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14284             "non-interleaved" : "interleaved", NULL);
14285         stream->alignment = GST_ROUND_UP_8 (depth);
14286         stream->alignment = round_up_pow2 (stream->alignment);
14287       } else {
14288         if (width == 0)
14289           width = 32;
14290         if (width == 64) {
14291           if (flags & FLAG_IS_BIG_ENDIAN)
14292             format = GST_AUDIO_FORMAT_F64BE;
14293           else
14294             format = GST_AUDIO_FORMAT_F64LE;
14295         } else {
14296           if (flags & FLAG_IS_BIG_ENDIAN)
14297             format = GST_AUDIO_FORMAT_F32BE;
14298           else
14299             format = GST_AUDIO_FORMAT_F32LE;
14300         }
14301         caps = gst_caps_new_simple ("audio/x-raw",
14302             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14303             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14304             "non-interleaved" : "interleaved", NULL);
14305         stream->alignment = width / 8;
14306       }
14307       break;
14308     }
14309     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14310       /* ? */
14311     default:
14312     {
14313       caps = _get_unknown_codec_name ("audio", fourcc);
14314       break;
14315     }
14316   }
14317
14318   if (caps) {
14319     GstCaps *templ_caps =
14320         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14321     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14322     gst_caps_unref (caps);
14323     gst_caps_unref (templ_caps);
14324     caps = intersection;
14325   }
14326
14327   /* enable clipping for raw audio streams */
14328   s = gst_caps_get_structure (caps, 0);
14329   name = gst_structure_get_name (s);
14330   if (g_str_has_prefix (name, "audio/x-raw")) {
14331     stream->need_clip = TRUE;
14332     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14333     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14334   }
14335   return caps;
14336 }
14337
14338 static GstCaps *
14339 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14340     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14341     const guint8 * stsd_entry_data, gchar ** codec_name)
14342 {
14343   GstCaps *caps;
14344
14345   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14346
14347   switch (fourcc) {
14348     case FOURCC_mp4s:
14349       _codec ("DVD subtitle");
14350       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14351       stream->need_process = TRUE;
14352       break;
14353     case FOURCC_text:
14354       _codec ("Quicktime timed text");
14355       goto text;
14356     case FOURCC_tx3g:
14357       _codec ("3GPP timed text");
14358     text:
14359       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14360           "utf8", NULL);
14361       /* actual text piece needs to be extracted */
14362       stream->need_process = TRUE;
14363       break;
14364     case FOURCC_stpp:
14365       _codec ("XML subtitles");
14366       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14367       break;
14368     default:
14369     {
14370       caps = _get_unknown_codec_name ("text", fourcc);
14371       break;
14372     }
14373   }
14374   return caps;
14375 }
14376
14377 static GstCaps *
14378 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14379     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14380     const guint8 * stsd_entry_data, gchar ** codec_name)
14381 {
14382   GstCaps *caps;
14383
14384   switch (fourcc) {
14385     case FOURCC_m1v:
14386       _codec ("MPEG 1 video");
14387       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14388           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14389       break;
14390     default:
14391       caps = NULL;
14392       break;
14393   }
14394   return caps;
14395 }
14396
14397 static void
14398 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14399     const gchar * system_id)
14400 {
14401   gint i;
14402
14403   if (!qtdemux->protection_system_ids)
14404     qtdemux->protection_system_ids =
14405         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14406   /* Check whether we already have an entry for this system ID. */
14407   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14408     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14409     if (g_ascii_strcasecmp (system_id, id) == 0) {
14410       return;
14411     }
14412   }
14413   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14414   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14415           -1));
14416 }