qtdemux: Don't perform seeks with inconsistent seek values
[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         res = TRUE;
912       }
913       break;
914     }
915     case GST_QUERY_FORMATS:
916       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
917       res = TRUE;
918       break;
919     case GST_QUERY_SEEKING:{
920       GstFormat fmt;
921       gboolean seekable;
922
923       /* try upstream first */
924       res = gst_pad_query_default (pad, parent, query);
925
926       if (!res) {
927         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
928         if (fmt == GST_FORMAT_TIME) {
929           GstClockTime duration;
930
931           gst_qtdemux_get_duration (qtdemux, &duration);
932           seekable = TRUE;
933           if (!qtdemux->pullbased) {
934             GstQuery *q;
935
936             /* we might be able with help from upstream */
937             seekable = FALSE;
938             q = gst_query_new_seeking (GST_FORMAT_BYTES);
939             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
940               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
941               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
942             }
943             gst_query_unref (q);
944           }
945           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
946           res = TRUE;
947         }
948       }
949       break;
950     }
951     case GST_QUERY_SEGMENT:
952     {
953       GstFormat format;
954       gint64 start, stop;
955
956       format = qtdemux->segment.format;
957
958       start =
959           gst_segment_to_stream_time (&qtdemux->segment, format,
960           qtdemux->segment.start);
961       if ((stop = qtdemux->segment.stop) == -1)
962         stop = qtdemux->segment.duration;
963       else
964         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
965
966       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
967       res = TRUE;
968       break;
969     }
970     default:
971       res = gst_pad_query_default (pad, parent, query);
972       break;
973   }
974
975   return res;
976 }
977
978 static void
979 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
980 {
981   if (G_LIKELY (stream->pad)) {
982     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
983         GST_DEBUG_PAD_NAME (stream->pad));
984
985     if (!gst_tag_list_is_empty (stream->stream_tags)) {
986       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
987           stream->stream_tags);
988       gst_pad_push_event (stream->pad,
989           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
990     }
991
992     if (G_UNLIKELY (stream->send_global_tags)) {
993       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
994           qtdemux->tag_list);
995       gst_pad_push_event (stream->pad,
996           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
997       stream->send_global_tags = FALSE;
998     }
999   }
1000 }
1001
1002 /* push event on all source pads; takes ownership of the event */
1003 static void
1004 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1005 {
1006   guint n;
1007   gboolean has_valid_stream = FALSE;
1008   GstEventType etype = GST_EVENT_TYPE (event);
1009
1010   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1011       GST_EVENT_TYPE_NAME (event));
1012
1013   for (n = 0; n < qtdemux->n_streams; n++) {
1014     GstPad *pad;
1015     QtDemuxStream *stream = qtdemux->streams[n];
1016     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
1017
1018     if ((pad = stream->pad)) {
1019       has_valid_stream = TRUE;
1020
1021       if (etype == GST_EVENT_EOS) {
1022         /* let's not send twice */
1023         if (stream->sent_eos)
1024           continue;
1025         stream->sent_eos = TRUE;
1026       }
1027
1028       gst_pad_push_event (pad, gst_event_ref (event));
1029     }
1030   }
1031
1032   gst_event_unref (event);
1033
1034   /* if it is EOS and there are no pads, post an error */
1035   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1036     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1037   }
1038 }
1039
1040 /* push a pending newsegment event, if any from the streaming thread */
1041 static void
1042 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1043 {
1044   if (qtdemux->pending_newsegment) {
1045     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1046     qtdemux->pending_newsegment = NULL;
1047   }
1048 }
1049
1050 typedef struct
1051 {
1052   guint64 media_time;
1053 } FindData;
1054
1055 static gint
1056 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1057 {
1058   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1059     return 1;
1060   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1061     return 0;
1062
1063   return -1;
1064 }
1065
1066 /* find the index of the sample that includes the data for @media_time using a
1067  * binary search.  Only to be called in optimized cases of linear search below.
1068  *
1069  * Returns the index of the sample.
1070  */
1071 static guint32
1072 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1073     guint64 media_time)
1074 {
1075   QtDemuxSample *result;
1076   guint32 index;
1077
1078   /* convert media_time to mov format */
1079   media_time =
1080       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1081
1082   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1083       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1084       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1085
1086   if (G_LIKELY (result))
1087     index = result - str->samples;
1088   else
1089     index = 0;
1090
1091   return index;
1092 }
1093
1094
1095
1096 /* find the index of the sample that includes the data for @media_offset using a
1097  * linear search
1098  *
1099  * Returns the index of the sample.
1100  */
1101 static guint32
1102 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1103     QtDemuxStream * str, gint64 media_offset)
1104 {
1105   QtDemuxSample *result = str->samples;
1106   guint32 index = 0;
1107
1108   if (result == NULL || str->n_samples == 0)
1109     return -1;
1110
1111   if (media_offset == result->offset)
1112     return index;
1113
1114   result++;
1115   while (index < str->n_samples - 1) {
1116     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1117       goto parse_failed;
1118
1119     if (media_offset < result->offset)
1120       break;
1121
1122     index++;
1123     result++;
1124   }
1125   return index;
1126
1127   /* ERRORS */
1128 parse_failed:
1129   {
1130     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1131     return -1;
1132   }
1133 }
1134
1135 /* find the index of the sample that includes the data for @media_time using a
1136  * linear search, and keeping in mind that not all samples may have been parsed
1137  * yet.  If possible, it will delegate to binary search.
1138  *
1139  * Returns the index of the sample.
1140  */
1141 static guint32
1142 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1143     GstClockTime media_time)
1144 {
1145   guint32 index = 0;
1146   guint64 mov_time;
1147   QtDemuxSample *sample;
1148
1149   /* convert media_time to mov format */
1150   mov_time =
1151       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1152
1153   sample = str->samples;
1154   if (mov_time == sample->timestamp + sample->pts_offset)
1155     return index;
1156
1157   /* use faster search if requested time in already parsed range */
1158   sample = str->samples + str->stbl_index;
1159   if (str->stbl_index >= 0 &&
1160       mov_time <= (sample->timestamp + sample->pts_offset))
1161     return gst_qtdemux_find_index (qtdemux, str, media_time);
1162
1163   while (index < str->n_samples - 1) {
1164     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1165       goto parse_failed;
1166
1167     sample = str->samples + index + 1;
1168     if (mov_time < (sample->timestamp + sample->pts_offset))
1169       break;
1170
1171     index++;
1172   }
1173   return index;
1174
1175   /* ERRORS */
1176 parse_failed:
1177   {
1178     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1179     return -1;
1180   }
1181 }
1182
1183 /* find the index of the keyframe needed to decode the sample at @index
1184  * of stream @str, or of a subsequent keyframe (depending on @next)
1185  *
1186  * Returns the index of the keyframe.
1187  */
1188 static guint32
1189 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1190     guint32 index, gboolean next)
1191 {
1192   guint32 new_index = index;
1193
1194   if (index >= str->n_samples) {
1195     new_index = str->n_samples;
1196     goto beach;
1197   }
1198
1199   /* all keyframes, return index */
1200   if (str->all_keyframe) {
1201     new_index = index;
1202     goto beach;
1203   }
1204
1205   /* else search until we have a keyframe */
1206   while (new_index < str->n_samples) {
1207     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1208       goto parse_failed;
1209
1210     if (str->samples[new_index].keyframe)
1211       break;
1212
1213     if (new_index == 0)
1214       break;
1215
1216     if (next)
1217       new_index++;
1218     else
1219       new_index--;
1220   }
1221
1222   if (new_index == str->n_samples) {
1223     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1224     new_index = -1;
1225   }
1226
1227 beach:
1228   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1229       "gave %u", next ? "after" : "before", index, new_index);
1230
1231   return new_index;
1232
1233   /* ERRORS */
1234 parse_failed:
1235   {
1236     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1237     return -1;
1238   }
1239 }
1240
1241 /* find the segment for @time_position for @stream
1242  *
1243  * Returns the index of the segment containing @time_position.
1244  * Returns the last segment and sets the @eos variable to TRUE
1245  * if the time is beyond the end. @eos may be NULL
1246  */
1247 static guint32
1248 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1249     GstClockTime time_position)
1250 {
1251   gint i;
1252   guint32 seg_idx;
1253
1254   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1255       GST_TIME_ARGS (time_position));
1256
1257   seg_idx = -1;
1258   for (i = 0; i < stream->n_segments; i++) {
1259     QtDemuxSegment *segment = &stream->segments[i];
1260
1261     GST_LOG_OBJECT (stream->pad,
1262         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1263         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1264
1265     /* For the last segment we include stop_time in the last segment */
1266     if (i < stream->n_segments - 1) {
1267       if (segment->time <= time_position && time_position < segment->stop_time) {
1268         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1269         seg_idx = i;
1270         break;
1271       }
1272     } else {
1273       /* Last segment always matches */
1274       seg_idx = i;
1275       break;
1276     }
1277   }
1278   return seg_idx;
1279 }
1280
1281 /* move the stream @str to the sample position @index.
1282  *
1283  * Updates @str->sample_index and marks discontinuity if needed.
1284  */
1285 static void
1286 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1287     guint32 index)
1288 {
1289   /* no change needed */
1290   if (index == str->sample_index)
1291     return;
1292
1293   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1294       str->n_samples);
1295
1296   /* position changed, we have a discont */
1297   str->sample_index = index;
1298   str->offset_in_sample = 0;
1299   /* Each time we move in the stream we store the position where we are
1300    * starting from */
1301   str->from_sample = index;
1302   str->discont = TRUE;
1303 }
1304
1305 static void
1306 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1307     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1308 {
1309   guint64 min_offset;
1310   gint64 min_byte_offset = -1;
1311   gint n;
1312
1313   min_offset = desired_time;
1314
1315   /* for each stream, find the index of the sample in the segment
1316    * and move back to the previous keyframe. */
1317   for (n = 0; n < qtdemux->n_streams; n++) {
1318     QtDemuxStream *str;
1319     guint32 index, kindex;
1320     guint32 seg_idx;
1321     GstClockTime media_start;
1322     GstClockTime media_time;
1323     GstClockTime seg_time;
1324     QtDemuxSegment *seg;
1325     gboolean empty_segment = FALSE;
1326
1327     str = qtdemux->streams[n];
1328
1329     if (CUR_STREAM (str)->sparse && !use_sparse)
1330       continue;
1331
1332     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1333     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1334
1335     /* get segment and time in the segment */
1336     seg = &str->segments[seg_idx];
1337     seg_time = (desired_time - seg->time) * seg->rate;
1338
1339     while (QTSEGMENT_IS_EMPTY (seg)) {
1340       seg_time = 0;
1341       empty_segment = TRUE;
1342       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1343           seg_idx);
1344       seg_idx++;
1345       if (seg_idx == str->n_segments)
1346         break;
1347       seg = &str->segments[seg_idx];
1348     }
1349
1350     if (seg_idx == str->n_segments) {
1351       /* FIXME track shouldn't have the last segment as empty, but if it
1352        * happens we better handle it */
1353       continue;
1354     }
1355
1356     /* get the media time in the segment */
1357     media_start = seg->media_start + seg_time;
1358
1359     /* get the index of the sample with media time */
1360     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1361     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1362         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1363         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1364         empty_segment);
1365
1366     /* shift to next frame if we are looking for next keyframe */
1367     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1368         && index < str->stbl_index)
1369       index++;
1370
1371     if (!empty_segment) {
1372       /* find previous keyframe */
1373       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1374
1375       /* we will settle for one before if none found after */
1376       if (next && kindex == -1)
1377         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1378
1379       /* if the keyframe is at a different position, we need to update the
1380        * requested seek time */
1381       if (index != kindex) {
1382         index = kindex;
1383
1384         /* get timestamp of keyframe */
1385         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1386         GST_DEBUG_OBJECT (qtdemux,
1387             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1388             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1389             str->samples[kindex].offset);
1390
1391         /* keyframes in the segment get a chance to change the
1392          * desired_offset. keyframes out of the segment are
1393          * ignored. */
1394         if (media_time >= seg->media_start) {
1395           GstClockTime seg_time;
1396
1397           /* this keyframe is inside the segment, convert back to
1398            * segment time */
1399           seg_time = (media_time - seg->media_start) + seg->time;
1400           if ((!next && (seg_time < min_offset)) ||
1401               (next && (seg_time > min_offset)))
1402             min_offset = seg_time;
1403         }
1404       }
1405     }
1406
1407     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1408       min_byte_offset = str->samples[index].offset;
1409   }
1410
1411   if (key_time)
1412     *key_time = min_offset;
1413   if (key_offset)
1414     *key_offset = min_byte_offset;
1415 }
1416
1417 static gboolean
1418 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1419     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1420 {
1421   gboolean res;
1422
1423   g_return_val_if_fail (format != NULL, FALSE);
1424   g_return_val_if_fail (cur != NULL, FALSE);
1425   g_return_val_if_fail (stop != NULL, FALSE);
1426
1427   if (*format == GST_FORMAT_TIME)
1428     return TRUE;
1429
1430   res = TRUE;
1431   if (cur_type != GST_SEEK_TYPE_NONE)
1432     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1433   if (res && stop_type != GST_SEEK_TYPE_NONE)
1434     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1435
1436   if (res)
1437     *format = GST_FORMAT_TIME;
1438
1439   return res;
1440 }
1441
1442 /* perform seek in push based mode:
1443    find BYTE position to move to based on time and delegate to upstream
1444 */
1445 static gboolean
1446 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1447 {
1448   gdouble rate;
1449   GstFormat format;
1450   GstSeekFlags flags;
1451   GstSeekType cur_type, stop_type;
1452   gint64 cur, stop, key_cur;
1453   gboolean res;
1454   gint64 byte_cur;
1455   gint64 original_stop;
1456   guint32 seqnum;
1457
1458   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1459
1460   gst_event_parse_seek (event, &rate, &format, &flags,
1461       &cur_type, &cur, &stop_type, &stop);
1462   seqnum = gst_event_get_seqnum (event);
1463
1464   /* only forward streaming and seeking is possible */
1465   if (rate <= 0)
1466     goto unsupported_seek;
1467
1468   /* convert to TIME if needed and possible */
1469   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1470           stop_type, &stop))
1471     goto no_format;
1472
1473   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1474    * the original stop position to use when upstream pushes the new segment
1475    * for this seek */
1476   original_stop = stop;
1477   stop = -1;
1478
1479   /* find reasonable corresponding BYTE position,
1480    * also try to mind about keyframes, since we can not go back a bit for them
1481    * later on */
1482   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1483    * mostly just work, but let's not yet boldly go there  ... */
1484   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1485
1486   if (byte_cur == -1)
1487     goto abort_seek;
1488
1489   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1490       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1491       stop);
1492
1493   GST_OBJECT_LOCK (qtdemux);
1494   qtdemux->seek_offset = byte_cur;
1495   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1496     qtdemux->push_seek_start = cur;
1497   } else {
1498     qtdemux->push_seek_start = key_cur;
1499   }
1500
1501   if (stop_type == GST_SEEK_TYPE_NONE) {
1502     qtdemux->push_seek_stop = qtdemux->segment.stop;
1503   } else {
1504     qtdemux->push_seek_stop = original_stop;
1505   }
1506   GST_OBJECT_UNLOCK (qtdemux);
1507
1508   /* BYTE seek event */
1509   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1510       stop_type, stop);
1511   gst_event_set_seqnum (event, seqnum);
1512   res = gst_pad_push_event (qtdemux->sinkpad, event);
1513
1514   return res;
1515
1516   /* ERRORS */
1517 abort_seek:
1518   {
1519     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1520         "seek aborted.");
1521     return FALSE;
1522   }
1523 unsupported_seek:
1524   {
1525     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1526     return FALSE;
1527   }
1528 no_format:
1529   {
1530     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1531     return FALSE;
1532   }
1533 }
1534
1535 /* perform the seek.
1536  *
1537  * We set all segment_indexes in the streams to unknown and
1538  * adjust the time_position to the desired position. this is enough
1539  * to trigger a segment switch in the streaming thread to start
1540  * streaming from the desired position.
1541  *
1542  * Keyframe seeking is a little more complicated when dealing with
1543  * segments. Ideally we want to move to the previous keyframe in
1544  * the segment but there might not be a keyframe in the segment. In
1545  * fact, none of the segments could contain a keyframe. We take a
1546  * practical approach: seek to the previous keyframe in the segment,
1547  * if there is none, seek to the beginning of the segment.
1548  *
1549  * Called with STREAM_LOCK
1550  */
1551 static gboolean
1552 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1553     guint32 seqnum, GstSeekFlags flags)
1554 {
1555   gint64 desired_offset;
1556   gint n;
1557
1558   desired_offset = segment->position;
1559
1560   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1561       GST_TIME_ARGS (desired_offset));
1562
1563   /* may not have enough fragmented info to do this adjustment,
1564    * and we can't scan (and probably should not) at this time with
1565    * possibly flushing upstream */
1566   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1567     gint64 min_offset;
1568     gboolean next, before, after;
1569
1570     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1571     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1572     next = after && !before;
1573     if (segment->rate < 0)
1574       next = !next;
1575
1576     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1577         NULL);
1578     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1579         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1580     desired_offset = min_offset;
1581   }
1582
1583   /* and set all streams to the final position */
1584   gst_flow_combiner_reset (qtdemux->flowcombiner);
1585   qtdemux->segment_seqnum = seqnum;
1586   for (n = 0; n < qtdemux->n_streams; n++) {
1587     QtDemuxStream *stream = qtdemux->streams[n];
1588
1589     stream->time_position = desired_offset;
1590     stream->accumulated_base = 0;
1591     stream->sample_index = -1;
1592     stream->offset_in_sample = 0;
1593     stream->segment_index = -1;
1594     stream->sent_eos = FALSE;
1595
1596     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1597       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1598   }
1599   segment->position = desired_offset;
1600   segment->time = desired_offset;
1601   if (segment->rate >= 0) {
1602     segment->start = desired_offset;
1603
1604     /* we stop at the end */
1605     if (segment->stop == -1)
1606       segment->stop = segment->duration;
1607   } else {
1608     segment->stop = desired_offset;
1609   }
1610
1611   if (qtdemux->fragmented)
1612     qtdemux->fragmented_seek_pending = TRUE;
1613
1614   return TRUE;
1615 }
1616
1617 /* do a seek in pull based mode */
1618 static gboolean
1619 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1620 {
1621   gdouble rate;
1622   GstFormat format;
1623   GstSeekFlags flags;
1624   GstSeekType cur_type, stop_type;
1625   gint64 cur, stop;
1626   gboolean flush;
1627   gboolean update;
1628   GstSegment seeksegment;
1629   guint32 seqnum = 0;
1630   GstEvent *flush_event;
1631   gboolean ret;
1632
1633   if (event) {
1634     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1635
1636     gst_event_parse_seek (event, &rate, &format, &flags,
1637         &cur_type, &cur, &stop_type, &stop);
1638     seqnum = gst_event_get_seqnum (event);
1639
1640     /* we have to have a format as the segment format. Try to convert
1641      * if not. */
1642     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1643             stop_type, &stop))
1644       goto no_format;
1645
1646     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1647   } else {
1648     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1649     flags = 0;
1650   }
1651
1652   flush = flags & GST_SEEK_FLAG_FLUSH;
1653
1654   /* stop streaming, either by flushing or by pausing the task */
1655   if (flush) {
1656     flush_event = gst_event_new_flush_start ();
1657     if (seqnum)
1658       gst_event_set_seqnum (flush_event, seqnum);
1659     /* unlock upstream pull_range */
1660     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1661     /* make sure out loop function exits */
1662     gst_qtdemux_push_event (qtdemux, flush_event);
1663   } else {
1664     /* non flushing seek, pause the task */
1665     gst_pad_pause_task (qtdemux->sinkpad);
1666   }
1667
1668   /* wait for streaming to finish */
1669   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1670
1671   /* copy segment, we need this because we still need the old
1672    * segment when we close the current segment. */
1673   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1674
1675   if (event) {
1676     /* configure the segment with the seek variables */
1677     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1678     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1679             cur_type, cur, stop_type, stop, &update)) {
1680       ret = FALSE;
1681       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1682     } else {
1683       /* now do the seek */
1684       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1685     }
1686   } else {
1687     /* now do the seek */
1688     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1689   }
1690
1691   /* prepare for streaming again */
1692   if (flush) {
1693     flush_event = gst_event_new_flush_stop (TRUE);
1694     if (seqnum)
1695       gst_event_set_seqnum (flush_event, seqnum);
1696
1697     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1698     gst_qtdemux_push_event (qtdemux, flush_event);
1699   }
1700
1701   /* commit the new segment */
1702   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1703
1704   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1705     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1706         qtdemux->segment.format, qtdemux->segment.position);
1707     if (seqnum)
1708       gst_message_set_seqnum (msg, seqnum);
1709     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1710   }
1711
1712   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1713   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1714       qtdemux->sinkpad, NULL);
1715
1716   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1717
1718   return ret;
1719
1720   /* ERRORS */
1721 no_format:
1722   {
1723     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1724     return FALSE;
1725   }
1726 }
1727
1728 static gboolean
1729 qtdemux_ensure_index (GstQTDemux * qtdemux)
1730 {
1731   guint i;
1732
1733   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1734
1735   /* Build complete index */
1736   for (i = 0; i < qtdemux->n_streams; i++) {
1737     QtDemuxStream *stream = qtdemux->streams[i];
1738
1739     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1740       goto parse_error;
1741   }
1742   return TRUE;
1743
1744   /* ERRORS */
1745 parse_error:
1746   {
1747     GST_LOG_OBJECT (qtdemux,
1748         "Building complete index of stream %u for seeking failed!", i);
1749     return FALSE;
1750   }
1751 }
1752
1753 static gboolean
1754 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1755     GstEvent * event)
1756 {
1757   gboolean res = TRUE;
1758   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1759
1760   switch (GST_EVENT_TYPE (event)) {
1761     case GST_EVENT_SEEK:
1762     {
1763 #ifndef GST_DISABLE_GST_DEBUG
1764       GstClockTime ts = gst_util_get_timestamp ();
1765 #endif
1766       guint32 seqnum = gst_event_get_seqnum (event);
1767
1768       if (seqnum == qtdemux->segment_seqnum) {
1769         GST_LOG_OBJECT (pad,
1770             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1771         gst_event_unref (event);
1772         return TRUE;
1773       }
1774
1775       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1776         /* seek should be handled by upstream, we might need to re-download fragments */
1777         GST_DEBUG_OBJECT (qtdemux,
1778             "let upstream handle seek for fragmented playback");
1779         goto upstream;
1780       }
1781
1782       /* Build complete index for seeking;
1783        * if not a fragmented file at least */
1784       if (!qtdemux->fragmented)
1785         if (!qtdemux_ensure_index (qtdemux))
1786           goto index_failed;
1787 #ifndef GST_DISABLE_GST_DEBUG
1788       ts = gst_util_get_timestamp () - ts;
1789       GST_INFO_OBJECT (qtdemux,
1790           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1791 #endif
1792     }
1793       if (qtdemux->pullbased) {
1794         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1795       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1796         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1797         res = TRUE;
1798       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1799           && !qtdemux->fragmented) {
1800         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1801       } else {
1802         GST_DEBUG_OBJECT (qtdemux,
1803             "ignoring seek in push mode in current state");
1804         res = FALSE;
1805       }
1806       gst_event_unref (event);
1807       break;
1808     default:
1809     upstream:
1810       res = gst_pad_event_default (pad, parent, event);
1811       break;
1812   }
1813
1814 done:
1815   return res;
1816
1817   /* ERRORS */
1818 index_failed:
1819   {
1820     GST_ERROR_OBJECT (qtdemux, "Index failed");
1821     gst_event_unref (event);
1822     res = FALSE;
1823     goto done;
1824   }
1825 }
1826
1827 /* stream/index return sample that is min/max w.r.t. byte position,
1828  * time is min/max w.r.t. time of samples,
1829  * the latter need not be time of the former sample */
1830 static void
1831 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1832     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1833 {
1834   gint i, n, index;
1835   gint64 time, min_time;
1836   QtDemuxStream *stream;
1837
1838   min_time = -1;
1839   stream = NULL;
1840   index = -1;
1841
1842   for (n = 0; n < qtdemux->n_streams; ++n) {
1843     QtDemuxStream *str;
1844     gint inc;
1845     gboolean set_sample;
1846
1847     str = qtdemux->streams[n];
1848     set_sample = !set;
1849
1850     if (fw) {
1851       i = 0;
1852       inc = 1;
1853     } else {
1854       i = str->n_samples - 1;
1855       inc = -1;
1856     }
1857
1858     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1859       if (str->samples[i].size == 0)
1860         continue;
1861
1862       if (fw && (str->samples[i].offset < byte_pos))
1863         continue;
1864
1865       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1866         continue;
1867
1868       /* move stream to first available sample */
1869       if (set) {
1870         gst_qtdemux_move_stream (qtdemux, str, i);
1871         set_sample = TRUE;
1872       }
1873
1874       /* avoid index from sparse streams since they might be far away */
1875       if (!CUR_STREAM (str)->sparse) {
1876         /* determine min/max time */
1877         time = QTSAMPLE_PTS (str, &str->samples[i]);
1878         if (min_time == -1 || (!fw && time > min_time) ||
1879             (fw && time < min_time)) {
1880           min_time = time;
1881         }
1882
1883         /* determine stream with leading sample, to get its position */
1884         if (!stream ||
1885             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1886             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1887           stream = str;
1888           index = i;
1889         }
1890       }
1891       break;
1892     }
1893
1894     /* no sample for this stream, mark eos */
1895     if (!set_sample)
1896       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1897   }
1898
1899   if (_time)
1900     *_time = min_time;
1901   if (_stream)
1902     *_stream = stream;
1903   if (_index)
1904     *_index = index;
1905 }
1906
1907 static QtDemuxStream *
1908 _create_stream (void)
1909 {
1910   QtDemuxStream *stream;
1911
1912   stream = g_new0 (QtDemuxStream, 1);
1913   /* new streams always need a discont */
1914   stream->discont = TRUE;
1915   /* we enable clipping for raw audio/video streams */
1916   stream->need_clip = FALSE;
1917   stream->need_process = FALSE;
1918   stream->segment_index = -1;
1919   stream->time_position = 0;
1920   stream->sample_index = -1;
1921   stream->offset_in_sample = 0;
1922   stream->new_stream = TRUE;
1923   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1924   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1925   stream->protected = FALSE;
1926   stream->protection_scheme_type = 0;
1927   stream->protection_scheme_version = 0;
1928   stream->protection_scheme_info = NULL;
1929   stream->n_samples_moof = 0;
1930   stream->duration_moof = 0;
1931   stream->duration_last_moof = 0;
1932   stream->alignment = 1;
1933   stream->stream_tags = gst_tag_list_new_empty ();
1934   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1935   g_queue_init (&stream->protection_scheme_event_queue);
1936   return stream;
1937 }
1938
1939 static gboolean
1940 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1941 {
1942   GstStructure *structure;
1943   const gchar *variant;
1944   const GstCaps *mediacaps = NULL;
1945
1946   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1947
1948   structure = gst_caps_get_structure (caps, 0);
1949   variant = gst_structure_get_string (structure, "variant");
1950
1951   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1952     QtDemuxStream *stream;
1953     const GValue *value;
1954
1955     demux->fragmented = TRUE;
1956     demux->mss_mode = TRUE;
1957
1958     if (demux->n_streams > 1) {
1959       /* can't do this, we can only renegotiate for another mss format */
1960       return FALSE;
1961     }
1962
1963     value = gst_structure_get_value (structure, "media-caps");
1964     /* create stream */
1965     if (value) {
1966       const GValue *timescale_v;
1967
1968       /* TODO update when stream changes during playback */
1969
1970       if (demux->n_streams == 0) {
1971         stream = _create_stream ();
1972         demux->streams[demux->n_streams] = stream;
1973         demux->n_streams = 1;
1974       } else {
1975         stream = demux->streams[0];
1976       }
1977
1978       timescale_v = gst_structure_get_value (structure, "timescale");
1979       if (timescale_v) {
1980         stream->timescale = g_value_get_uint64 (timescale_v);
1981       } else {
1982         /* default mss timescale */
1983         stream->timescale = 10000000;
1984       }
1985       demux->timescale = stream->timescale;
1986
1987       mediacaps = gst_value_get_caps (value);
1988       if (!CUR_STREAM (stream)->caps
1989           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1990         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1991             mediacaps);
1992         stream->new_caps = TRUE;
1993       }
1994       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1995       structure = gst_caps_get_structure (mediacaps, 0);
1996       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1997         stream->subtype = FOURCC_vide;
1998
1999         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2000         gst_structure_get_int (structure, "height",
2001             &CUR_STREAM (stream)->height);
2002         gst_structure_get_fraction (structure, "framerate",
2003             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2004       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2005         gint rate = 0;
2006         stream->subtype = FOURCC_soun;
2007         gst_structure_get_int (structure, "channels",
2008             &CUR_STREAM (stream)->n_channels);
2009         gst_structure_get_int (structure, "rate", &rate);
2010         CUR_STREAM (stream)->rate = rate;
2011       }
2012     }
2013     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2014   } else {
2015     demux->mss_mode = FALSE;
2016   }
2017
2018   return TRUE;
2019 }
2020
2021 static void
2022 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2023 {
2024   gint n;
2025
2026   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2027   gst_pad_stop_task (qtdemux->sinkpad);
2028
2029   if (hard || qtdemux->upstream_format_is_time) {
2030     qtdemux->state = QTDEMUX_STATE_INITIAL;
2031     qtdemux->neededbytes = 16;
2032     qtdemux->todrop = 0;
2033     qtdemux->pullbased = FALSE;
2034     qtdemux->posted_redirect = FALSE;
2035     qtdemux->first_mdat = -1;
2036     qtdemux->header_size = 0;
2037     qtdemux->mdatoffset = -1;
2038     qtdemux->restoredata_offset = -1;
2039     if (qtdemux->mdatbuffer)
2040       gst_buffer_unref (qtdemux->mdatbuffer);
2041     if (qtdemux->restoredata_buffer)
2042       gst_buffer_unref (qtdemux->restoredata_buffer);
2043     qtdemux->mdatbuffer = NULL;
2044     qtdemux->restoredata_buffer = NULL;
2045     qtdemux->mdatleft = 0;
2046     qtdemux->mdatsize = 0;
2047     if (qtdemux->comp_brands)
2048       gst_buffer_unref (qtdemux->comp_brands);
2049     qtdemux->comp_brands = NULL;
2050     qtdemux->last_moov_offset = -1;
2051     if (qtdemux->moov_node_compressed) {
2052       g_node_destroy (qtdemux->moov_node_compressed);
2053       if (qtdemux->moov_node)
2054         g_free (qtdemux->moov_node->data);
2055     }
2056     qtdemux->moov_node_compressed = NULL;
2057     if (qtdemux->moov_node)
2058       g_node_destroy (qtdemux->moov_node);
2059     qtdemux->moov_node = NULL;
2060     if (qtdemux->tag_list)
2061       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2062     qtdemux->tag_list = gst_tag_list_new_empty ();
2063     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2064 #if 0
2065     if (qtdemux->element_index)
2066       gst_object_unref (qtdemux->element_index);
2067     qtdemux->element_index = NULL;
2068 #endif
2069     qtdemux->major_brand = 0;
2070     if (qtdemux->pending_newsegment)
2071       gst_event_unref (qtdemux->pending_newsegment);
2072     qtdemux->pending_newsegment = NULL;
2073     qtdemux->upstream_format_is_time = FALSE;
2074     qtdemux->upstream_seekable = FALSE;
2075     qtdemux->upstream_size = 0;
2076
2077     qtdemux->fragment_start = -1;
2078     qtdemux->fragment_start_offset = -1;
2079     qtdemux->duration = 0;
2080     qtdemux->moof_offset = 0;
2081     qtdemux->chapters_track_id = 0;
2082     qtdemux->have_group_id = FALSE;
2083     qtdemux->group_id = G_MAXUINT;
2084
2085     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2086         NULL);
2087     g_queue_clear (&qtdemux->protection_event_queue);
2088   }
2089   qtdemux->offset = 0;
2090   gst_adapter_clear (qtdemux->adapter);
2091   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2092   qtdemux->segment_seqnum = 0;
2093
2094   if (hard) {
2095     for (n = 0; n < qtdemux->n_streams; n++) {
2096       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2097       qtdemux->streams[n] = NULL;
2098     }
2099     qtdemux->n_streams = 0;
2100     qtdemux->n_video_streams = 0;
2101     qtdemux->n_audio_streams = 0;
2102     qtdemux->n_sub_streams = 0;
2103     qtdemux->exposed = FALSE;
2104     qtdemux->fragmented = FALSE;
2105     qtdemux->mss_mode = FALSE;
2106     gst_caps_replace (&qtdemux->media_caps, NULL);
2107     qtdemux->timescale = 0;
2108     qtdemux->got_moov = FALSE;
2109     if (qtdemux->protection_system_ids) {
2110       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2111       qtdemux->protection_system_ids = NULL;
2112     }
2113   } else if (qtdemux->mss_mode) {
2114     gst_flow_combiner_reset (qtdemux->flowcombiner);
2115     for (n = 0; n < qtdemux->n_streams; n++)
2116       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2117   } else {
2118     gst_flow_combiner_reset (qtdemux->flowcombiner);
2119     for (n = 0; n < qtdemux->n_streams; n++) {
2120       qtdemux->streams[n]->sent_eos = FALSE;
2121       qtdemux->streams[n]->time_position = 0;
2122       qtdemux->streams[n]->accumulated_base = 0;
2123     }
2124     if (!qtdemux->pending_newsegment) {
2125       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2126       if (qtdemux->segment_seqnum)
2127         gst_event_set_seqnum (qtdemux->pending_newsegment,
2128             qtdemux->segment_seqnum);
2129     }
2130   }
2131 }
2132
2133
2134 /* Maps the @segment to the qt edts internal segments and pushes
2135  * the correspnding segment event.
2136  *
2137  * If it ends up being at a empty segment, a gap will be pushed and the next
2138  * edts segment will be activated in sequence.
2139  *
2140  * To be used in push-mode only */
2141 static void
2142 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2143 {
2144   gint n, i;
2145
2146   for (n = 0; n < qtdemux->n_streams; n++) {
2147     QtDemuxStream *stream = qtdemux->streams[n];
2148
2149     stream->time_position = segment->start;
2150
2151     /* in push mode we should be guaranteed that we will have empty segments
2152      * at the beginning and then one segment after, other scenarios are not
2153      * supported and are discarded when parsing the edts */
2154     for (i = 0; i < stream->n_segments; i++) {
2155       if (stream->segments[i].stop_time > segment->start) {
2156         gst_qtdemux_activate_segment (qtdemux, stream, i,
2157             stream->time_position);
2158         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2159           /* push the empty segment and move to the next one */
2160           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2161               stream->time_position);
2162           continue;
2163         }
2164
2165         g_assert (i == stream->n_segments - 1);
2166       }
2167     }
2168   }
2169 }
2170
2171 static gboolean
2172 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2173     GstEvent * event)
2174 {
2175   GstQTDemux *demux = GST_QTDEMUX (parent);
2176   gboolean res = TRUE;
2177
2178   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2179
2180   switch (GST_EVENT_TYPE (event)) {
2181     case GST_EVENT_SEGMENT:
2182     {
2183       gint64 offset = 0;
2184       QtDemuxStream *stream;
2185       gint idx;
2186       GstSegment segment;
2187
2188       /* some debug output */
2189       gst_event_copy_segment (event, &segment);
2190       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2191           &segment);
2192
2193       /* erase any previously set segment */
2194       gst_event_replace (&demux->pending_newsegment, NULL);
2195
2196       if (segment.format == GST_FORMAT_TIME) {
2197         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2198         gst_event_replace (&demux->pending_newsegment, event);
2199         demux->upstream_format_is_time = TRUE;
2200       } else {
2201         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2202             "not in time format");
2203
2204         /* chain will send initial newsegment after pads have been added */
2205         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2206           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2207           goto exit;
2208         }
2209       }
2210
2211       /* check if this matches a time seek we received previously
2212        * FIXME for backwards compatibility reasons we use the
2213        * seek_offset here to compare. In the future we might want to
2214        * change this to use the seqnum as it uniquely should identify
2215        * the segment that corresponds to the seek. */
2216       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2217           ", received segment offset %" G_GINT64_FORMAT,
2218           demux->seek_offset, segment.start);
2219       if (segment.format == GST_FORMAT_BYTES
2220           && demux->seek_offset == segment.start) {
2221         GST_OBJECT_LOCK (demux);
2222         offset = segment.start;
2223
2224         segment.format = GST_FORMAT_TIME;
2225         segment.start = demux->push_seek_start;
2226         segment.stop = demux->push_seek_stop;
2227         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2228             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2229             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2230         GST_OBJECT_UNLOCK (demux);
2231       }
2232
2233       /* we only expect a BYTE segment, e.g. following a seek */
2234       if (segment.format == GST_FORMAT_BYTES) {
2235         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2236           offset = segment.start;
2237
2238           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2239               NULL, (gint64 *) & segment.start);
2240           if ((gint64) segment.start < 0)
2241             segment.start = 0;
2242         }
2243         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2244           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2245               NULL, (gint64 *) & segment.stop);
2246           /* keyframe seeking should already arrange for start >= stop,
2247            * but make sure in other rare cases */
2248           segment.stop = MAX (segment.stop, segment.start);
2249         }
2250       } else if (segment.format == GST_FORMAT_TIME) {
2251         /* push all data on the adapter before starting this
2252          * new segment */
2253         gst_qtdemux_process_adapter (demux, TRUE);
2254       } else {
2255         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2256         goto exit;
2257       }
2258
2259       /* We shouldn't modify upstream driven TIME FORMAT segment */
2260       if (!demux->upstream_format_is_time) {
2261         /* accept upstream's notion of segment and distribute along */
2262         segment.format = GST_FORMAT_TIME;
2263         segment.position = segment.time = segment.start;
2264         segment.duration = demux->segment.duration;
2265         segment.base = gst_segment_to_running_time (&demux->segment,
2266             GST_FORMAT_TIME, demux->segment.position);
2267       }
2268
2269       gst_segment_copy_into (&segment, &demux->segment);
2270       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2271
2272       /* map segment to internal qt segments and push on each stream */
2273       if (demux->n_streams) {
2274         if (demux->fragmented) {
2275           GstEvent *segment_event = gst_event_new_segment (&segment);
2276
2277           gst_event_replace (&demux->pending_newsegment, NULL);
2278           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2279           gst_qtdemux_push_event (demux, segment_event);
2280         } else {
2281           gst_event_replace (&demux->pending_newsegment, NULL);
2282           gst_qtdemux_map_and_push_segments (demux, &segment);
2283         }
2284       }
2285
2286       /* clear leftover in current segment, if any */
2287       gst_adapter_clear (demux->adapter);
2288
2289       /* set up streaming thread */
2290       demux->offset = offset;
2291       if (demux->upstream_format_is_time) {
2292         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2293             "set values to restart reading from a new atom");
2294         demux->neededbytes = 16;
2295         demux->todrop = 0;
2296       } else {
2297         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2298             NULL);
2299         if (stream) {
2300           demux->todrop = stream->samples[idx].offset - offset;
2301           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2302         } else {
2303           /* set up for EOS */
2304           demux->neededbytes = -1;
2305           demux->todrop = 0;
2306         }
2307       }
2308     exit:
2309       gst_event_unref (event);
2310       res = TRUE;
2311       goto drop;
2312     }
2313     case GST_EVENT_FLUSH_START:
2314     {
2315       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2316         gst_event_unref (event);
2317         goto drop;
2318       }
2319       break;
2320     }
2321     case GST_EVENT_FLUSH_STOP:
2322     {
2323       guint64 dur;
2324
2325       dur = demux->segment.duration;
2326       gst_qtdemux_reset (demux, FALSE);
2327       demux->segment.duration = dur;
2328
2329       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2330         gst_event_unref (event);
2331         goto drop;
2332       }
2333       break;
2334     }
2335     case GST_EVENT_EOS:
2336       /* If we are in push mode, and get an EOS before we've seen any streams,
2337        * then error out - we have nowhere to send the EOS */
2338       if (!demux->pullbased) {
2339         gint i;
2340         gboolean has_valid_stream = FALSE;
2341         for (i = 0; i < demux->n_streams; i++) {
2342           if (demux->streams[i]->pad != NULL) {
2343             has_valid_stream = TRUE;
2344             break;
2345           }
2346         }
2347         if (!has_valid_stream)
2348           gst_qtdemux_post_no_playable_stream_error (demux);
2349         else {
2350           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2351               (guint) gst_adapter_available (demux->adapter));
2352           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2353             res = FALSE;
2354           }
2355         }
2356       }
2357       break;
2358     case GST_EVENT_CAPS:{
2359       GstCaps *caps = NULL;
2360
2361       gst_event_parse_caps (event, &caps);
2362       gst_qtdemux_setcaps (demux, caps);
2363       res = TRUE;
2364       gst_event_unref (event);
2365       goto drop;
2366     }
2367     case GST_EVENT_PROTECTION:
2368     {
2369       const gchar *system_id = NULL;
2370
2371       gst_event_parse_protection (event, &system_id, NULL, NULL);
2372       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2373           system_id);
2374       gst_qtdemux_append_protection_system_id (demux, system_id);
2375       /* save the event for later, for source pads that have not been created */
2376       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2377       /* send it to all pads that already exist */
2378       gst_qtdemux_push_event (demux, event);
2379       res = TRUE;
2380       goto drop;
2381     }
2382     default:
2383       break;
2384   }
2385
2386   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2387
2388 drop:
2389   return res;
2390 }
2391
2392 #if 0
2393 static void
2394 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2395 {
2396   GstQTDemux *demux = GST_QTDEMUX (element);
2397
2398   GST_OBJECT_LOCK (demux);
2399   if (demux->element_index)
2400     gst_object_unref (demux->element_index);
2401   if (index) {
2402     demux->element_index = gst_object_ref (index);
2403   } else {
2404     demux->element_index = NULL;
2405   }
2406   GST_OBJECT_UNLOCK (demux);
2407   /* object lock might be taken again */
2408   if (index)
2409     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2410   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2411       demux->element_index, demux->index_id);
2412 }
2413
2414 static GstIndex *
2415 gst_qtdemux_get_index (GstElement * element)
2416 {
2417   GstIndex *result = NULL;
2418   GstQTDemux *demux = GST_QTDEMUX (element);
2419
2420   GST_OBJECT_LOCK (demux);
2421   if (demux->element_index)
2422     result = gst_object_ref (demux->element_index);
2423   GST_OBJECT_UNLOCK (demux);
2424
2425   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2426
2427   return result;
2428 }
2429 #endif
2430
2431 static void
2432 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2433 {
2434   g_free ((gpointer) stream->stco.data);
2435   stream->stco.data = NULL;
2436   g_free ((gpointer) stream->stsz.data);
2437   stream->stsz.data = NULL;
2438   g_free ((gpointer) stream->stsc.data);
2439   stream->stsc.data = NULL;
2440   g_free ((gpointer) stream->stts.data);
2441   stream->stts.data = NULL;
2442   g_free ((gpointer) stream->stss.data);
2443   stream->stss.data = NULL;
2444   g_free ((gpointer) stream->stps.data);
2445   stream->stps.data = NULL;
2446   g_free ((gpointer) stream->ctts.data);
2447   stream->ctts.data = NULL;
2448 }
2449
2450 static void
2451 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2452     QtDemuxStream * stream)
2453 {
2454   g_free (stream->segments);
2455   stream->segments = NULL;
2456   stream->segment_index = -1;
2457   stream->accumulated_base = 0;
2458 }
2459
2460 static void
2461 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2462     QtDemuxStream * stream)
2463 {
2464   g_free (stream->samples);
2465   stream->samples = NULL;
2466   gst_qtdemux_stbl_free (stream);
2467
2468   /* fragments */
2469   g_free (stream->ra_entries);
2470   stream->ra_entries = NULL;
2471   stream->n_ra_entries = 0;
2472
2473   stream->sample_index = -1;
2474   stream->stbl_index = -1;
2475   stream->n_samples = 0;
2476   stream->time_position = 0;
2477
2478   stream->n_samples_moof = 0;
2479   stream->duration_moof = 0;
2480   stream->duration_last_moof = 0;
2481 }
2482
2483 static void
2484 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2485 {
2486   gint i;
2487   if (stream->allocator)
2488     gst_object_unref (stream->allocator);
2489   while (stream->buffers) {
2490     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2491     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2492   }
2493   for (i = 0; i < stream->stsd_entries_length; i++) {
2494     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2495     if (entry->rgb8_palette) {
2496       gst_memory_unref (entry->rgb8_palette);
2497       entry->rgb8_palette = NULL;
2498     }
2499     entry->sparse = FALSE;
2500   }
2501
2502   gst_tag_list_unref (stream->stream_tags);
2503   stream->stream_tags = gst_tag_list_new_empty ();
2504   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2505   g_free (stream->redirect_uri);
2506   stream->redirect_uri = NULL;
2507   stream->sent_eos = FALSE;
2508   stream->protected = FALSE;
2509   if (stream->protection_scheme_info) {
2510     if (stream->protection_scheme_type == FOURCC_cenc) {
2511       QtDemuxCencSampleSetInfo *info =
2512           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2513       if (info->default_properties)
2514         gst_structure_free (info->default_properties);
2515       if (info->crypto_info)
2516         g_ptr_array_free (info->crypto_info, TRUE);
2517     }
2518     g_free (stream->protection_scheme_info);
2519     stream->protection_scheme_info = NULL;
2520   }
2521   stream->protection_scheme_type = 0;
2522   stream->protection_scheme_version = 0;
2523   g_queue_foreach (&stream->protection_scheme_event_queue,
2524       (GFunc) gst_event_unref, NULL);
2525   g_queue_clear (&stream->protection_scheme_event_queue);
2526   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2527   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2528 }
2529
2530 static void
2531 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2532 {
2533   gint i;
2534   gst_qtdemux_stream_clear (qtdemux, stream);
2535   for (i = 0; i < stream->stsd_entries_length; i++) {
2536     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2537     if (entry->caps) {
2538       gst_caps_unref (entry->caps);
2539       entry->caps = NULL;
2540     }
2541   }
2542   gst_tag_list_unref (stream->stream_tags);
2543   if (stream->pad) {
2544     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2545     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2546   }
2547   g_free (stream->stsd_entries);
2548   g_free (stream);
2549 }
2550
2551 static void
2552 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2553 {
2554   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2555
2556   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2557   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2558   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2559   qtdemux->n_streams--;
2560 }
2561
2562 static GstStateChangeReturn
2563 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2564 {
2565   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2566   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2567
2568   switch (transition) {
2569     case GST_STATE_CHANGE_PAUSED_TO_READY:
2570       break;
2571     default:
2572       break;
2573   }
2574
2575   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2576
2577   switch (transition) {
2578     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2579       gst_qtdemux_reset (qtdemux, TRUE);
2580       break;
2581     }
2582     default:
2583       break;
2584   }
2585
2586   return result;
2587 }
2588
2589 static void
2590 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2591 {
2592   /* counts as header data */
2593   qtdemux->header_size += length;
2594
2595   /* only consider at least a sufficiently complete ftyp atom */
2596   if (length >= 20) {
2597     GstBuffer *buf;
2598
2599     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2600     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2601         GST_FOURCC_ARGS (qtdemux->major_brand));
2602     if (qtdemux->comp_brands)
2603       gst_buffer_unref (qtdemux->comp_brands);
2604     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2605     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2606   }
2607 }
2608
2609 static void
2610 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2611     GstTagList * xmptaglist)
2612 {
2613   /* Strip out bogus fields */
2614   if (xmptaglist) {
2615     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2616       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2617       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2618     } else {
2619       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2620     }
2621
2622     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2623
2624     /* prioritize native tags using _KEEP mode */
2625     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2626     gst_tag_list_unref (xmptaglist);
2627   }
2628 }
2629
2630 static void
2631 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2632     guint offset)
2633 {
2634   GstByteReader br;
2635   guint8 version;
2636   guint32 flags = 0;
2637   guint i;
2638   guint8 iv_size = 8;
2639   QtDemuxStream *stream;
2640   GstStructure *structure;
2641   QtDemuxCencSampleSetInfo *ss_info = NULL;
2642   const gchar *system_id;
2643   gboolean uses_sub_sample_encryption = FALSE;
2644
2645   if (qtdemux->n_streams == 0)
2646     return;
2647
2648   stream = qtdemux->streams[0];
2649
2650   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2651   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2652     GST_WARNING_OBJECT (qtdemux,
2653         "Attempting PIFF box parsing on an unencrypted stream.");
2654     return;
2655   }
2656
2657   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2658       G_TYPE_STRING, &system_id, NULL);
2659   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2660
2661   stream->protected = TRUE;
2662   stream->protection_scheme_type = FOURCC_cenc;
2663
2664   if (!stream->protection_scheme_info)
2665     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2666
2667   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2668
2669   if (ss_info->default_properties)
2670     gst_structure_free (ss_info->default_properties);
2671
2672   ss_info->default_properties =
2673       gst_structure_new ("application/x-cenc",
2674       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2675
2676   if (ss_info->crypto_info) {
2677     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2678     g_ptr_array_free (ss_info->crypto_info, TRUE);
2679     ss_info->crypto_info = NULL;
2680   }
2681
2682   /* skip UUID */
2683   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2684
2685   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2686     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2687     return;
2688   }
2689
2690   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2691     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2692     return;
2693   }
2694
2695   if ((flags & 0x000001)) {
2696     guint32 algorithm_id = 0;
2697     const guint8 *kid;
2698     GstBuffer *kid_buf;
2699     gboolean is_encrypted = TRUE;
2700
2701     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2702       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2703       return;
2704     }
2705
2706     algorithm_id >>= 8;
2707     if (algorithm_id == 0) {
2708       is_encrypted = FALSE;
2709     } else if (algorithm_id == 1) {
2710       /* FIXME: maybe store this in properties? */
2711       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2712     } else if (algorithm_id == 2) {
2713       /* FIXME: maybe store this in properties? */
2714       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2715     }
2716
2717     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2718       return;
2719
2720     if (!gst_byte_reader_get_data (&br, 16, &kid))
2721       return;
2722
2723     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2724     gst_buffer_fill (kid_buf, 0, kid, 16);
2725     if (ss_info->default_properties)
2726       gst_structure_free (ss_info->default_properties);
2727     ss_info->default_properties =
2728         gst_structure_new ("application/x-cenc",
2729         "iv_size", G_TYPE_UINT, iv_size,
2730         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2731         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2732     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2733         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2734     gst_buffer_unref (kid_buf);
2735   } else if ((flags & 0x000002)) {
2736     uses_sub_sample_encryption = TRUE;
2737   }
2738
2739   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2740     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2741     return;
2742   }
2743
2744   ss_info->crypto_info =
2745       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2746       (GDestroyNotify) qtdemux_gst_structure_free);
2747
2748   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2749     GstStructure *properties;
2750     guint8 *data;
2751     GstBuffer *buf;
2752
2753     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2754     if (properties == NULL) {
2755       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2756       return;
2757     }
2758
2759     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2760       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2761       gst_structure_free (properties);
2762       return;
2763     }
2764     buf = gst_buffer_new_wrapped (data, iv_size);
2765     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2766     gst_buffer_unref (buf);
2767
2768     if (uses_sub_sample_encryption) {
2769       guint16 n_subsamples;
2770
2771       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2772           || n_subsamples == 0) {
2773         GST_ERROR_OBJECT (qtdemux,
2774             "failed to get subsample count for sample %u", i);
2775         gst_structure_free (properties);
2776         return;
2777       }
2778       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2779       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2780         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2781             i);
2782         gst_structure_free (properties);
2783         return;
2784       }
2785       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2786       gst_structure_set (properties,
2787           "subsample_count", G_TYPE_UINT, n_subsamples,
2788           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2789       gst_buffer_unref (buf);
2790     } else {
2791       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2792     }
2793
2794     g_ptr_array_add (ss_info->crypto_info, properties);
2795   }
2796 }
2797
2798 static void
2799 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2800 {
2801   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2802     0x97, 0xA9, 0x42, 0xE8,
2803     0x9C, 0x71, 0x99, 0x94,
2804     0x91, 0xE3, 0xAF, 0xAC
2805   };
2806   static const guint8 playready_uuid[] = {
2807     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2808     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2809   };
2810
2811   static const guint8 piff_sample_encryption_uuid[] = {
2812     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2813     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2814   };
2815
2816   guint offset;
2817
2818   /* counts as header data */
2819   qtdemux->header_size += length;
2820
2821   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2822
2823   if (length <= offset + 16) {
2824     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2825     return;
2826   }
2827
2828   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2829     GstBuffer *buf;
2830     GstTagList *taglist;
2831
2832     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2833         length - offset - 16, NULL);
2834     taglist = gst_tag_list_from_xmp_buffer (buf);
2835     gst_buffer_unref (buf);
2836
2837     /* make sure we have a usable taglist */
2838     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2839
2840     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2841
2842   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2843     int len;
2844     const gunichar2 *s_utf16;
2845     char *contents;
2846
2847     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2848     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2849     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2850     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2851
2852     g_free (contents);
2853
2854     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2855         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2856         (NULL));
2857   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2858     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2859   } else {
2860     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2861         GST_READ_UINT32_LE (buffer + offset),
2862         GST_READ_UINT32_LE (buffer + offset + 4),
2863         GST_READ_UINT32_LE (buffer + offset + 8),
2864         GST_READ_UINT32_LE (buffer + offset + 12));
2865   }
2866 }
2867
2868 static void
2869 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2870 {
2871   GstSidxParser sidx_parser;
2872   GstIsoffParserResult res;
2873   guint consumed;
2874
2875   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2876
2877   res =
2878       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2879       &consumed);
2880   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2881   if (res == GST_ISOFF_QT_PARSER_DONE) {
2882     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2883   }
2884   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2885 }
2886
2887 /* caller verifies at least 8 bytes in buf */
2888 static void
2889 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2890     guint64 * plength, guint32 * pfourcc)
2891 {
2892   guint64 length;
2893   guint32 fourcc;
2894
2895   length = QT_UINT32 (data);
2896   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2897   fourcc = QT_FOURCC (data + 4);
2898   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2899
2900   if (length == 0) {
2901     length = G_MAXUINT64;
2902   } else if (length == 1 && size >= 16) {
2903     /* this means we have an extended size, which is the 64 bit value of
2904      * the next 8 bytes */
2905     length = QT_UINT64 (data + 8);
2906     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2907   }
2908
2909   if (plength)
2910     *plength = length;
2911   if (pfourcc)
2912     *pfourcc = fourcc;
2913 }
2914
2915 static gboolean
2916 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2917 {
2918   guint32 version = 0;
2919   GstClockTime duration = 0;
2920
2921   if (!gst_byte_reader_get_uint32_be (br, &version))
2922     goto failed;
2923
2924   version >>= 24;
2925   if (version == 1) {
2926     if (!gst_byte_reader_get_uint64_be (br, &duration))
2927       goto failed;
2928   } else {
2929     guint32 dur = 0;
2930
2931     if (!gst_byte_reader_get_uint32_be (br, &dur))
2932       goto failed;
2933     duration = dur;
2934   }
2935
2936   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2937   qtdemux->duration = duration;
2938
2939   return TRUE;
2940
2941 failed:
2942   {
2943     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2944     return FALSE;
2945   }
2946 }
2947
2948 static gboolean
2949 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2950     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2951 {
2952   if (!stream->parsed_trex && qtdemux->moov_node) {
2953     GNode *mvex, *trex;
2954     GstByteReader trex_data;
2955
2956     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2957     if (mvex) {
2958       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2959           &trex_data);
2960       while (trex) {
2961         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
2962
2963         /* skip version/flags */
2964         if (!gst_byte_reader_skip (&trex_data, 4))
2965           goto next;
2966         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2967           goto next;
2968         if (id != stream->track_id)
2969           goto next;
2970         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
2971           goto next;
2972         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2973           goto next;
2974         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2975           goto next;
2976         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2977           goto next;
2978
2979         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2980             "duration %d,  size %d, flags 0x%x", stream->track_id,
2981             dur, size, flags);
2982
2983         stream->parsed_trex = TRUE;
2984         stream->def_sample_description_index = sdi;
2985         stream->def_sample_duration = dur;
2986         stream->def_sample_size = size;
2987         stream->def_sample_flags = flags;
2988
2989       next:
2990         /* iterate all siblings */
2991         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2992             &trex_data);
2993       }
2994     }
2995   }
2996
2997   *ds_duration = stream->def_sample_duration;
2998   *ds_size = stream->def_sample_size;
2999   *ds_flags = stream->def_sample_flags;
3000
3001   /* even then, above values are better than random ... */
3002   if (G_UNLIKELY (!stream->parsed_trex)) {
3003     GST_WARNING_OBJECT (qtdemux,
3004         "failed to find fragment defaults for stream %d", stream->track_id);
3005     return FALSE;
3006   }
3007
3008   return TRUE;
3009 }
3010
3011 /* This method should be called whenever a more accurate duration might
3012  * have been found. It will update all relevant variables if/where needed
3013  */
3014 static void
3015 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3016 {
3017   guint i;
3018   guint64 movdur;
3019   GstClockTime prevdur;
3020
3021   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3022
3023   if (movdur > qtdemux->duration) {
3024     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3025     GST_DEBUG_OBJECT (qtdemux,
3026         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3027         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3028     qtdemux->duration = movdur;
3029     GST_DEBUG_OBJECT (qtdemux,
3030         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3031         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3032         GST_TIME_ARGS (qtdemux->segment.stop));
3033     if (qtdemux->segment.duration == prevdur) {
3034       /* If the current segment has duration/stop identical to previous duration
3035        * update them also (because they were set at that point in time with
3036        * the wrong duration */
3037       /* We convert the value *from* the timescale version to avoid rounding errors */
3038       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3039       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3040       qtdemux->segment.duration = fixeddur;
3041       qtdemux->segment.stop = fixeddur;
3042     }
3043   }
3044   for (i = 0; i < qtdemux->n_streams; i++) {
3045     QtDemuxStream *stream = qtdemux->streams[i];
3046     if (stream) {
3047       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3048       if (movdur > stream->duration) {
3049         GST_DEBUG_OBJECT (qtdemux,
3050             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3051             GST_TIME_ARGS (duration));
3052         stream->duration = movdur;
3053         if (stream->dummy_segment) {
3054           /* Update all dummy values to new duration */
3055           stream->segments[0].stop_time = duration;
3056           stream->segments[0].duration = duration;
3057           stream->segments[0].media_stop = duration;
3058
3059           /* let downstream know we possibly have a new stop time */
3060           if (stream->segment_index != -1) {
3061             GstClockTime pos;
3062
3063             if (qtdemux->segment.rate >= 0) {
3064               pos = stream->segment.start;
3065             } else {
3066               pos = stream->segment.stop;
3067             }
3068
3069             gst_qtdemux_stream_update_segment (qtdemux, stream,
3070                 stream->segment_index, pos, NULL, NULL);
3071           }
3072         }
3073       }
3074     }
3075   }
3076 }
3077
3078 static gboolean
3079 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3080     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3081     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3082     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3083     gboolean has_tfdt)
3084 {
3085   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3086   guint64 timestamp;
3087   gint32 data_offset = 0;
3088   guint32 flags = 0, first_flags = 0, samples_count = 0;
3089   gint i;
3090   guint8 *data;
3091   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3092   QtDemuxSample *sample;
3093   gboolean ismv = FALSE;
3094   gint64 initial_offset;
3095
3096   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3097       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3098       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3099       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3100
3101   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3102     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3103     return TRUE;
3104   }
3105
3106   /* presence of stss or not can't really tell us much,
3107    * and flags and so on tend to be marginally reliable in these files */
3108   if (stream->subtype == FOURCC_soun) {
3109     GST_DEBUG_OBJECT (qtdemux,
3110         "sound track in fragmented file; marking all keyframes");
3111     stream->all_keyframe = TRUE;
3112   }
3113
3114   if (!gst_byte_reader_skip (trun, 1) ||
3115       !gst_byte_reader_get_uint24_be (trun, &flags))
3116     goto fail;
3117
3118   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3119     goto fail;
3120
3121   if (flags & TR_DATA_OFFSET) {
3122     /* note this is really signed */
3123     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3124       goto fail;
3125     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3126     /* default base offset = first byte of moof */
3127     if (*base_offset == -1) {
3128       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3129       *base_offset = moof_offset;
3130     }
3131     *running_offset = *base_offset + data_offset;
3132   } else {
3133     /* if no offset at all, that would mean data starts at moof start,
3134      * which is a bit wrong and is ismv crappy way, so compensate
3135      * assuming data is in mdat following moof */
3136     if (*base_offset == -1) {
3137       *base_offset = moof_offset + moof_length + 8;
3138       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3139       ismv = TRUE;
3140     }
3141     if (*running_offset == -1)
3142       *running_offset = *base_offset;
3143   }
3144
3145   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3146       *running_offset);
3147   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3148       data_offset, flags, samples_count);
3149
3150   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3151     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3152       GST_DEBUG_OBJECT (qtdemux,
3153           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3154       flags ^= TR_FIRST_SAMPLE_FLAGS;
3155     } else {
3156       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3157         goto fail;
3158       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3159     }
3160   }
3161
3162   /* FIXME ? spec says other bits should also be checked to determine
3163    * entry size (and prefix size for that matter) */
3164   entry_size = 0;
3165   dur_offset = size_offset = 0;
3166   if (flags & TR_SAMPLE_DURATION) {
3167     GST_LOG_OBJECT (qtdemux, "entry duration present");
3168     dur_offset = entry_size;
3169     entry_size += 4;
3170   }
3171   if (flags & TR_SAMPLE_SIZE) {
3172     GST_LOG_OBJECT (qtdemux, "entry size present");
3173     size_offset = entry_size;
3174     entry_size += 4;
3175   }
3176   if (flags & TR_SAMPLE_FLAGS) {
3177     GST_LOG_OBJECT (qtdemux, "entry flags present");
3178     flags_offset = entry_size;
3179     entry_size += 4;
3180   }
3181   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3182     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3183     ct_offset = entry_size;
3184     entry_size += 4;
3185   }
3186
3187   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3188     goto fail;
3189   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3190
3191   if (stream->n_samples + samples_count >=
3192       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3193     goto index_too_big;
3194
3195   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3196       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3197       (stream->n_samples + samples_count) *
3198       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3199
3200   /* create a new array of samples if it's the first sample parsed */
3201   if (stream->n_samples == 0) {
3202     g_assert (stream->samples == NULL);
3203     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3204     /* or try to reallocate it with space enough to insert the new samples */
3205   } else
3206     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3207         stream->n_samples + samples_count);
3208   if (stream->samples == NULL)
3209     goto out_of_memory;
3210
3211   if (qtdemux->fragment_start != -1) {
3212     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3213     qtdemux->fragment_start = -1;
3214   } else {
3215     if (stream->n_samples == 0) {
3216       if (decode_ts > 0) {
3217         timestamp = decode_ts;
3218       } else if (stream->pending_seek != NULL) {
3219         /* if we don't have a timestamp from a tfdt box, we'll use the one
3220          * from the mfra seek table */
3221         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3222             GST_TIME_ARGS (stream->pending_seek->ts));
3223
3224         /* FIXME: this is not fully correct, the timestamp refers to the random
3225          * access sample refered to in the tfra entry, which may not necessarily
3226          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3227         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3228       } else {
3229         timestamp = 0;
3230       }
3231
3232       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3233       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3234           GST_TIME_ARGS (gst_ts));
3235     } else {
3236       /* subsequent fragments extend stream */
3237       timestamp =
3238           stream->samples[stream->n_samples - 1].timestamp +
3239           stream->samples[stream->n_samples - 1].duration;
3240
3241       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3242        * difference (1 sec.) between decode_ts and timestamp, prefer the
3243        * former */
3244       if (has_tfdt && !qtdemux->upstream_format_is_time
3245           && ABSDIFF (decode_ts, timestamp) >
3246           MAX (stream->duration_last_moof / 2,
3247               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3248         GST_INFO_OBJECT (qtdemux,
3249             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3250             ") are significantly different (more than %" GST_TIME_FORMAT
3251             "), using decode_ts",
3252             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3253             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3254             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3255                     MAX (stream->duration_last_moof / 2,
3256                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3257         timestamp = decode_ts;
3258       }
3259
3260       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3261       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3262           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3263     }
3264   }
3265
3266   initial_offset = *running_offset;
3267
3268   sample = stream->samples + stream->n_samples;
3269   for (i = 0; i < samples_count; i++) {
3270     guint32 dur, size, sflags, ct;
3271
3272     /* first read sample data */
3273     if (flags & TR_SAMPLE_DURATION) {
3274       dur = QT_UINT32 (data + dur_offset);
3275     } else {
3276       dur = d_sample_duration;
3277     }
3278     if (flags & TR_SAMPLE_SIZE) {
3279       size = QT_UINT32 (data + size_offset);
3280     } else {
3281       size = d_sample_size;
3282     }
3283     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3284       if (i == 0) {
3285         sflags = first_flags;
3286       } else {
3287         sflags = d_sample_flags;
3288       }
3289     } else if (flags & TR_SAMPLE_FLAGS) {
3290       sflags = QT_UINT32 (data + flags_offset);
3291     } else {
3292       sflags = d_sample_flags;
3293     }
3294     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3295       ct = QT_UINT32 (data + ct_offset);
3296     } else {
3297       ct = 0;
3298     }
3299     data += entry_size;
3300
3301     /* fill the sample information */
3302     sample->offset = *running_offset;
3303     sample->pts_offset = ct;
3304     sample->size = size;
3305     sample->timestamp = timestamp;
3306     sample->duration = dur;
3307     /* sample-is-difference-sample */
3308     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3309      * now idea how it relates to bitfield other than massive LE/BE confusion */
3310     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3311     *running_offset += size;
3312     timestamp += dur;
3313     stream->duration_moof += dur;
3314     sample++;
3315   }
3316
3317   /* Update total duration if needed */
3318   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3319
3320   /* Pre-emptively figure out size of mdat based on trun information.
3321    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3322    * size, else we will still be able to use this when dealing with gap'ed
3323    * input */
3324   qtdemux->mdatleft = *running_offset - initial_offset;
3325   qtdemux->mdatoffset = initial_offset;
3326   qtdemux->mdatsize = qtdemux->mdatleft;
3327
3328   stream->n_samples += samples_count;
3329   stream->n_samples_moof += samples_count;
3330
3331   if (stream->pending_seek != NULL)
3332     stream->pending_seek = NULL;
3333
3334   return TRUE;
3335
3336 fail:
3337   {
3338     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3339     return FALSE;
3340   }
3341 out_of_memory:
3342   {
3343     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3344         stream->n_samples);
3345     return FALSE;
3346   }
3347 index_too_big:
3348   {
3349     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3350         "be larger than %uMB (broken file?)", stream->n_samples,
3351         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3352     return FALSE;
3353   }
3354 }
3355
3356 /* find stream with @id */
3357 static inline QtDemuxStream *
3358 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3359 {
3360   QtDemuxStream *stream;
3361   gint i;
3362
3363   /* check */
3364   if (G_UNLIKELY (!id)) {
3365     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3366     return NULL;
3367   }
3368
3369   /* try to get it fast and simple */
3370   if (G_LIKELY (id <= qtdemux->n_streams)) {
3371     stream = qtdemux->streams[id - 1];
3372     if (G_LIKELY (stream->track_id == id))
3373       return stream;
3374   }
3375
3376   /* linear search otherwise */
3377   for (i = 0; i < qtdemux->n_streams; i++) {
3378     stream = qtdemux->streams[i];
3379     if (stream->track_id == id)
3380       return stream;
3381   }
3382   if (qtdemux->mss_mode) {
3383     /* mss should have only 1 stream anyway */
3384     return qtdemux->streams[0];
3385   }
3386
3387   return NULL;
3388 }
3389
3390 static gboolean
3391 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3392     guint32 * fragment_number)
3393 {
3394   if (!gst_byte_reader_skip (mfhd, 4))
3395     goto fail;
3396   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3397     goto fail;
3398   return TRUE;
3399 fail:
3400   {
3401     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3402     return FALSE;
3403   }
3404 }
3405
3406 static gboolean
3407 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3408     QtDemuxStream ** stream, guint32 * default_sample_duration,
3409     guint32 * default_sample_size, guint32 * default_sample_flags,
3410     gint64 * base_offset)
3411 {
3412   guint32 flags = 0;
3413   guint32 track_id = 0;
3414
3415   if (!gst_byte_reader_skip (tfhd, 1) ||
3416       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3417     goto invalid_track;
3418
3419   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3420     goto invalid_track;
3421
3422   *stream = qtdemux_find_stream (qtdemux, track_id);
3423   if (G_UNLIKELY (!*stream))
3424     goto unknown_stream;
3425
3426   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3427     *base_offset = qtdemux->moof_offset;
3428
3429   if (flags & TF_BASE_DATA_OFFSET)
3430     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3431       goto invalid_track;
3432
3433   /* obtain stream defaults */
3434   qtdemux_parse_trex (qtdemux, *stream,
3435       default_sample_duration, default_sample_size, default_sample_flags);
3436
3437   (*stream)->stsd_sample_description_id =
3438       (*stream)->def_sample_description_index - 1;
3439
3440   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3441     guint32 sample_description_index;
3442     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3443       goto invalid_track;
3444     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3445   }
3446
3447   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3448     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3449       goto invalid_track;
3450
3451   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3452     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3453       goto invalid_track;
3454
3455   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3456     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3457       goto invalid_track;
3458
3459   return TRUE;
3460
3461 invalid_track:
3462   {
3463     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3464     return FALSE;
3465   }
3466 unknown_stream:
3467   {
3468     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3469     return TRUE;
3470   }
3471 }
3472
3473 static gboolean
3474 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3475     guint64 * decode_time)
3476 {
3477   guint32 version = 0;
3478
3479   if (!gst_byte_reader_get_uint32_be (br, &version))
3480     return FALSE;
3481
3482   version >>= 24;
3483   if (version == 1) {
3484     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3485       goto failed;
3486   } else {
3487     guint32 dec_time = 0;
3488     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3489       goto failed;
3490     *decode_time = dec_time;
3491   }
3492
3493   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3494       *decode_time);
3495
3496   return TRUE;
3497
3498 failed:
3499   {
3500     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3501     return FALSE;
3502   }
3503 }
3504
3505 /* Returns a pointer to a GstStructure containing the properties of
3506  * the stream sample identified by @sample_index. The caller must unref
3507  * the returned object after use. Returns NULL if unsuccessful. */
3508 static GstStructure *
3509 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3510     QtDemuxStream * stream, guint sample_index)
3511 {
3512   QtDemuxCencSampleSetInfo *info = NULL;
3513
3514   g_return_val_if_fail (stream != NULL, NULL);
3515   g_return_val_if_fail (stream->protected, NULL);
3516   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3517
3518   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3519
3520   /* Currently, cenc properties for groups of samples are not supported, so
3521    * simply return a copy of the default sample properties */
3522   return gst_structure_copy (info->default_properties);
3523 }
3524
3525 /* Parses the sizes of sample auxiliary information contained within a stream,
3526  * as given in a saiz box. Returns array of sample_count guint8 size values,
3527  * or NULL on failure */
3528 static guint8 *
3529 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3530     GstByteReader * br, guint32 * sample_count)
3531 {
3532   guint32 flags = 0;
3533   guint8 *info_sizes;
3534   guint8 default_info_size;
3535
3536   g_return_val_if_fail (qtdemux != NULL, NULL);
3537   g_return_val_if_fail (stream != NULL, NULL);
3538   g_return_val_if_fail (br != NULL, NULL);
3539   g_return_val_if_fail (sample_count != NULL, NULL);
3540
3541   if (!gst_byte_reader_get_uint32_be (br, &flags))
3542     return NULL;
3543
3544   if (flags & 0x1) {
3545     /* aux_info_type and aux_info_type_parameter are ignored */
3546     if (!gst_byte_reader_skip (br, 8))
3547       return NULL;
3548   }
3549
3550   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3551     return NULL;
3552   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3553
3554   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3555     return NULL;
3556   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3557
3558
3559   if (default_info_size == 0) {
3560     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3561       return NULL;
3562     }
3563   } else {
3564     info_sizes = g_new (guint8, *sample_count);
3565     memset (info_sizes, default_info_size, *sample_count);
3566   }
3567
3568   return info_sizes;
3569 }
3570
3571 /* Parses the offset of sample auxiliary information contained within a stream,
3572  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3573 static gboolean
3574 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3575     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3576     guint64 * offset)
3577 {
3578   guint8 version = 0;
3579   guint32 flags = 0;
3580   guint32 aux_info_type = 0;
3581   guint32 aux_info_type_parameter = 0;
3582   guint32 entry_count;
3583   guint32 off_32;
3584   guint64 off_64;
3585   const guint8 *aux_info_type_data = NULL;
3586
3587   g_return_val_if_fail (qtdemux != NULL, FALSE);
3588   g_return_val_if_fail (stream != NULL, FALSE);
3589   g_return_val_if_fail (br != NULL, FALSE);
3590   g_return_val_if_fail (offset != NULL, FALSE);
3591
3592   if (!gst_byte_reader_get_uint8 (br, &version))
3593     return FALSE;
3594
3595   if (!gst_byte_reader_get_uint24_be (br, &flags))
3596     return FALSE;
3597
3598   if (flags & 0x1) {
3599
3600     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3601       return FALSE;
3602     aux_info_type = QT_FOURCC (aux_info_type_data);
3603
3604     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3605       return FALSE;
3606   } else if (stream->protected) {
3607     aux_info_type = stream->protection_scheme_type;
3608   } else {
3609     aux_info_type = CUR_STREAM (stream)->fourcc;
3610   }
3611
3612   if (info_type)
3613     *info_type = aux_info_type;
3614   if (info_type_parameter)
3615     *info_type_parameter = aux_info_type_parameter;
3616
3617   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3618       "aux_info_type_parameter:  %#06x",
3619       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3620
3621   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3622     return FALSE;
3623
3624   if (entry_count != 1) {
3625     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3626     return FALSE;
3627   }
3628
3629   if (version == 0) {
3630     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3631       return FALSE;
3632     *offset = (guint64) off_32;
3633   } else {
3634     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3635       return FALSE;
3636     *offset = off_64;
3637   }
3638
3639   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3640   return TRUE;
3641 }
3642
3643 static void
3644 qtdemux_gst_structure_free (GstStructure * gststructure)
3645 {
3646   if (gststructure) {
3647     gst_structure_free (gststructure);
3648   }
3649 }
3650
3651 /* Parses auxiliary information relating to samples protected using Common
3652  * Encryption (cenc); the format of this information is defined in
3653  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3654 static gboolean
3655 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3656     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3657 {
3658   QtDemuxCencSampleSetInfo *ss_info = NULL;
3659   guint8 size;
3660   gint i;
3661   GPtrArray *old_crypto_info = NULL;
3662   guint old_entries = 0;
3663
3664   g_return_val_if_fail (qtdemux != NULL, FALSE);
3665   g_return_val_if_fail (stream != NULL, FALSE);
3666   g_return_val_if_fail (br != NULL, FALSE);
3667   g_return_val_if_fail (stream->protected, FALSE);
3668   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3669
3670   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3671
3672   if (ss_info->crypto_info) {
3673     old_crypto_info = ss_info->crypto_info;
3674     /* Count number of non-null entries remaining at the tail end */
3675     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3676       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3677         break;
3678       old_entries++;
3679     }
3680   }
3681
3682   ss_info->crypto_info =
3683       g_ptr_array_new_full (sample_count + old_entries,
3684       (GDestroyNotify) qtdemux_gst_structure_free);
3685
3686   /* We preserve old entries because we parse the next moof in advance
3687    * of consuming all samples from the previous moof, and otherwise
3688    * we'd discard the corresponding crypto info for the samples
3689    * from the previous fragment. */
3690   if (old_entries) {
3691     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3692         old_entries);
3693     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3694       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3695               i));
3696       g_ptr_array_index (old_crypto_info, i) = NULL;
3697     }
3698   }
3699
3700   if (old_crypto_info) {
3701     /* Everything now belongs to the new array */
3702     g_ptr_array_free (old_crypto_info, TRUE);
3703   }
3704
3705   for (i = 0; i < sample_count; ++i) {
3706     GstStructure *properties;
3707     guint16 n_subsamples = 0;
3708     guint8 *data;
3709     guint iv_size;
3710     GstBuffer *buf;
3711
3712     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3713     if (properties == NULL) {
3714       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3715       return FALSE;
3716     }
3717     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3718       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3719       gst_structure_free (properties);
3720       return FALSE;
3721     }
3722     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3723       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3724       gst_structure_free (properties);
3725       return FALSE;
3726     }
3727     buf = gst_buffer_new_wrapped (data, iv_size);
3728     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3729     gst_buffer_unref (buf);
3730     size = info_sizes[i];
3731     if (size > iv_size) {
3732       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3733           || !(n_subsamples > 0)) {
3734         gst_structure_free (properties);
3735         GST_ERROR_OBJECT (qtdemux,
3736             "failed to get subsample count for sample %u", i);
3737         return FALSE;
3738       }
3739       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3740       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3741         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3742             i);
3743         gst_structure_free (properties);
3744         return FALSE;
3745       }
3746       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3747       if (!buf) {
3748         gst_structure_free (properties);
3749         return FALSE;
3750       }
3751       gst_structure_set (properties,
3752           "subsample_count", G_TYPE_UINT, n_subsamples,
3753           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3754       gst_buffer_unref (buf);
3755     } else {
3756       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3757     }
3758     g_ptr_array_add (ss_info->crypto_info, properties);
3759   }
3760   return TRUE;
3761 }
3762
3763 /* Converts a UUID in raw byte form to a string representation, as defined in
3764  * RFC 4122. The caller takes ownership of the returned string and is
3765  * responsible for freeing it after use. */
3766 static gchar *
3767 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3768 {
3769   const guint8 *uuid = (const guint8 *) uuid_bytes;
3770
3771   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3772       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3773       uuid[0], uuid[1], uuid[2], uuid[3],
3774       uuid[4], uuid[5], uuid[6], uuid[7],
3775       uuid[8], uuid[9], uuid[10], uuid[11],
3776       uuid[12], uuid[13], uuid[14], uuid[15]);
3777 }
3778
3779 /* Parses a Protection System Specific Header box (pssh), as defined in the
3780  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3781  * information needed by a specific content protection system in order to
3782  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3783  * otherwise. */
3784 static gboolean
3785 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3786 {
3787   gchar *sysid_string;
3788   guint32 pssh_size = QT_UINT32 (node->data);
3789   GstBuffer *pssh = NULL;
3790   GstEvent *event = NULL;
3791   guint32 parent_box_type;
3792   gint i;
3793
3794   if (G_UNLIKELY (pssh_size < 32U)) {
3795     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3796     return FALSE;
3797   }
3798
3799   sysid_string =
3800       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3801
3802   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3803
3804   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3805   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3806       gst_buffer_get_size (pssh));
3807
3808   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3809
3810   /* Push an event containing the pssh box onto the queues of all streams. */
3811   event = gst_event_new_protection (sysid_string, pssh,
3812       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3813   for (i = 0; i < qtdemux->n_streams; ++i) {
3814     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3815         gst_event_ref (event));
3816   }
3817   g_free (sysid_string);
3818   gst_event_unref (event);
3819   gst_buffer_unref (pssh);
3820   return TRUE;
3821 }
3822
3823 static gboolean
3824 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3825     guint64 moof_offset, QtDemuxStream * stream)
3826 {
3827   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3828   GNode *uuid_node;
3829   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3830   GNode *saiz_node, *saio_node, *pssh_node;
3831   GstByteReader saiz_data, saio_data;
3832   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3833   gint64 base_offset, running_offset;
3834   guint32 frag_num;
3835
3836   /* NOTE @stream ignored */
3837
3838   moof_node = g_node_new ((guint8 *) buffer);
3839   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3840   qtdemux_node_dump (qtdemux, moof_node);
3841
3842   /* Get fragment number from mfhd and check it's valid */
3843   mfhd_node =
3844       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3845   if (mfhd_node == NULL)
3846     goto missing_mfhd;
3847   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3848     goto fail;
3849   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3850
3851   /* unknown base_offset to start with */
3852   base_offset = running_offset = -1;
3853   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3854   while (traf_node) {
3855     guint64 decode_time = 0;
3856
3857     /* Fragment Header node */
3858     tfhd_node =
3859         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3860         &tfhd_data);
3861     if (!tfhd_node)
3862       goto missing_tfhd;
3863     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3864             &ds_size, &ds_flags, &base_offset))
3865       goto missing_tfhd;
3866
3867     /* The following code assumes at most a single set of sample auxiliary
3868      * data in the fragment (consisting of a saiz box and a corresponding saio
3869      * box); in theory, however, there could be multiple sets of sample
3870      * auxiliary data in a fragment. */
3871     saiz_node =
3872         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3873         &saiz_data);
3874     if (saiz_node) {
3875       guint32 info_type = 0;
3876       guint64 offset = 0;
3877       guint32 info_type_parameter = 0;
3878
3879       g_free (qtdemux->cenc_aux_info_sizes);
3880
3881       qtdemux->cenc_aux_info_sizes =
3882           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3883           &qtdemux->cenc_aux_sample_count);
3884       if (qtdemux->cenc_aux_info_sizes == NULL) {
3885         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3886         goto fail;
3887       }
3888       saio_node =
3889           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3890           &saio_data);
3891       if (!saio_node) {
3892         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3893         g_free (qtdemux->cenc_aux_info_sizes);
3894         qtdemux->cenc_aux_info_sizes = NULL;
3895         goto fail;
3896       }
3897
3898       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3899                   &info_type, &info_type_parameter, &offset))) {
3900         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3901         g_free (qtdemux->cenc_aux_info_sizes);
3902         qtdemux->cenc_aux_info_sizes = NULL;
3903         goto fail;
3904       }
3905       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3906         offset += (guint64) (base_offset - qtdemux->moof_offset);
3907       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3908         GstByteReader br;
3909         if (offset > length) {
3910           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3911           qtdemux->cenc_aux_info_offset = offset;
3912         } else {
3913           gst_byte_reader_init (&br, buffer + offset, length - offset);
3914           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3915                   qtdemux->cenc_aux_info_sizes,
3916                   qtdemux->cenc_aux_sample_count)) {
3917             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3918             g_free (qtdemux->cenc_aux_info_sizes);
3919             qtdemux->cenc_aux_info_sizes = NULL;
3920             goto fail;
3921           }
3922         }
3923       }
3924     }
3925
3926     tfdt_node =
3927         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3928         &tfdt_data);
3929     if (tfdt_node) {
3930       /* We'll use decode_time to interpolate timestamps
3931        * in case the input timestamps are missing */
3932       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3933
3934       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3935           " (%" GST_TIME_FORMAT ")", decode_time,
3936           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3937
3938       /* Discard the fragment buffer timestamp info to avoid using it.
3939        * Rely on tfdt instead as it is more accurate than the timestamp
3940        * that is fetched from a manifest/playlist and is usually
3941        * less accurate. */
3942       qtdemux->fragment_start = -1;
3943     }
3944
3945     if (G_UNLIKELY (!stream)) {
3946       /* we lost track of offset, we'll need to regain it,
3947        * but can delay complaining until later or avoid doing so altogether */
3948       base_offset = -2;
3949       goto next;
3950     }
3951     if (G_UNLIKELY (base_offset < -1))
3952       goto lost_offset;
3953
3954     if (qtdemux->upstream_format_is_time)
3955       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3956
3957     /* initialise moof sample data */
3958     stream->n_samples_moof = 0;
3959     stream->duration_last_moof = stream->duration_moof;
3960     stream->duration_moof = 0;
3961
3962     /* Track Run node */
3963     trun_node =
3964         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3965         &trun_data);
3966     while (trun_node) {
3967       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3968           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3969           &running_offset, decode_time, (tfdt_node != NULL));
3970       /* iterate all siblings */
3971       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3972           &trun_data);
3973     }
3974
3975     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3976     if (uuid_node) {
3977       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3978       guint32 box_length = QT_UINT32 (uuid_buffer);
3979
3980       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3981     }
3982
3983     /* if no new base_offset provided for next traf,
3984      * base is end of current traf */
3985     base_offset = running_offset;
3986     running_offset = -1;
3987
3988     if (stream->n_samples_moof && stream->duration_moof)
3989       stream->new_caps = TRUE;
3990
3991   next:
3992     /* iterate all siblings */
3993     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3994   }
3995
3996   /* parse any protection system info */
3997   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3998   while (pssh_node) {
3999     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4000     qtdemux_parse_pssh (qtdemux, pssh_node);
4001     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4002   }
4003
4004   g_node_destroy (moof_node);
4005   return TRUE;
4006
4007 missing_tfhd:
4008   {
4009     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4010     goto fail;
4011   }
4012 missing_mfhd:
4013   {
4014     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4015     goto fail;
4016   }
4017 lost_offset:
4018   {
4019     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4020     goto fail;
4021   }
4022 fail:
4023   {
4024     g_node_destroy (moof_node);
4025     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4026         (_("This file is corrupt and cannot be played.")), (NULL));
4027     return FALSE;
4028   }
4029 }
4030
4031 #if 0
4032 /* might be used if some day we actually use mfra & co
4033  * for random access to fragments,
4034  * but that will require quite some modifications and much less relying
4035  * on a sample array */
4036 #endif
4037
4038 static gboolean
4039 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4040 {
4041   QtDemuxStream *stream;
4042   guint32 ver_flags, track_id, len, num_entries, i;
4043   guint value_size, traf_size, trun_size, sample_size;
4044   guint64 time = 0, moof_offset = 0;
4045 #if 0
4046   GstBuffer *buf = NULL;
4047   GstFlowReturn ret;
4048 #endif
4049   GstByteReader tfra;
4050
4051   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4052
4053   if (!gst_byte_reader_skip (&tfra, 8))
4054     return FALSE;
4055
4056   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4057     return FALSE;
4058
4059   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4060       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4061       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4062     return FALSE;
4063
4064   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4065
4066   stream = qtdemux_find_stream (qtdemux, track_id);
4067   if (stream == NULL)
4068     goto unknown_trackid;
4069
4070   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4071   sample_size = (len & 3) + 1;
4072   trun_size = ((len & 12) >> 2) + 1;
4073   traf_size = ((len & 48) >> 4) + 1;
4074
4075   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4076       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4077
4078   if (num_entries == 0)
4079     goto no_samples;
4080
4081   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4082           value_size + value_size + traf_size + trun_size + sample_size))
4083     goto corrupt_file;
4084
4085   g_free (stream->ra_entries);
4086   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4087   stream->n_ra_entries = num_entries;
4088
4089   for (i = 0; i < num_entries; i++) {
4090     qt_atom_parser_get_offset (&tfra, value_size, &time);
4091     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4092     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4093     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4094     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4095
4096     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4097
4098     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4099         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4100
4101     stream->ra_entries[i].ts = time;
4102     stream->ra_entries[i].moof_offset = moof_offset;
4103
4104     /* don't want to go through the entire file and read all moofs at startup */
4105 #if 0
4106     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4107     if (ret != GST_FLOW_OK)
4108       goto corrupt_file;
4109     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4110         moof_offset, stream);
4111     gst_buffer_unref (buf);
4112 #endif
4113   }
4114
4115   check_update_duration (qtdemux, time);
4116
4117   return TRUE;
4118
4119 /* ERRORS */
4120 unknown_trackid:
4121   {
4122     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4123     return FALSE;
4124   }
4125 corrupt_file:
4126   {
4127     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4128     return FALSE;
4129   }
4130 no_samples:
4131   {
4132     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4133     return FALSE;
4134   }
4135 }
4136
4137 static gboolean
4138 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4139 {
4140   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4141   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4142   GstBuffer *mfro = NULL, *mfra = NULL;
4143   GstFlowReturn flow;
4144   gboolean ret = FALSE;
4145   GNode *mfra_node, *tfra_node;
4146   guint64 mfra_offset = 0;
4147   guint32 fourcc, mfra_size;
4148   gint64 len;
4149
4150   /* query upstream size in bytes */
4151   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4152     goto size_query_failed;
4153
4154   /* mfro box should be at the very end of the file */
4155   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4156   if (flow != GST_FLOW_OK)
4157     goto exit;
4158
4159   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4160
4161   fourcc = QT_FOURCC (mfro_map.data + 4);
4162   if (fourcc != FOURCC_mfro)
4163     goto exit;
4164
4165   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4166   if (mfro_map.size < 16)
4167     goto invalid_mfro_size;
4168
4169   mfra_size = QT_UINT32 (mfro_map.data + 12);
4170   if (mfra_size >= len)
4171     goto invalid_mfra_size;
4172
4173   mfra_offset = len - mfra_size;
4174
4175   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4176       mfra_offset, mfra_size);
4177
4178   /* now get and parse mfra box */
4179   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4180   if (flow != GST_FLOW_OK)
4181     goto broken_file;
4182
4183   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4184
4185   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4186   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4187
4188   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4189
4190   while (tfra_node) {
4191     qtdemux_parse_tfra (qtdemux, tfra_node);
4192     /* iterate all siblings */
4193     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4194   }
4195   g_node_destroy (mfra_node);
4196
4197   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4198   ret = TRUE;
4199
4200 exit:
4201
4202   if (mfro) {
4203     if (mfro_map.memory != NULL)
4204       gst_buffer_unmap (mfro, &mfro_map);
4205     gst_buffer_unref (mfro);
4206   }
4207   if (mfra) {
4208     if (mfra_map.memory != NULL)
4209       gst_buffer_unmap (mfra, &mfra_map);
4210     gst_buffer_unref (mfra);
4211   }
4212   return ret;
4213
4214 /* ERRORS */
4215 size_query_failed:
4216   {
4217     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4218     goto exit;
4219   }
4220 invalid_mfro_size:
4221   {
4222     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4223     goto exit;
4224   }
4225 invalid_mfra_size:
4226   {
4227     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4228     goto exit;
4229   }
4230 broken_file:
4231   {
4232     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4233     goto exit;
4234   }
4235 }
4236
4237 static guint64
4238 add_offset (guint64 offset, guint64 advance)
4239 {
4240   /* Avoid 64-bit overflow by clamping */
4241   if (offset > G_MAXUINT64 - advance)
4242     return G_MAXUINT64;
4243   return offset + advance;
4244 }
4245
4246 static GstFlowReturn
4247 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4248 {
4249   guint64 length = 0;
4250   guint32 fourcc = 0;
4251   GstBuffer *buf = NULL;
4252   GstFlowReturn ret = GST_FLOW_OK;
4253   guint64 cur_offset = qtdemux->offset;
4254   GstMapInfo map;
4255
4256   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4257   if (G_UNLIKELY (ret != GST_FLOW_OK))
4258     goto beach;
4259   gst_buffer_map (buf, &map, GST_MAP_READ);
4260   if (G_LIKELY (map.size >= 8))
4261     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4262   gst_buffer_unmap (buf, &map);
4263   gst_buffer_unref (buf);
4264
4265   /* maybe we already got most we needed, so only consider this eof */
4266   if (G_UNLIKELY (length == 0)) {
4267     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4268         (_("Invalid atom size.")),
4269         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4270             GST_FOURCC_ARGS (fourcc)));
4271     ret = GST_FLOW_EOS;
4272     goto beach;
4273   }
4274
4275   switch (fourcc) {
4276     case FOURCC_moof:
4277       /* record for later parsing when needed */
4278       if (!qtdemux->moof_offset) {
4279         qtdemux->moof_offset = qtdemux->offset;
4280       }
4281       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4282         /* FIXME */
4283       } else {
4284         qtdemux->offset += length;      /* skip moof and keep going */
4285       }
4286       if (qtdemux->got_moov) {
4287         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4288         ret = GST_FLOW_EOS;
4289         goto beach;
4290       }
4291       break;
4292     case FOURCC_mdat:
4293     case FOURCC_free:
4294     case FOURCC_wide:
4295     case FOURCC_PICT:
4296     case FOURCC_pnot:
4297     {
4298       GST_LOG_OBJECT (qtdemux,
4299           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4300           GST_FOURCC_ARGS (fourcc), cur_offset);
4301       qtdemux->offset = add_offset (qtdemux->offset, length);
4302       break;
4303     }
4304     case FOURCC_moov:
4305     {
4306       GstBuffer *moov = NULL;
4307
4308       if (qtdemux->got_moov) {
4309         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4310         qtdemux->offset = add_offset (qtdemux->offset, length);
4311         goto beach;
4312       }
4313
4314       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4315       if (ret != GST_FLOW_OK)
4316         goto beach;
4317       gst_buffer_map (moov, &map, GST_MAP_READ);
4318
4319       if (length != map.size) {
4320         /* Some files have a 'moov' atom at the end of the file which contains
4321          * a terminal 'free' atom where the body of the atom is missing.
4322          * Check for, and permit, this special case.
4323          */
4324         if (map.size >= 8) {
4325           guint8 *final_data = map.data + (map.size - 8);
4326           guint32 final_length = QT_UINT32 (final_data);
4327           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4328
4329           if (final_fourcc == FOURCC_free
4330               && map.size + final_length - 8 == length) {
4331             /* Ok, we've found that special case. Allocate a new buffer with
4332              * that free atom actually present. */
4333             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4334             gst_buffer_fill (newmoov, 0, map.data, map.size);
4335             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4336             gst_buffer_unmap (moov, &map);
4337             gst_buffer_unref (moov);
4338             moov = newmoov;
4339             gst_buffer_map (moov, &map, GST_MAP_READ);
4340           }
4341         }
4342       }
4343
4344       if (length != map.size) {
4345         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4346             (_("This file is incomplete and cannot be played.")),
4347             ("We got less than expected (received %" G_GSIZE_FORMAT
4348                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4349                 (guint) length, cur_offset));
4350         gst_buffer_unmap (moov, &map);
4351         gst_buffer_unref (moov);
4352         ret = GST_FLOW_ERROR;
4353         goto beach;
4354       }
4355       qtdemux->offset += length;
4356
4357       qtdemux_parse_moov (qtdemux, map.data, length);
4358       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4359
4360       qtdemux_parse_tree (qtdemux);
4361       if (qtdemux->moov_node_compressed) {
4362         g_node_destroy (qtdemux->moov_node_compressed);
4363         g_free (qtdemux->moov_node->data);
4364       }
4365       qtdemux->moov_node_compressed = NULL;
4366       g_node_destroy (qtdemux->moov_node);
4367       qtdemux->moov_node = NULL;
4368       gst_buffer_unmap (moov, &map);
4369       gst_buffer_unref (moov);
4370       qtdemux->got_moov = TRUE;
4371
4372       break;
4373     }
4374     case FOURCC_ftyp:
4375     {
4376       GstBuffer *ftyp = NULL;
4377
4378       /* extract major brand; might come in handy for ISO vs QT issues */
4379       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4380       if (ret != GST_FLOW_OK)
4381         goto beach;
4382       qtdemux->offset += length;
4383       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4384       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4385       gst_buffer_unmap (ftyp, &map);
4386       gst_buffer_unref (ftyp);
4387       break;
4388     }
4389     case FOURCC_uuid:
4390     {
4391       GstBuffer *uuid = NULL;
4392
4393       /* uuid are extension atoms */
4394       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4395       if (ret != GST_FLOW_OK)
4396         goto beach;
4397       qtdemux->offset += length;
4398       gst_buffer_map (uuid, &map, GST_MAP_READ);
4399       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4400       gst_buffer_unmap (uuid, &map);
4401       gst_buffer_unref (uuid);
4402       break;
4403     }
4404     case FOURCC_sidx:
4405     {
4406       GstBuffer *sidx = NULL;
4407       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4408       if (ret != GST_FLOW_OK)
4409         goto beach;
4410       qtdemux->offset += length;
4411       gst_buffer_map (sidx, &map, GST_MAP_READ);
4412       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4413       gst_buffer_unmap (sidx, &map);
4414       gst_buffer_unref (sidx);
4415       break;
4416     }
4417     default:
4418     {
4419       GstBuffer *unknown = NULL;
4420
4421       GST_LOG_OBJECT (qtdemux,
4422           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4423           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4424           cur_offset);
4425       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4426       if (ret != GST_FLOW_OK)
4427         goto beach;
4428       gst_buffer_map (unknown, &map, GST_MAP_READ);
4429       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4430       gst_buffer_unmap (unknown, &map);
4431       gst_buffer_unref (unknown);
4432       qtdemux->offset += length;
4433       break;
4434     }
4435   }
4436
4437 beach:
4438   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4439     /* digested all data, show what we have */
4440     qtdemux_prepare_streams (qtdemux);
4441     ret = qtdemux_expose_streams (qtdemux);
4442
4443     qtdemux->state = QTDEMUX_STATE_MOVIE;
4444     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4445         qtdemux->state);
4446     return ret;
4447   }
4448   return ret;
4449 }
4450
4451 /* Seeks to the previous keyframe of the indexed stream and
4452  * aligns other streams with respect to the keyframe timestamp
4453  * of indexed stream. Only called in case of Reverse Playback
4454  */
4455 static GstFlowReturn
4456 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4457 {
4458   guint8 n = 0;
4459   guint32 seg_idx = 0, k_index = 0;
4460   guint32 ref_seg_idx, ref_k_index;
4461   GstClockTime k_pos = 0, last_stop = 0;
4462   QtDemuxSegment *seg = NULL;
4463   QtDemuxStream *ref_str = NULL;
4464   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4465   guint64 target_ts;
4466
4467   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4468    * and finally align all the other streams on that timestamp with their
4469    * respective keyframes */
4470   for (n = 0; n < qtdemux->n_streams; n++) {
4471     QtDemuxStream *str = qtdemux->streams[n];
4472
4473     /* No candidate yet, take the first stream */
4474     if (!ref_str) {
4475       ref_str = str;
4476       continue;
4477     }
4478
4479     /* So that stream has a segment, we prefer video streams */
4480     if (str->subtype == FOURCC_vide) {
4481       ref_str = str;
4482       break;
4483     }
4484   }
4485
4486   if (G_UNLIKELY (!ref_str)) {
4487     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4488     goto eos;
4489   }
4490
4491   if (G_UNLIKELY (!ref_str->from_sample)) {
4492     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4493     goto eos;
4494   }
4495
4496   /* So that stream has been playing from from_sample to to_sample. We will
4497    * get the timestamp of the previous sample and search for a keyframe before
4498    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4499   if (ref_str->subtype == FOURCC_vide) {
4500     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4501         ref_str->from_sample - 1, FALSE);
4502   } else {
4503     if (ref_str->from_sample >= 10)
4504       k_index = ref_str->from_sample - 10;
4505     else
4506       k_index = 0;
4507   }
4508
4509   target_ts =
4510       ref_str->samples[k_index].timestamp +
4511       ref_str->samples[k_index].pts_offset;
4512
4513   /* get current segment for that stream */
4514   seg = &ref_str->segments[ref_str->segment_index];
4515   /* Use segment start in original timescale for comparisons */
4516   seg_media_start_mov = seg->trak_media_start;
4517
4518   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4519       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4520       k_index, target_ts, seg_media_start_mov,
4521       GST_TIME_ARGS (seg->media_start));
4522
4523   /* Crawl back through segments to find the one containing this I frame */
4524   while (target_ts < seg_media_start_mov) {
4525     GST_DEBUG_OBJECT (qtdemux,
4526         "keyframe position (sample %u) is out of segment %u " " target %"
4527         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4528         ref_str->segment_index, target_ts, seg_media_start_mov);
4529
4530     if (G_UNLIKELY (!ref_str->segment_index)) {
4531       /* Reached first segment, let's consider it's EOS */
4532       goto eos;
4533     }
4534     ref_str->segment_index--;
4535     seg = &ref_str->segments[ref_str->segment_index];
4536     /* Use segment start in original timescale for comparisons */
4537     seg_media_start_mov = seg->trak_media_start;
4538   }
4539   /* Calculate time position of the keyframe and where we should stop */
4540   k_pos =
4541       QTSTREAMTIME_TO_GSTTIME (ref_str,
4542       target_ts - seg->trak_media_start) + seg->time;
4543   last_stop =
4544       QTSTREAMTIME_TO_GSTTIME (ref_str,
4545       ref_str->samples[ref_str->from_sample].timestamp -
4546       seg->trak_media_start) + seg->time;
4547
4548   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4549       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4550       k_index, GST_TIME_ARGS (k_pos));
4551
4552   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4553   qtdemux->segment.position = last_stop;
4554   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4555       GST_TIME_ARGS (last_stop));
4556
4557   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4558     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4559     goto eos;
4560   }
4561
4562   ref_seg_idx = ref_str->segment_index;
4563   ref_k_index = k_index;
4564
4565   /* Align them all on this */
4566   for (n = 0; n < qtdemux->n_streams; n++) {
4567     guint32 index = 0;
4568     GstClockTime seg_time = 0;
4569     QtDemuxStream *str = qtdemux->streams[n];
4570
4571     /* aligning reference stream again might lead to backing up to yet another
4572      * keyframe (due to timestamp rounding issues),
4573      * potentially putting more load on downstream; so let's try to avoid */
4574     if (str == ref_str) {
4575       seg_idx = ref_seg_idx;
4576       seg = &str->segments[seg_idx];
4577       k_index = ref_k_index;
4578       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4579           "sample at index %d", n, ref_str->segment_index, k_index);
4580     } else {
4581       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4582       GST_DEBUG_OBJECT (qtdemux,
4583           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4584           seg_idx, GST_TIME_ARGS (k_pos));
4585
4586       /* get segment and time in the segment */
4587       seg = &str->segments[seg_idx];
4588       seg_time = k_pos - seg->time;
4589
4590       /* get the media time in the segment.
4591        * No adjustment for empty "filler" segments */
4592       if (seg->media_start != GST_CLOCK_TIME_NONE)
4593         seg_time += seg->media_start;
4594
4595       /* get the index of the sample with media time */
4596       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4597       GST_DEBUG_OBJECT (qtdemux,
4598           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4599           GST_TIME_ARGS (seg_time), index);
4600
4601       /* find previous keyframe */
4602       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4603     }
4604
4605     /* Remember until where we want to go */
4606     str->to_sample = str->from_sample - 1;
4607     /* Define our time position */
4608     target_ts =
4609         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4610     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4611     if (seg->media_start != GST_CLOCK_TIME_NONE)
4612       str->time_position -= seg->media_start;
4613
4614     /* Now seek back in time */
4615     gst_qtdemux_move_stream (qtdemux, str, k_index);
4616     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4617         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4618         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4619   }
4620
4621   return GST_FLOW_OK;
4622
4623 eos:
4624   return GST_FLOW_EOS;
4625 }
4626
4627 /*
4628  * Gets the current qt segment start, stop and position for the
4629  * given time offset. This is used in update_segment()
4630  */
4631 static void
4632 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4633     QtDemuxStream * stream, GstClockTime offset,
4634     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4635 {
4636   GstClockTime seg_time;
4637   GstClockTime start, stop, time;
4638   QtDemuxSegment *segment;
4639
4640   segment = &stream->segments[stream->segment_index];
4641
4642   /* get time in this segment */
4643   seg_time = (offset - segment->time) * segment->rate;
4644
4645   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4646       GST_TIME_ARGS (seg_time));
4647
4648   if (G_UNLIKELY (seg_time > segment->duration)) {
4649     GST_LOG_OBJECT (stream->pad,
4650         "seg_time > segment->duration %" GST_TIME_FORMAT,
4651         GST_TIME_ARGS (segment->duration));
4652     seg_time = segment->duration;
4653   }
4654
4655   /* qtdemux->segment.stop is in outside-time-realm, whereas
4656    * segment->media_stop is in track-time-realm.
4657    *
4658    * In order to compare the two, we need to bring segment.stop
4659    * into the track-time-realm
4660    *
4661    * FIXME - does this comment still hold? Don't see any conversion here */
4662
4663   stop = qtdemux->segment.stop;
4664   if (stop == GST_CLOCK_TIME_NONE)
4665     stop = qtdemux->segment.duration;
4666   if (stop == GST_CLOCK_TIME_NONE)
4667     stop = segment->media_stop;
4668   else
4669     stop =
4670         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4671
4672   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4673     start = segment->time + seg_time;
4674     time = offset;
4675     stop = start - seg_time + segment->duration;
4676   } else if (qtdemux->segment.rate >= 0) {
4677     start = MIN (segment->media_start + seg_time, stop);
4678     time = offset;
4679   } else {
4680     if (segment->media_start >= qtdemux->segment.start) {
4681       time = segment->time;
4682     } else {
4683       time = segment->time + (qtdemux->segment.start - segment->media_start);
4684     }
4685
4686     start = MAX (segment->media_start, qtdemux->segment.start);
4687     stop = MIN (segment->media_start + seg_time, stop);
4688   }
4689
4690   *_start = start;
4691   *_stop = stop;
4692   *_time = time;
4693 }
4694
4695 /*
4696  * Updates the qt segment used for the stream and pushes a new segment event
4697  * downstream on this stream's pad.
4698  */
4699 static gboolean
4700 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4701     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4702     GstClockTime * _stop)
4703 {
4704   QtDemuxSegment *segment;
4705   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4706   gdouble rate;
4707   GstEvent *event;
4708
4709   /* update the current segment */
4710   stream->segment_index = seg_idx;
4711
4712   /* get the segment */
4713   segment = &stream->segments[seg_idx];
4714
4715   if (G_UNLIKELY (offset < segment->time)) {
4716     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4717         GST_TIME_ARGS (segment->time));
4718     return FALSE;
4719   }
4720
4721   /* segment lies beyond total indicated duration */
4722   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4723           segment->time > qtdemux->segment.duration)) {
4724     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4725         " < segment->time %" GST_TIME_FORMAT,
4726         GST_TIME_ARGS (qtdemux->segment.duration),
4727         GST_TIME_ARGS (segment->time));
4728     return FALSE;
4729   }
4730
4731   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4732       &start, &stop, &time);
4733
4734   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4735       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4736       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4737
4738   /* combine global rate with that of the segment */
4739   rate = segment->rate * qtdemux->segment.rate;
4740
4741   /* Copy flags from main segment */
4742   stream->segment.flags = qtdemux->segment.flags;
4743
4744   /* update the segment values used for clipping */
4745   stream->segment.offset = qtdemux->segment.offset;
4746   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4747   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4748   stream->segment.rate = rate;
4749   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4750       stream->cslg_shift);
4751   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4752       stream->cslg_shift);
4753   stream->segment.time = time;
4754   stream->segment.position = stream->segment.start;
4755
4756   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4757       &stream->segment);
4758
4759   /* now prepare and send the segment */
4760   if (stream->pad) {
4761     event = gst_event_new_segment (&stream->segment);
4762     if (qtdemux->segment_seqnum) {
4763       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4764     }
4765     gst_pad_push_event (stream->pad, event);
4766     /* assume we can send more data now */
4767     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4768     /* clear to send tags on this pad now */
4769     gst_qtdemux_push_tags (qtdemux, stream);
4770   }
4771
4772   if (_start)
4773     *_start = start;
4774   if (_stop)
4775     *_stop = stop;
4776
4777   return TRUE;
4778 }
4779
4780 /* activate the given segment number @seg_idx of @stream at time @offset.
4781  * @offset is an absolute global position over all the segments.
4782  *
4783  * This will push out a NEWSEGMENT event with the right values and
4784  * position the stream index to the first decodable sample before
4785  * @offset.
4786  */
4787 static gboolean
4788 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4789     guint32 seg_idx, GstClockTime offset)
4790 {
4791   QtDemuxSegment *segment;
4792   guint32 index, kf_index;
4793   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4794
4795   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4796       seg_idx, GST_TIME_ARGS (offset));
4797
4798   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4799           &start, &stop))
4800     return FALSE;
4801
4802   segment = &stream->segments[stream->segment_index];
4803
4804   /* in the fragmented case, we pick a fragment that starts before our
4805    * desired position and rely on downstream to wait for a keyframe
4806    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4807    * tfra entries tells us which trun/sample the key unit is in, but we don't
4808    * make use of this additional information at the moment) */
4809   if (qtdemux->fragmented) {
4810     stream->to_sample = G_MAXUINT32;
4811     return TRUE;
4812   }
4813
4814   /* We don't need to look for a sample in push-based */
4815   if (!qtdemux->pullbased)
4816     return TRUE;
4817
4818   /* and move to the keyframe before the indicated media time of the
4819    * segment */
4820   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4821     if (qtdemux->segment.rate >= 0) {
4822       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4823       stream->to_sample = G_MAXUINT32;
4824       GST_DEBUG_OBJECT (stream->pad,
4825           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4826           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4827           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4828     } else {
4829       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4830       stream->to_sample = index;
4831       GST_DEBUG_OBJECT (stream->pad,
4832           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4833           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4834           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4835     }
4836   } else {
4837     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4838         "this is an empty segment");
4839     return TRUE;
4840   }
4841
4842   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4843    * encountered an error and printed a message so we return appropriately */
4844   if (index == -1)
4845     return FALSE;
4846
4847   /* we're at the right spot */
4848   if (index == stream->sample_index) {
4849     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4850     return TRUE;
4851   }
4852
4853   /* find keyframe of the target index */
4854   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4855
4856 /* *INDENT-OFF* */
4857 /* indent does stupid stuff with stream->samples[].timestamp */
4858
4859   /* if we move forwards, we don't have to go back to the previous
4860    * keyframe since we already sent that. We can also just jump to
4861    * the keyframe right before the target index if there is one. */
4862   if (index > stream->sample_index) {
4863     /* moving forwards check if we move past a keyframe */
4864     if (kf_index > stream->sample_index) {
4865       GST_DEBUG_OBJECT (stream->pad,
4866            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4867            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4868            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4869       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4870     } else {
4871       GST_DEBUG_OBJECT (stream->pad,
4872           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4873           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4874           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4875     }
4876   } else {
4877     GST_DEBUG_OBJECT (stream->pad,
4878         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4879         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4880         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4881     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4882   }
4883
4884 /* *INDENT-ON* */
4885
4886   return TRUE;
4887 }
4888
4889 /* prepare to get the current sample of @stream, getting essential values.
4890  *
4891  * This function will also prepare and send the segment when needed.
4892  *
4893  * Return FALSE if the stream is EOS.
4894  *
4895  * PULL-BASED
4896  */
4897 static gboolean
4898 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4899     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4900     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4901     gboolean * keyframe)
4902 {
4903   QtDemuxSample *sample;
4904   GstClockTime time_position;
4905   guint32 seg_idx;
4906
4907   g_return_val_if_fail (stream != NULL, FALSE);
4908
4909   time_position = stream->time_position;
4910   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4911     goto eos;
4912
4913   seg_idx = stream->segment_index;
4914   if (G_UNLIKELY (seg_idx == -1)) {
4915     /* find segment corresponding to time_position if we are looking
4916      * for a segment. */
4917     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4918   }
4919
4920   /* different segment, activate it, sample_index will be set. */
4921   if (G_UNLIKELY (stream->segment_index != seg_idx))
4922     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4923
4924   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4925                   segment_index]))) {
4926     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4927
4928     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4929         " prepare empty sample");
4930
4931     *empty = TRUE;
4932     *pts = *dts = time_position;
4933     *duration = seg->duration - (time_position - seg->time);
4934
4935     return TRUE;
4936   }
4937
4938   *empty = FALSE;
4939
4940   if (stream->sample_index == -1)
4941     stream->sample_index = 0;
4942
4943   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4944       stream->sample_index, stream->n_samples);
4945
4946   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4947     if (!qtdemux->fragmented)
4948       goto eos;
4949
4950     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4951     do {
4952       GstFlowReturn flow;
4953
4954       GST_OBJECT_LOCK (qtdemux);
4955       flow = qtdemux_add_fragmented_samples (qtdemux);
4956       GST_OBJECT_UNLOCK (qtdemux);
4957
4958       if (flow != GST_FLOW_OK)
4959         goto eos;
4960     }
4961     while (stream->sample_index >= stream->n_samples);
4962   }
4963
4964   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4965     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4966         stream->sample_index);
4967     return FALSE;
4968   }
4969
4970   /* now get the info for the sample we're at */
4971   sample = &stream->samples[stream->sample_index];
4972
4973   *dts = QTSAMPLE_DTS (stream, sample);
4974   *pts = QTSAMPLE_PTS (stream, sample);
4975   *offset = sample->offset;
4976   *size = sample->size;
4977   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4978   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4979
4980   return TRUE;
4981
4982   /* special cases */
4983 eos:
4984   {
4985     stream->time_position = GST_CLOCK_TIME_NONE;
4986     return FALSE;
4987   }
4988 }
4989
4990 /* move to the next sample in @stream.
4991  *
4992  * Moves to the next segment when needed.
4993  */
4994 static void
4995 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4996 {
4997   QtDemuxSample *sample;
4998   QtDemuxSegment *segment;
4999
5000   /* get current segment */
5001   segment = &stream->segments[stream->segment_index];
5002
5003   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5004     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5005     goto next_segment;
5006   }
5007
5008   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5009     /* Mark the stream as EOS */
5010     GST_DEBUG_OBJECT (qtdemux,
5011         "reached max allowed sample %u, mark EOS", stream->to_sample);
5012     stream->time_position = GST_CLOCK_TIME_NONE;
5013     return;
5014   }
5015
5016   /* move to next sample */
5017   stream->sample_index++;
5018   stream->offset_in_sample = 0;
5019
5020   /* reached the last sample, we need the next segment */
5021   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5022     goto next_segment;
5023
5024   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5025     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5026         stream->sample_index);
5027     return;
5028   }
5029
5030   /* get next sample */
5031   sample = &stream->samples[stream->sample_index];
5032
5033   /* see if we are past the segment */
5034   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5035     goto next_segment;
5036
5037   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5038     /* inside the segment, update time_position, looks very familiar to
5039      * GStreamer segments, doesn't it? */
5040     stream->time_position =
5041         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5042   } else {
5043     /* not yet in segment, time does not yet increment. This means
5044      * that we are still prerolling keyframes to the decoder so it can
5045      * decode the first sample of the segment. */
5046     stream->time_position = segment->time;
5047   }
5048   return;
5049
5050   /* move to the next segment */
5051 next_segment:
5052   {
5053     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5054
5055     if (stream->segment_index == stream->n_segments - 1) {
5056       /* are we at the end of the last segment, we're EOS */
5057       stream->time_position = GST_CLOCK_TIME_NONE;
5058     } else {
5059       /* else we're only at the end of the current segment */
5060       stream->time_position = segment->stop_time;
5061     }
5062     /* make sure we select a new segment */
5063
5064     /* accumulate previous segments */
5065     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5066       stream->accumulated_base +=
5067           (stream->segment.stop -
5068           stream->segment.start) / ABS (stream->segment.rate);
5069
5070     stream->segment_index = -1;
5071   }
5072 }
5073
5074 static void
5075 gst_qtdemux_sync_streams (GstQTDemux * demux)
5076 {
5077   gint i;
5078
5079   if (demux->n_streams <= 1)
5080     return;
5081
5082   for (i = 0; i < demux->n_streams; i++) {
5083     QtDemuxStream *stream;
5084     GstClockTime end_time;
5085
5086     stream = demux->streams[i];
5087
5088     if (!stream->pad)
5089       continue;
5090
5091     /* TODO advance time on subtitle streams here, if any some day */
5092
5093     /* some clips/trailers may have unbalanced streams at the end,
5094      * so send EOS on shorter stream to prevent stalling others */
5095
5096     /* do not mess with EOS if SEGMENT seeking */
5097     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5098       continue;
5099
5100     if (demux->pullbased) {
5101       /* loop mode is sample time based */
5102       if (!STREAM_IS_EOS (stream))
5103         continue;
5104     } else {
5105       /* push mode is byte position based */
5106       if (stream->n_samples &&
5107           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5108         continue;
5109     }
5110
5111     if (stream->sent_eos)
5112       continue;
5113
5114     /* only act if some gap */
5115     end_time = stream->segments[stream->n_segments - 1].stop_time;
5116     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5117         ", stream end: %" GST_TIME_FORMAT,
5118         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5119     if (GST_CLOCK_TIME_IS_VALID (end_time)
5120         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5121       GstEvent *event;
5122
5123       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5124           GST_PAD_NAME (stream->pad));
5125       stream->sent_eos = TRUE;
5126       event = gst_event_new_eos ();
5127       if (demux->segment_seqnum)
5128         gst_event_set_seqnum (event, demux->segment_seqnum);
5129       gst_pad_push_event (stream->pad, event);
5130     }
5131   }
5132 }
5133
5134 /* EOS and NOT_LINKED need to be combined. This means that we return:
5135  *
5136  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5137  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5138  */
5139 static GstFlowReturn
5140 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5141     GstFlowReturn ret)
5142 {
5143   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5144
5145   if (stream->pad)
5146     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5147         ret);
5148   else
5149     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5150
5151   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5152   return ret;
5153 }
5154
5155 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5156  * completely clipped
5157  *
5158  * Should be used only with raw buffers */
5159 static GstBuffer *
5160 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5161     GstBuffer * buf)
5162 {
5163   guint64 start, stop, cstart, cstop, diff;
5164   GstClockTime pts, duration;
5165   gsize size, osize;
5166   gint num_rate, denom_rate;
5167   gint frame_size;
5168   gboolean clip_data;
5169   guint offset;
5170
5171   osize = size = gst_buffer_get_size (buf);
5172   offset = 0;
5173
5174   /* depending on the type, setup the clip parameters */
5175   if (stream->subtype == FOURCC_soun) {
5176     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5177     num_rate = GST_SECOND;
5178     denom_rate = (gint) CUR_STREAM (stream)->rate;
5179     clip_data = TRUE;
5180   } else if (stream->subtype == FOURCC_vide) {
5181     frame_size = size;
5182     num_rate = CUR_STREAM (stream)->fps_n;
5183     denom_rate = CUR_STREAM (stream)->fps_d;
5184     clip_data = FALSE;
5185   } else
5186     goto wrong_type;
5187
5188   if (frame_size <= 0)
5189     goto bad_frame_size;
5190
5191   /* we can only clip if we have a valid pts */
5192   pts = GST_BUFFER_PTS (buf);
5193   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5194     goto no_pts;
5195
5196   duration = GST_BUFFER_DURATION (buf);
5197
5198   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5199     duration =
5200         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5201   }
5202
5203   start = pts;
5204   stop = start + duration;
5205
5206   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5207               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5208     goto clipped;
5209
5210   /* see if some clipping happened */
5211   diff = cstart - start;
5212   if (diff > 0) {
5213     pts += diff;
5214     duration -= diff;
5215
5216     if (clip_data) {
5217       /* bring clipped time to samples and to bytes */
5218       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5219       diff *= frame_size;
5220
5221       GST_DEBUG_OBJECT (qtdemux,
5222           "clipping start to %" GST_TIME_FORMAT " %"
5223           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5224
5225       offset = diff;
5226       size -= diff;
5227     }
5228   }
5229   diff = stop - cstop;
5230   if (diff > 0) {
5231     duration -= diff;
5232
5233     if (clip_data) {
5234       /* bring clipped time to samples and then to bytes */
5235       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5236       diff *= frame_size;
5237       GST_DEBUG_OBJECT (qtdemux,
5238           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5239           " bytes", GST_TIME_ARGS (cstop), diff);
5240       size -= diff;
5241     }
5242   }
5243
5244   if (offset != 0 || size != osize)
5245     gst_buffer_resize (buf, offset, size);
5246
5247   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5248   GST_BUFFER_PTS (buf) = pts;
5249   GST_BUFFER_DURATION (buf) = duration;
5250
5251   return buf;
5252
5253   /* dropped buffer */
5254 wrong_type:
5255   {
5256     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5257     return buf;
5258   }
5259 bad_frame_size:
5260   {
5261     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5262     return buf;
5263   }
5264 no_pts:
5265   {
5266     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5267     return buf;
5268   }
5269 clipped:
5270   {
5271     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5272     gst_buffer_unref (buf);
5273     return NULL;
5274   }
5275 }
5276
5277 static GstBuffer *
5278 gst_qtdemux_align_buffer (GstQTDemux * demux,
5279     GstBuffer * buffer, gsize alignment)
5280 {
5281   GstMapInfo map;
5282
5283   gst_buffer_map (buffer, &map, GST_MAP_READ);
5284
5285   if (map.size < sizeof (guintptr)) {
5286     gst_buffer_unmap (buffer, &map);
5287     return buffer;
5288   }
5289
5290   if (((guintptr) map.data) & (alignment - 1)) {
5291     GstBuffer *new_buffer;
5292     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5293
5294     new_buffer = gst_buffer_new_allocate (NULL,
5295         gst_buffer_get_size (buffer), &params);
5296
5297     /* Copy data "by hand", so ensure alignment is kept: */
5298     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5299
5300     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5301     GST_DEBUG_OBJECT (demux,
5302         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5303         alignment);
5304
5305     gst_buffer_unmap (buffer, &map);
5306     gst_buffer_unref (buffer);
5307
5308     return new_buffer;
5309   }
5310
5311   gst_buffer_unmap (buffer, &map);
5312   return buffer;
5313 }
5314
5315 /* the input buffer metadata must be writable,
5316  * but time/duration etc not yet set and need not be preserved */
5317 static GstBuffer *
5318 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5319     GstBuffer * buf)
5320 {
5321   GstMapInfo map;
5322   guint nsize = 0;
5323   gchar *str;
5324
5325   /* not many cases for now */
5326   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5327     /* send a one time dvd clut event */
5328     if (stream->pending_event && stream->pad)
5329       gst_pad_push_event (stream->pad, stream->pending_event);
5330     stream->pending_event = NULL;
5331   }
5332
5333   if (G_UNLIKELY (stream->subtype != FOURCC_text
5334           && stream->subtype != FOURCC_sbtl &&
5335           stream->subtype != FOURCC_subp)) {
5336     return buf;
5337   }
5338
5339   gst_buffer_map (buf, &map, GST_MAP_READ);
5340
5341   /* empty buffer is sent to terminate previous subtitle */
5342   if (map.size <= 2) {
5343     gst_buffer_unmap (buf, &map);
5344     gst_buffer_unref (buf);
5345     return NULL;
5346   }
5347   if (stream->subtype == FOURCC_subp) {
5348     /* That's all the processing needed for subpictures */
5349     gst_buffer_unmap (buf, &map);
5350     return buf;
5351   }
5352
5353   nsize = GST_READ_UINT16_BE (map.data);
5354   nsize = MIN (nsize, map.size - 2);
5355
5356   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5357       nsize, map.size);
5358
5359   /* takes care of UTF-8 validation or UTF-16 recognition,
5360    * no other encoding expected */
5361   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5362   gst_buffer_unmap (buf, &map);
5363   if (str) {
5364     gst_buffer_unref (buf);
5365     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5366   } else {
5367     /* this should not really happen unless the subtitle is corrupted */
5368     gst_buffer_unref (buf);
5369     buf = NULL;
5370   }
5371
5372   /* FIXME ? convert optional subsequent style info to markup */
5373
5374   return buf;
5375 }
5376
5377 /* Sets a buffer's attributes properly and pushes it downstream.
5378  * Also checks for additional actions and custom processing that may
5379  * need to be done first.
5380  */
5381 static GstFlowReturn
5382 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5383     QtDemuxStream * stream, GstBuffer * buf,
5384     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5385     gboolean keyframe, GstClockTime position, guint64 byte_position)
5386 {
5387   GstFlowReturn ret = GST_FLOW_OK;
5388
5389   /* offset the timestamps according to the edit list */
5390
5391   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5392     gchar *url;
5393     GstMapInfo map;
5394
5395     gst_buffer_map (buf, &map, GST_MAP_READ);
5396     url = g_strndup ((gchar *) map.data, map.size);
5397     gst_buffer_unmap (buf, &map);
5398     if (url != NULL && strlen (url) != 0) {
5399       /* we have RTSP redirect now */
5400       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5401           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5402               gst_structure_new ("redirect",
5403                   "new-location", G_TYPE_STRING, url, NULL)));
5404       qtdemux->posted_redirect = TRUE;
5405     } else {
5406       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5407           "posting");
5408     }
5409     g_free (url);
5410   }
5411
5412   /* position reporting */
5413   if (qtdemux->segment.rate >= 0) {
5414     qtdemux->segment.position = position;
5415     gst_qtdemux_sync_streams (qtdemux);
5416   }
5417
5418   if (G_UNLIKELY (!stream->pad)) {
5419     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5420     gst_buffer_unref (buf);
5421     goto exit;
5422   }
5423
5424   /* send out pending buffers */
5425   while (stream->buffers) {
5426     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5427
5428     if (G_UNLIKELY (stream->discont)) {
5429       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5430       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5431       stream->discont = FALSE;
5432     } else {
5433       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5434     }
5435
5436     if (stream->alignment > 1)
5437       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5438     gst_pad_push (stream->pad, buffer);
5439
5440     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5441   }
5442
5443   /* we're going to modify the metadata */
5444   buf = gst_buffer_make_writable (buf);
5445
5446   if (G_UNLIKELY (stream->need_process))
5447     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5448
5449   if (!buf) {
5450     goto exit;
5451   }
5452
5453   GST_BUFFER_DTS (buf) = dts;
5454   GST_BUFFER_PTS (buf) = pts;
5455   GST_BUFFER_DURATION (buf) = duration;
5456   GST_BUFFER_OFFSET (buf) = -1;
5457   GST_BUFFER_OFFSET_END (buf) = -1;
5458
5459   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5460     gst_buffer_append_memory (buf,
5461         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5462
5463   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5464     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5465   }
5466 #if 0
5467   if (G_UNLIKELY (qtdemux->element_index)) {
5468     GstClockTime stream_time;
5469
5470     stream_time =
5471         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5472         timestamp);
5473     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5474       GST_LOG_OBJECT (qtdemux,
5475           "adding association %" GST_TIME_FORMAT "-> %"
5476           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5477       gst_index_add_association (qtdemux->element_index,
5478           qtdemux->index_id,
5479           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5480           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5481           GST_FORMAT_BYTES, byte_position, NULL);
5482     }
5483   }
5484 #endif
5485
5486   if (stream->need_clip)
5487     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5488
5489   if (G_UNLIKELY (buf == NULL))
5490     goto exit;
5491
5492   if (G_UNLIKELY (stream->discont)) {
5493     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5494     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5495     stream->discont = FALSE;
5496   } else {
5497     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5498   }
5499
5500   if (!keyframe) {
5501     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5502     stream->on_keyframe = FALSE;
5503   } else {
5504     stream->on_keyframe = TRUE;
5505   }
5506
5507
5508   GST_LOG_OBJECT (qtdemux,
5509       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5510       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5511       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5512       GST_PAD_NAME (stream->pad));
5513
5514   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5515     GstStructure *crypto_info;
5516     QtDemuxCencSampleSetInfo *info =
5517         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5518     gint index;
5519     GstEvent *event;
5520
5521     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5522       gst_pad_push_event (stream->pad, event);
5523     }
5524
5525     if (info->crypto_info == NULL) {
5526       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5527       gst_buffer_unref (buf);
5528       goto exit;
5529     }
5530
5531     /* The end of the crypto_info array matches our n_samples position,
5532      * so count backward from there */
5533     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5534     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5535       /* steal structure from array */
5536       crypto_info = g_ptr_array_index (info->crypto_info, index);
5537       g_ptr_array_index (info->crypto_info, index) = NULL;
5538       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5539           info->crypto_info->len);
5540       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5541         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5542     } else {
5543       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5544           index, stream->sample_index);
5545     }
5546   }
5547
5548   if (stream->alignment > 1)
5549     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5550
5551   ret = gst_pad_push (stream->pad, buf);
5552
5553   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5554     /* mark position in stream, we'll need this to know when to send GAP event */
5555     stream->segment.position = pts + duration;
5556   }
5557
5558 exit:
5559   return ret;
5560 }
5561
5562 static const QtDemuxRandomAccessEntry *
5563 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5564     GstClockTime pos, gboolean after)
5565 {
5566   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5567   guint n_entries = stream->n_ra_entries;
5568   guint i;
5569
5570   /* we assume the table is sorted */
5571   for (i = 0; i < n_entries; ++i) {
5572     if (entries[i].ts > pos)
5573       break;
5574   }
5575
5576   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5577    * probably okay to assume that the index lists the very first fragment */
5578   if (i == 0)
5579     return &entries[0];
5580
5581   if (after)
5582     return &entries[i];
5583   else
5584     return &entries[i - 1];
5585 }
5586
5587 static gboolean
5588 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5589 {
5590   const QtDemuxRandomAccessEntry *best_entry = NULL;
5591   guint i;
5592
5593   GST_OBJECT_LOCK (qtdemux);
5594
5595   g_assert (qtdemux->n_streams > 0);
5596
5597   for (i = 0; i < qtdemux->n_streams; i++) {
5598     const QtDemuxRandomAccessEntry *entry;
5599     QtDemuxStream *stream;
5600     gboolean is_audio_or_video;
5601
5602     stream = qtdemux->streams[i];
5603
5604     g_free (stream->samples);
5605     stream->samples = NULL;
5606     stream->n_samples = 0;
5607     stream->stbl_index = -1;    /* no samples have yet been parsed */
5608     stream->sample_index = -1;
5609
5610     if (stream->protection_scheme_info) {
5611       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5612       if (stream->protection_scheme_type == FOURCC_cenc) {
5613         QtDemuxCencSampleSetInfo *info =
5614             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5615         if (info->crypto_info) {
5616           g_ptr_array_free (info->crypto_info, TRUE);
5617           info->crypto_info = NULL;
5618         }
5619       }
5620     }
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   if (best_entry == NULL) {
5648     GST_OBJECT_UNLOCK (qtdemux);
5649     return FALSE;
5650   }
5651
5652   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5653       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5654       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5655       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5656
5657   qtdemux->moof_offset = best_entry->moof_offset;
5658
5659   qtdemux_add_fragmented_samples (qtdemux);
5660
5661   GST_OBJECT_UNLOCK (qtdemux);
5662   return TRUE;
5663 }
5664
5665 static GstFlowReturn
5666 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5667 {
5668   GstFlowReturn ret = GST_FLOW_OK;
5669   GstBuffer *buf = NULL;
5670   QtDemuxStream *stream;
5671   GstClockTime min_time;
5672   guint64 offset = 0;
5673   GstClockTime dts = GST_CLOCK_TIME_NONE;
5674   GstClockTime pts = GST_CLOCK_TIME_NONE;
5675   GstClockTime duration = 0;
5676   gboolean keyframe = FALSE;
5677   guint sample_size = 0;
5678   gboolean empty = 0;
5679   guint size;
5680   gint index;
5681   gint i;
5682
5683   gst_qtdemux_push_pending_newsegment (qtdemux);
5684
5685   if (qtdemux->fragmented_seek_pending) {
5686     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5687     gst_qtdemux_do_fragmented_seek (qtdemux);
5688     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5689     qtdemux->fragmented_seek_pending = FALSE;
5690   }
5691
5692   /* Figure out the next stream sample to output, min_time is expressed in
5693    * global time and runs over the edit list segments. */
5694   min_time = G_MAXUINT64;
5695   index = -1;
5696   for (i = 0; i < qtdemux->n_streams; i++) {
5697     GstClockTime position;
5698
5699     stream = qtdemux->streams[i];
5700     position = stream->time_position;
5701
5702     /* position of -1 is EOS */
5703     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5704       min_time = position;
5705       index = i;
5706     }
5707   }
5708   /* all are EOS */
5709   if (G_UNLIKELY (index == -1)) {
5710     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5711     goto eos;
5712   }
5713
5714   /* check for segment end */
5715   if (G_UNLIKELY (qtdemux->segment.stop != -1
5716           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5717               || (qtdemux->segment.rate < 0
5718                   && qtdemux->segment.start > min_time))
5719           && qtdemux->streams[index]->on_keyframe)) {
5720     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5721     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5722     goto eos_stream;
5723   }
5724
5725   /* gap events for subtitle streams */
5726   for (i = 0; i < qtdemux->n_streams; i++) {
5727     stream = qtdemux->streams[i];
5728     if (stream->pad && (stream->subtype == FOURCC_subp
5729             || stream->subtype == FOURCC_text
5730             || stream->subtype == FOURCC_sbtl)) {
5731       /* send one second gap events until the stream catches up */
5732       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5733       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5734           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5735           stream->segment.position + GST_SECOND < min_time) {
5736         GstEvent *gap =
5737             gst_event_new_gap (stream->segment.position, GST_SECOND);
5738         gst_pad_push_event (stream->pad, gap);
5739         stream->segment.position += GST_SECOND;
5740       }
5741     }
5742   }
5743
5744   stream = qtdemux->streams[index];
5745   /* fetch info for the current sample of this stream */
5746   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5747               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5748     goto eos_stream;
5749
5750   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5751   if (stream->new_caps) {
5752     gst_qtdemux_configure_stream (qtdemux, stream);
5753     qtdemux_do_allocation (qtdemux, stream);
5754   }
5755
5756   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5757   if (G_UNLIKELY (qtdemux->
5758           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5759     if (stream->subtype == FOURCC_vide && !keyframe) {
5760       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5761       goto next;
5762     }
5763   }
5764
5765   GST_DEBUG_OBJECT (qtdemux,
5766       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5767       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5768       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5769       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5770
5771   if (G_UNLIKELY (empty)) {
5772     /* empty segment, push a gap and move to the next one */
5773     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5774     stream->segment.position = pts + duration;
5775     goto next;
5776   }
5777
5778   /* hmm, empty sample, skip and move to next sample */
5779   if (G_UNLIKELY (sample_size <= 0))
5780     goto next;
5781
5782   /* last pushed sample was out of boundary, goto next sample */
5783   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5784     goto next;
5785
5786   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5787     size = sample_size;
5788   } else {
5789     GST_DEBUG_OBJECT (qtdemux,
5790         "size %d larger than stream max_buffer_size %d, trimming",
5791         sample_size, stream->max_buffer_size);
5792     size =
5793         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5794   }
5795
5796   if (qtdemux->cenc_aux_info_offset > 0) {
5797     GstMapInfo map;
5798     GstByteReader br;
5799     GstBuffer *aux_info = NULL;
5800
5801     /* pull the data stored before the sample */
5802     ret =
5803         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5804         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5805     if (G_UNLIKELY (ret != GST_FLOW_OK))
5806       goto beach;
5807     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5808     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5809     gst_byte_reader_init (&br, map.data + 8, map.size);
5810     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5811             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5812       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5813       gst_buffer_unmap (aux_info, &map);
5814       gst_buffer_unref (aux_info);
5815       ret = GST_FLOW_ERROR;
5816       goto beach;
5817     }
5818     gst_buffer_unmap (aux_info, &map);
5819     gst_buffer_unref (aux_info);
5820   }
5821
5822   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5823       offset);
5824
5825   if (stream->use_allocator) {
5826     /* if we have a per-stream allocator, use it */
5827     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5828   }
5829
5830   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5831       size, &buf);
5832   if (G_UNLIKELY (ret != GST_FLOW_OK))
5833     goto beach;
5834
5835   if (size != sample_size) {
5836     pts += gst_util_uint64_scale_int (GST_SECOND,
5837         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5838         stream->timescale);
5839     dts +=
5840         gst_util_uint64_scale_int (GST_SECOND,
5841         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5842         stream->timescale);
5843     duration =
5844         gst_util_uint64_scale_int (GST_SECOND,
5845         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5846   }
5847
5848   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5849       dts, pts, duration, keyframe, min_time, offset);
5850
5851   if (size != sample_size) {
5852     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5853     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5854
5855     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5856         sample->timestamp +
5857         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5858     if (time_position >= segment->media_start) {
5859       /* inside the segment, update time_position, looks very familiar to
5860        * GStreamer segments, doesn't it? */
5861       stream->time_position = (time_position - segment->media_start) +
5862           segment->time;
5863     } else {
5864       /* not yet in segment, time does not yet increment. This means
5865        * that we are still prerolling keyframes to the decoder so it can
5866        * decode the first sample of the segment. */
5867       stream->time_position = segment->time;
5868     }
5869   }
5870
5871   /* combine flows */
5872   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5873   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5874    * we have no more data for the pad to push */
5875   if (ret == GST_FLOW_EOS)
5876     ret = GST_FLOW_OK;
5877
5878   stream->offset_in_sample += size;
5879   if (stream->offset_in_sample >= sample_size) {
5880     gst_qtdemux_advance_sample (qtdemux, stream);
5881   }
5882   goto beach;
5883
5884 next:
5885   gst_qtdemux_advance_sample (qtdemux, stream);
5886
5887 beach:
5888   return ret;
5889
5890   /* special cases */
5891 eos:
5892   {
5893     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5894     ret = GST_FLOW_EOS;
5895     goto beach;
5896   }
5897 eos_stream:
5898   {
5899     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5900     /* EOS will be raised if all are EOS */
5901     ret = GST_FLOW_OK;
5902     goto beach;
5903   }
5904 }
5905
5906 static void
5907 gst_qtdemux_loop (GstPad * pad)
5908 {
5909   GstQTDemux *qtdemux;
5910   guint64 cur_offset;
5911   GstFlowReturn ret;
5912
5913   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5914
5915   cur_offset = qtdemux->offset;
5916   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5917       cur_offset, qt_demux_state_string (qtdemux->state));
5918
5919   switch (qtdemux->state) {
5920     case QTDEMUX_STATE_INITIAL:
5921     case QTDEMUX_STATE_HEADER:
5922       ret = gst_qtdemux_loop_state_header (qtdemux);
5923       break;
5924     case QTDEMUX_STATE_MOVIE:
5925       ret = gst_qtdemux_loop_state_movie (qtdemux);
5926       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5927         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5928       }
5929       break;
5930     default:
5931       /* ouch */
5932       goto invalid_state;
5933   }
5934
5935   /* if something went wrong, pause */
5936   if (ret != GST_FLOW_OK)
5937     goto pause;
5938
5939 done:
5940   gst_object_unref (qtdemux);
5941   return;
5942
5943   /* ERRORS */
5944 invalid_state:
5945   {
5946     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5947         (NULL), ("streaming stopped, invalid state"));
5948     gst_pad_pause_task (pad);
5949     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5950     goto done;
5951   }
5952 pause:
5953   {
5954     const gchar *reason = gst_flow_get_name (ret);
5955
5956     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5957
5958     gst_pad_pause_task (pad);
5959
5960     /* fatal errors need special actions */
5961     /* check EOS */
5962     if (ret == GST_FLOW_EOS) {
5963       if (qtdemux->n_streams == 0) {
5964         /* we have no streams, post an error */
5965         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5966       }
5967       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5968         gint64 stop;
5969
5970         if ((stop = qtdemux->segment.stop) == -1)
5971           stop = qtdemux->segment.duration;
5972
5973         if (qtdemux->segment.rate >= 0) {
5974           GstMessage *message;
5975           GstEvent *event;
5976
5977           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5978           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5979               GST_FORMAT_TIME, stop);
5980           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5981           if (qtdemux->segment_seqnum) {
5982             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5983             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5984           }
5985           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5986           gst_qtdemux_push_event (qtdemux, event);
5987         } else {
5988           GstMessage *message;
5989           GstEvent *event;
5990
5991           /*  For Reverse Playback */
5992           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5993           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5994               GST_FORMAT_TIME, qtdemux->segment.start);
5995           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5996               qtdemux->segment.start);
5997           if (qtdemux->segment_seqnum) {
5998             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5999             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6000           }
6001           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6002           gst_qtdemux_push_event (qtdemux, event);
6003         }
6004       } else {
6005         GstEvent *event;
6006
6007         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6008         event = gst_event_new_eos ();
6009         if (qtdemux->segment_seqnum)
6010           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6011         gst_qtdemux_push_event (qtdemux, event);
6012       }
6013     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6014       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6015       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6016     }
6017     goto done;
6018   }
6019 }
6020
6021 /*
6022  * has_next_entry
6023  *
6024  * Returns if there are samples to be played.
6025  */
6026 static gboolean
6027 has_next_entry (GstQTDemux * demux)
6028 {
6029   QtDemuxStream *stream;
6030   int i;
6031
6032   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6033
6034   for (i = 0; i < demux->n_streams; i++) {
6035     stream = demux->streams[i];
6036
6037     if (stream->sample_index == -1) {
6038       stream->sample_index = 0;
6039       stream->offset_in_sample = 0;
6040     }
6041
6042     if (stream->sample_index >= stream->n_samples) {
6043       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6044       continue;
6045     }
6046     GST_DEBUG_OBJECT (demux, "Found a sample");
6047     return TRUE;
6048   }
6049
6050   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6051   return FALSE;
6052 }
6053
6054 /*
6055  * next_entry_size
6056  *
6057  * Returns the size of the first entry at the current offset.
6058  * If -1, there are none (which means EOS or empty file).
6059  */
6060 static guint64
6061 next_entry_size (GstQTDemux * demux)
6062 {
6063   QtDemuxStream *stream;
6064   int i;
6065   int smallidx = -1;
6066   guint64 smalloffs = (guint64) - 1;
6067   QtDemuxSample *sample;
6068
6069   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6070       demux->offset);
6071
6072   for (i = 0; i < demux->n_streams; i++) {
6073     stream = demux->streams[i];
6074
6075     if (stream->sample_index == -1) {
6076       stream->sample_index = 0;
6077       stream->offset_in_sample = 0;
6078     }
6079
6080     if (stream->sample_index >= stream->n_samples) {
6081       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6082       continue;
6083     }
6084
6085     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6086       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6087           stream->sample_index);
6088       return -1;
6089     }
6090
6091     sample = &stream->samples[stream->sample_index];
6092
6093     GST_LOG_OBJECT (demux,
6094         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6095         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6096         sample->offset, sample->size);
6097
6098     if (((smalloffs == -1)
6099             || (sample->offset < smalloffs)) && (sample->size)) {
6100       smallidx = i;
6101       smalloffs = sample->offset;
6102     }
6103   }
6104
6105   GST_LOG_OBJECT (demux,
6106       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6107       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6108
6109   if (smallidx == -1)
6110     return -1;
6111
6112   stream = demux->streams[smallidx];
6113   sample = &stream->samples[stream->sample_index];
6114
6115   if (sample->offset >= demux->offset) {
6116     demux->todrop = sample->offset - demux->offset;
6117     return sample->size + demux->todrop;
6118   }
6119
6120   GST_DEBUG_OBJECT (demux,
6121       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6122   return -1;
6123 }
6124
6125 static void
6126 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6127 {
6128   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6129
6130   gst_element_post_message (GST_ELEMENT_CAST (demux),
6131       gst_message_new_element (GST_OBJECT_CAST (demux),
6132           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6133 }
6134
6135 static gboolean
6136 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6137 {
6138   GstEvent *event;
6139   gboolean res = 0;
6140
6141   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6142
6143   event =
6144       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6145       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6146       GST_SEEK_TYPE_NONE, -1);
6147
6148   /* store seqnum to drop flush events, they don't need to reach downstream */
6149   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6150   res = gst_pad_push_event (demux->sinkpad, event);
6151   demux->offset_seek_seqnum = 0;
6152
6153   return res;
6154 }
6155
6156 /* check for seekable upstream, above and beyond a mere query */
6157 static void
6158 gst_qtdemux_check_seekability (GstQTDemux * demux)
6159 {
6160   GstQuery *query;
6161   gboolean seekable = FALSE;
6162   gint64 start = -1, stop = -1;
6163
6164   if (demux->upstream_size)
6165     return;
6166
6167   if (demux->upstream_format_is_time)
6168     return;
6169
6170   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6171   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6172     GST_DEBUG_OBJECT (demux, "seeking query failed");
6173     goto done;
6174   }
6175
6176   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6177
6178   /* try harder to query upstream size if we didn't get it the first time */
6179   if (seekable && stop == -1) {
6180     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6181     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6182   }
6183
6184   /* if upstream doesn't know the size, it's likely that it's not seekable in
6185    * practice even if it technically may be seekable */
6186   if (seekable && (start != 0 || stop <= start)) {
6187     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6188     seekable = FALSE;
6189   }
6190
6191 done:
6192   gst_query_unref (query);
6193
6194   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6195       G_GUINT64_FORMAT ")", seekable, start, stop);
6196   demux->upstream_seekable = seekable;
6197   demux->upstream_size = seekable ? stop : -1;
6198 }
6199
6200 static void
6201 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6202 {
6203   g_return_if_fail (bytes <= demux->todrop);
6204
6205   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6206   gst_adapter_flush (demux->adapter, bytes);
6207   demux->neededbytes -= bytes;
6208   demux->offset += bytes;
6209   demux->todrop -= bytes;
6210 }
6211
6212 static void
6213 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6214 {
6215   if (G_UNLIKELY (demux->pending_newsegment)) {
6216     gint i;
6217
6218     gst_qtdemux_push_pending_newsegment (demux);
6219     /* clear to send tags on all streams */
6220     for (i = 0; i < demux->n_streams; i++) {
6221       QtDemuxStream *stream;
6222       stream = demux->streams[i];
6223       gst_qtdemux_push_tags (demux, stream);
6224       if (CUR_STREAM (stream)->sparse) {
6225         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6226         gst_pad_push_event (stream->pad,
6227             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6228       }
6229     }
6230   }
6231 }
6232
6233 static void
6234 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6235     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6236 {
6237   GstClockTime ts, dur;
6238   GstEvent *gap;
6239
6240   ts = pos;
6241   dur =
6242       stream->segments[segment_index].duration - (pos -
6243       stream->segments[segment_index].time);
6244   gap = gst_event_new_gap (ts, dur);
6245   stream->time_position += dur;
6246
6247   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6248       "segment: %" GST_PTR_FORMAT, gap);
6249   gst_pad_push_event (stream->pad, gap);
6250 }
6251
6252 static void
6253 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6254     QtDemuxStream * stream)
6255 {
6256   gint i;
6257
6258   /* Push any initial gap segments before proceeding to the
6259    * 'real' data */
6260   for (i = 0; i < stream->n_segments; i++) {
6261     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6262
6263     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6264       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6265           stream->time_position);
6266     } else {
6267       /* Only support empty segment at the beginning followed by
6268        * one non-empty segment, this was checked when parsing the
6269        * edts atom, arriving here is unexpected */
6270       g_assert (i + 1 == stream->n_segments);
6271       break;
6272     }
6273   }
6274 }
6275
6276 static GstFlowReturn
6277 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6278 {
6279   GstQTDemux *demux;
6280
6281   demux = GST_QTDEMUX (parent);
6282
6283   GST_DEBUG_OBJECT (demux,
6284       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6285       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6286       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6287       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6288       gst_buffer_get_size (inbuf), demux->offset);
6289
6290   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6291     gboolean is_gap_input = FALSE;
6292     gint i;
6293
6294     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6295
6296     for (i = 0; i < demux->n_streams; i++) {
6297       demux->streams[i]->discont = TRUE;
6298     }
6299
6300     /* Check if we can land back on our feet in the case where upstream is
6301      * handling the seeking/pushing of samples with gaps in between (like
6302      * in the case of trick-mode DASH for example) */
6303     if (demux->upstream_format_is_time
6304         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6305       gint i;
6306       for (i = 0; i < demux->n_streams; i++) {
6307         guint32 res;
6308         GST_LOG_OBJECT (demux,
6309             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6310             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6311         res =
6312             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6313             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6314         if (res != -1) {
6315           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6316           GST_LOG_OBJECT (demux,
6317               "Checking if sample %d from stream %d is valid (offset:%"
6318               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6319               sample->offset, sample->size);
6320           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6321             GST_LOG_OBJECT (demux,
6322                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6323                 res);
6324             is_gap_input = TRUE;
6325             /* We can go back to standard playback mode */
6326             demux->state = QTDEMUX_STATE_MOVIE;
6327             /* Remember which sample this stream is at */
6328             demux->streams[i]->sample_index = res;
6329             /* Finally update all push-based values to the expected values */
6330             demux->neededbytes = demux->streams[i]->samples[res].size;
6331             demux->offset = GST_BUFFER_OFFSET (inbuf);
6332             demux->mdatleft =
6333                 demux->mdatsize - demux->offset + demux->mdatoffset;
6334             demux->todrop = 0;
6335           }
6336         }
6337       }
6338       if (!is_gap_input) {
6339         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6340         /* Reset state if it's a real discont */
6341         demux->neededbytes = 16;
6342         demux->state = QTDEMUX_STATE_INITIAL;
6343         demux->offset = GST_BUFFER_OFFSET (inbuf);
6344         gst_adapter_clear (demux->adapter);
6345       }
6346     }
6347     /* Reverse fragmented playback, need to flush all we have before
6348      * consuming a new fragment.
6349      * The samples array have the timestamps calculated by accumulating the
6350      * durations but this won't work for reverse playback of fragments as
6351      * the timestamps of a subsequent fragment should be smaller than the
6352      * previously received one. */
6353     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6354       gst_qtdemux_process_adapter (demux, TRUE);
6355       for (i = 0; i < demux->n_streams; i++)
6356         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6357     }
6358   }
6359
6360   gst_adapter_push (demux->adapter, inbuf);
6361
6362   GST_DEBUG_OBJECT (demux,
6363       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6364       demux->neededbytes, gst_adapter_available (demux->adapter));
6365
6366   return gst_qtdemux_process_adapter (demux, FALSE);
6367 }
6368
6369 static GstFlowReturn
6370 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6371 {
6372   GstFlowReturn ret = GST_FLOW_OK;
6373
6374   /* we never really mean to buffer that much */
6375   if (demux->neededbytes == -1) {
6376     goto eos;
6377   }
6378
6379   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6380       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6381
6382 #ifndef GST_DISABLE_GST_DEBUG
6383     {
6384       guint64 discont_offset, distance_from_discont;
6385
6386       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6387       distance_from_discont =
6388           gst_adapter_distance_from_discont (demux->adapter);
6389
6390       GST_DEBUG_OBJECT (demux,
6391           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6392           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6393           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6394           demux->offset, discont_offset, distance_from_discont);
6395     }
6396 #endif
6397
6398     switch (demux->state) {
6399       case QTDEMUX_STATE_INITIAL:{
6400         const guint8 *data;
6401         guint32 fourcc;
6402         guint64 size;
6403
6404         gst_qtdemux_check_seekability (demux);
6405
6406         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6407
6408         /* get fourcc/length, set neededbytes */
6409         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6410             &size, &fourcc);
6411         gst_adapter_unmap (demux->adapter);
6412         data = NULL;
6413         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6414             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6415         if (size == 0) {
6416           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6417               (_("This file is invalid and cannot be played.")),
6418               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6419                   GST_FOURCC_ARGS (fourcc)));
6420           ret = GST_FLOW_ERROR;
6421           break;
6422         }
6423         if (fourcc == FOURCC_mdat) {
6424           gint next_entry = next_entry_size (demux);
6425           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6426             /* we have the headers, start playback */
6427             demux->state = QTDEMUX_STATE_MOVIE;
6428             demux->neededbytes = next_entry;
6429             demux->mdatleft = size;
6430             demux->mdatsize = demux->mdatleft;
6431           } else {
6432             /* no headers yet, try to get them */
6433             guint bs;
6434             gboolean res;
6435             guint64 old, target;
6436
6437           buffer_data:
6438             old = demux->offset;
6439             target = old + size;
6440
6441             /* try to jump over the atom with a seek */
6442             /* only bother if it seems worth doing so,
6443              * and avoids possible upstream/server problems */
6444             if (demux->upstream_seekable &&
6445                 demux->upstream_size > 4 * (1 << 20)) {
6446               res = qtdemux_seek_offset (demux, target);
6447             } else {
6448               GST_DEBUG_OBJECT (demux, "skipping seek");
6449               res = FALSE;
6450             }
6451
6452             if (res) {
6453               GST_DEBUG_OBJECT (demux, "seek success");
6454               /* remember the offset fo the first mdat so we can seek back to it
6455                * after we have the headers */
6456               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6457                 demux->first_mdat = old;
6458                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6459                     demux->first_mdat);
6460               }
6461               /* seek worked, continue reading */
6462               demux->offset = target;
6463               demux->neededbytes = 16;
6464               demux->state = QTDEMUX_STATE_INITIAL;
6465             } else {
6466               /* seek failed, need to buffer */
6467               demux->offset = old;
6468               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6469               /* there may be multiple mdat (or alike) buffers */
6470               /* sanity check */
6471               if (demux->mdatbuffer)
6472                 bs = gst_buffer_get_size (demux->mdatbuffer);
6473               else
6474                 bs = 0;
6475               if (size + bs > 10 * (1 << 20))
6476                 goto no_moov;
6477               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6478               demux->neededbytes = size;
6479               if (!demux->mdatbuffer)
6480                 demux->mdatoffset = demux->offset;
6481             }
6482           }
6483         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6484           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6485               (_("This file is invalid and cannot be played.")),
6486               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6487                   GST_FOURCC_ARGS (fourcc), size));
6488           ret = GST_FLOW_ERROR;
6489           break;
6490         } else {
6491           /* this means we already started buffering and still no moov header,
6492            * let's continue buffering everything till we get moov */
6493           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6494                   || fourcc == FOURCC_moof))
6495             goto buffer_data;
6496           demux->neededbytes = size;
6497           demux->state = QTDEMUX_STATE_HEADER;
6498         }
6499         break;
6500       }
6501       case QTDEMUX_STATE_HEADER:{
6502         const guint8 *data;
6503         guint32 fourcc;
6504
6505         GST_DEBUG_OBJECT (demux, "In header");
6506
6507         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6508
6509         /* parse the header */
6510         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6511             &fourcc);
6512         if (fourcc == FOURCC_moov) {
6513           gint n;
6514
6515           /* in usual fragmented setup we could try to scan for more
6516            * and end up at the the moov (after mdat) again */
6517           if (demux->got_moov && demux->n_streams > 0 &&
6518               (!demux->fragmented
6519                   || demux->last_moov_offset == demux->offset)) {
6520             GST_DEBUG_OBJECT (demux,
6521                 "Skipping moov atom as we have (this) one already");
6522           } else {
6523             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6524
6525             if (demux->got_moov && demux->fragmented) {
6526               GST_DEBUG_OBJECT (demux,
6527                   "Got a second moov, clean up data from old one");
6528               if (demux->moov_node_compressed) {
6529                 g_node_destroy (demux->moov_node_compressed);
6530                 if (demux->moov_node)
6531                   g_free (demux->moov_node->data);
6532               }
6533               demux->moov_node_compressed = NULL;
6534               if (demux->moov_node)
6535                 g_node_destroy (demux->moov_node);
6536               demux->moov_node = NULL;
6537             } else {
6538               /* prepare newsegment to send when streaming actually starts */
6539               if (!demux->pending_newsegment) {
6540                 demux->pending_newsegment =
6541                     gst_event_new_segment (&demux->segment);
6542                 if (demux->segment_seqnum)
6543                   gst_event_set_seqnum (demux->pending_newsegment,
6544                       demux->segment_seqnum);
6545               }
6546             }
6547
6548             demux->last_moov_offset = demux->offset;
6549
6550             qtdemux_parse_moov (demux, data, demux->neededbytes);
6551             qtdemux_node_dump (demux, demux->moov_node);
6552             qtdemux_parse_tree (demux);
6553             qtdemux_prepare_streams (demux);
6554             if (!demux->got_moov)
6555               qtdemux_expose_streams (demux);
6556             else {
6557
6558               for (n = 0; n < demux->n_streams; n++) {
6559                 QtDemuxStream *stream = demux->streams[n];
6560
6561                 gst_qtdemux_configure_stream (demux, stream);
6562               }
6563             }
6564
6565             demux->got_moov = TRUE;
6566             gst_qtdemux_check_send_pending_segment (demux);
6567
6568             /* fragmented streams headers shouldn't contain edts atoms */
6569             if (!demux->fragmented) {
6570               for (n = 0; n < demux->n_streams; n++) {
6571                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6572                     demux->streams[n]);
6573               }
6574             }
6575
6576             if (demux->moov_node_compressed) {
6577               g_node_destroy (demux->moov_node_compressed);
6578               g_free (demux->moov_node->data);
6579             }
6580             demux->moov_node_compressed = NULL;
6581             g_node_destroy (demux->moov_node);
6582             demux->moov_node = NULL;
6583             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6584           }
6585         } else if (fourcc == FOURCC_moof) {
6586           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6587             guint64 dist = 0;
6588             GstClockTime prev_pts;
6589             guint64 prev_offset;
6590             guint64 adapter_discont_offset, adapter_discont_dist;
6591
6592             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6593
6594             /*
6595              * The timestamp of the moof buffer is relevant as some scenarios
6596              * won't have the initial timestamp in the atoms. Whenever a new
6597              * buffer has started, we get that buffer's PTS and use it as a base
6598              * timestamp for the trun entries.
6599              *
6600              * To keep track of the current buffer timestamp and starting point
6601              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6602              * from the beggining of the buffer, with the distance and demux->offset
6603              * we know if it is still the same buffer or not.
6604              */
6605             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6606             prev_offset = demux->offset - dist;
6607             if (demux->fragment_start_offset == -1
6608                 || prev_offset > demux->fragment_start_offset) {
6609               demux->fragment_start_offset = prev_offset;
6610               demux->fragment_start = prev_pts;
6611               GST_DEBUG_OBJECT (demux,
6612                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6613                   GST_TIME_FORMAT, demux->fragment_start_offset,
6614                   GST_TIME_ARGS (demux->fragment_start));
6615             }
6616
6617             /* We can't use prev_offset() here because this would require
6618              * upstream to set consistent and correct offsets on all buffers
6619              * since the discont. Nothing ever did that in the past and we
6620              * would break backwards compatibility here then.
6621              * Instead take the offset we had at the last discont and count
6622              * the bytes from there. This works with old code as there would
6623              * be no discont between moov and moof, and also works with
6624              * adaptivedemux which correctly sets offset and will set the
6625              * DISCONT flag accordingly when needed.
6626              *
6627              * We also only do this for upstream TIME segments as otherwise
6628              * there are potential backwards compatibility problems with
6629              * seeking in PUSH mode and upstream providing inconsistent
6630              * timestamps. */
6631             adapter_discont_offset =
6632                 gst_adapter_offset_at_discont (demux->adapter);
6633             adapter_discont_dist =
6634                 gst_adapter_distance_from_discont (demux->adapter);
6635
6636             GST_DEBUG_OBJECT (demux,
6637                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6638                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6639                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6640
6641             if (demux->upstream_format_is_time) {
6642               demux->moof_offset = adapter_discont_offset;
6643               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6644                 demux->moof_offset += adapter_discont_dist;
6645               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6646                 demux->moof_offset = demux->offset;
6647             } else {
6648               demux->moof_offset = demux->offset;
6649             }
6650
6651             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6652                     demux->moof_offset, NULL)) {
6653               gst_adapter_unmap (demux->adapter);
6654               ret = GST_FLOW_ERROR;
6655               goto done;
6656             }
6657             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6658             if (demux->mss_mode && !demux->exposed) {
6659               if (!demux->pending_newsegment) {
6660                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6661                 demux->pending_newsegment =
6662                     gst_event_new_segment (&demux->segment);
6663                 if (demux->segment_seqnum)
6664                   gst_event_set_seqnum (demux->pending_newsegment,
6665                       demux->segment_seqnum);
6666               }
6667               qtdemux_expose_streams (demux);
6668             }
6669           } else {
6670             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6671           }
6672         } else if (fourcc == FOURCC_ftyp) {
6673           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6674           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6675         } else if (fourcc == FOURCC_uuid) {
6676           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6677           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6678         } else if (fourcc == FOURCC_sidx) {
6679           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6680           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6681         } else {
6682           switch (fourcc) {
6683             case FOURCC_styp:
6684               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6685                * FALLTHROUGH */
6686             case FOURCC_free:
6687               /* [free] is a padding atom */
6688               GST_DEBUG_OBJECT (demux,
6689                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6690                   GST_FOURCC_ARGS (fourcc));
6691               break;
6692             default:
6693               GST_WARNING_OBJECT (demux,
6694                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6695                   GST_FOURCC_ARGS (fourcc));
6696               /* Let's jump that one and go back to initial state */
6697               break;
6698           }
6699         }
6700         gst_adapter_unmap (demux->adapter);
6701         data = NULL;
6702
6703         if (demux->mdatbuffer && demux->n_streams) {
6704           gsize remaining_data_size = 0;
6705
6706           /* the mdat was before the header */
6707           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6708               demux->n_streams, demux->mdatbuffer);
6709           /* restore our adapter/offset view of things with upstream;
6710            * put preceding buffered data ahead of current moov data.
6711            * This should also handle evil mdat, moov, mdat cases and alike */
6712           gst_adapter_flush (demux->adapter, demux->neededbytes);
6713
6714           /* Store any remaining data after the mdat for later usage */
6715           remaining_data_size = gst_adapter_available (demux->adapter);
6716           if (remaining_data_size > 0) {
6717             g_assert (demux->restoredata_buffer == NULL);
6718             demux->restoredata_buffer =
6719                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6720             demux->restoredata_offset = demux->offset + demux->neededbytes;
6721             GST_DEBUG_OBJECT (demux,
6722                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6723                 G_GUINT64_FORMAT, remaining_data_size,
6724                 demux->restoredata_offset);
6725           }
6726
6727           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6728           demux->mdatbuffer = NULL;
6729           demux->offset = demux->mdatoffset;
6730           demux->neededbytes = next_entry_size (demux);
6731           demux->state = QTDEMUX_STATE_MOVIE;
6732           demux->mdatleft = gst_adapter_available (demux->adapter);
6733           demux->mdatsize = demux->mdatleft;
6734         } else {
6735           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6736           gst_adapter_flush (demux->adapter, demux->neededbytes);
6737
6738           /* only go back to the mdat if there are samples to play */
6739           if (demux->got_moov && demux->first_mdat != -1
6740               && has_next_entry (demux)) {
6741             gboolean res;
6742
6743             /* we need to seek back */
6744             res = qtdemux_seek_offset (demux, demux->first_mdat);
6745             if (res) {
6746               demux->offset = demux->first_mdat;
6747             } else {
6748               GST_DEBUG_OBJECT (demux, "Seek back failed");
6749             }
6750           } else {
6751             demux->offset += demux->neededbytes;
6752           }
6753           demux->neededbytes = 16;
6754           demux->state = QTDEMUX_STATE_INITIAL;
6755         }
6756
6757         break;
6758       }
6759       case QTDEMUX_STATE_BUFFER_MDAT:{
6760         GstBuffer *buf;
6761         guint8 fourcc[4];
6762
6763         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6764             demux->offset);
6765         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6766         gst_buffer_extract (buf, 0, fourcc, 4);
6767         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6768             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6769         if (demux->mdatbuffer)
6770           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6771         else
6772           demux->mdatbuffer = buf;
6773         demux->offset += demux->neededbytes;
6774         demux->neededbytes = 16;
6775         demux->state = QTDEMUX_STATE_INITIAL;
6776         gst_qtdemux_post_progress (demux, 1, 1);
6777
6778         break;
6779       }
6780       case QTDEMUX_STATE_MOVIE:{
6781         QtDemuxStream *stream = NULL;
6782         QtDemuxSample *sample;
6783         int i = -1;
6784         GstClockTime dts, pts, duration;
6785         gboolean keyframe;
6786
6787         GST_DEBUG_OBJECT (demux,
6788             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6789
6790         if (demux->fragmented) {
6791           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6792               demux->mdatleft);
6793           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6794             /* if needed data starts within this atom,
6795              * then it should not exceed this atom */
6796             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6797               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6798                   (_("This file is invalid and cannot be played.")),
6799                   ("sample data crosses atom boundary"));
6800               ret = GST_FLOW_ERROR;
6801               break;
6802             }
6803             demux->mdatleft -= demux->neededbytes;
6804           } else {
6805             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6806             /* so we are dropping more than left in this atom */
6807             gst_qtdemux_drop_data (demux, demux->mdatleft);
6808             demux->mdatleft = 0;
6809
6810             /* need to resume atom parsing so we do not miss any other pieces */
6811             demux->state = QTDEMUX_STATE_INITIAL;
6812             demux->neededbytes = 16;
6813
6814             /* check if there was any stored post mdat data from previous buffers */
6815             if (demux->restoredata_buffer) {
6816               g_assert (gst_adapter_available (demux->adapter) == 0);
6817
6818               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6819               demux->restoredata_buffer = NULL;
6820               demux->offset = demux->restoredata_offset;
6821             }
6822
6823             break;
6824           }
6825         }
6826
6827         if (demux->todrop) {
6828           if (demux->cenc_aux_info_offset > 0) {
6829             GstByteReader br;
6830             const guint8 *data;
6831
6832             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6833             data = gst_adapter_map (demux->adapter, demux->todrop);
6834             gst_byte_reader_init (&br, data + 8, demux->todrop);
6835             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6836                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6837               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6838               ret = GST_FLOW_ERROR;
6839               gst_adapter_unmap (demux->adapter);
6840               g_free (demux->cenc_aux_info_sizes);
6841               demux->cenc_aux_info_sizes = NULL;
6842               goto done;
6843             }
6844             demux->cenc_aux_info_offset = 0;
6845             g_free (demux->cenc_aux_info_sizes);
6846             demux->cenc_aux_info_sizes = NULL;
6847             gst_adapter_unmap (demux->adapter);
6848           }
6849           gst_qtdemux_drop_data (demux, demux->todrop);
6850         }
6851
6852         /* first buffer? */
6853         /* initial newsegment sent here after having added pads,
6854          * possible others in sink_event */
6855         gst_qtdemux_check_send_pending_segment (demux);
6856
6857         /* Figure out which stream this packet belongs to */
6858         for (i = 0; i < demux->n_streams; i++) {
6859           stream = demux->streams[i];
6860           if (stream->sample_index >= stream->n_samples)
6861             continue;
6862           GST_LOG_OBJECT (demux,
6863               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6864               " / size:%d)", i, stream->sample_index,
6865               stream->samples[stream->sample_index].offset,
6866               stream->samples[stream->sample_index].size);
6867
6868           if (stream->samples[stream->sample_index].offset == demux->offset)
6869             break;
6870         }
6871
6872         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6873           goto unknown_stream;
6874
6875         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6876
6877         if (stream->new_caps) {
6878           gst_qtdemux_configure_stream (demux, stream);
6879         }
6880
6881         /* Put data in a buffer, set timestamps, caps, ... */
6882         sample = &stream->samples[stream->sample_index];
6883
6884         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6885           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6886               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6887
6888           dts = QTSAMPLE_DTS (stream, sample);
6889           pts = QTSAMPLE_PTS (stream, sample);
6890           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6891           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6892
6893           /* check for segment end */
6894           if (G_UNLIKELY (demux->segment.stop != -1
6895                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6896             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6897             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6898
6899             /* skip this data, stream is EOS */
6900             gst_adapter_flush (demux->adapter, demux->neededbytes);
6901             demux->offset += demux->neededbytes;
6902
6903             /* check if all streams are eos */
6904             ret = GST_FLOW_EOS;
6905             for (i = 0; i < demux->n_streams; i++) {
6906               if (!STREAM_IS_EOS (demux->streams[i])) {
6907                 ret = GST_FLOW_OK;
6908                 break;
6909               }
6910             }
6911           } else {
6912             GstBuffer *outbuf;
6913
6914             outbuf =
6915                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6916
6917             /* FIXME: should either be an assert or a plain check */
6918             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6919
6920             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6921                 dts, pts, duration, keyframe, dts, demux->offset);
6922           }
6923
6924           /* combine flows */
6925           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6926         } else {
6927           /* skip this data, stream is EOS */
6928           gst_adapter_flush (demux->adapter, demux->neededbytes);
6929         }
6930
6931         stream->sample_index++;
6932         stream->offset_in_sample = 0;
6933
6934         /* update current offset and figure out size of next buffer */
6935         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6936             demux->offset, demux->neededbytes);
6937         demux->offset += demux->neededbytes;
6938         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6939             demux->offset);
6940
6941
6942         if (ret == GST_FLOW_EOS) {
6943           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6944           demux->neededbytes = -1;
6945           goto eos;
6946         }
6947
6948         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6949           if (demux->fragmented) {
6950             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6951             /* there may be more to follow, only finish this atom */
6952             demux->todrop = demux->mdatleft;
6953             demux->neededbytes = demux->todrop;
6954             break;
6955           }
6956           goto eos;
6957         }
6958         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
6959           goto non_ok_unlinked_flow;
6960         }
6961         break;
6962       }
6963       default:
6964         goto invalid_state;
6965     }
6966   }
6967
6968   /* when buffering movie data, at least show user something is happening */
6969   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6970       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6971     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6972         demux->neededbytes);
6973   }
6974 done:
6975
6976   return ret;
6977
6978   /* ERRORS */
6979 non_ok_unlinked_flow:
6980   {
6981     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6982         gst_flow_get_name (ret));
6983     return ret;
6984   }
6985 unknown_stream:
6986   {
6987     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6988     ret = GST_FLOW_ERROR;
6989     goto done;
6990   }
6991 eos:
6992   {
6993     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6994     ret = GST_FLOW_EOS;
6995     goto done;
6996   }
6997 invalid_state:
6998   {
6999     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7000         (NULL), ("qtdemuxer invalid state %d", demux->state));
7001     ret = GST_FLOW_ERROR;
7002     goto done;
7003   }
7004 no_moov:
7005   {
7006     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7007         (NULL), ("no 'moov' atom within the first 10 MB"));
7008     ret = GST_FLOW_ERROR;
7009     goto done;
7010   }
7011 }
7012
7013 static gboolean
7014 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7015 {
7016   GstQuery *query;
7017   gboolean pull_mode;
7018
7019   query = gst_query_new_scheduling ();
7020
7021   if (!gst_pad_peer_query (sinkpad, query)) {
7022     gst_query_unref (query);
7023     goto activate_push;
7024   }
7025
7026   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7027       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7028   gst_query_unref (query);
7029
7030   if (!pull_mode)
7031     goto activate_push;
7032
7033   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7034   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7035
7036 activate_push:
7037   {
7038     GST_DEBUG_OBJECT (sinkpad, "activating push");
7039     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7040   }
7041 }
7042
7043 static gboolean
7044 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7045     GstPadMode mode, gboolean active)
7046 {
7047   gboolean res;
7048   GstQTDemux *demux = GST_QTDEMUX (parent);
7049
7050   switch (mode) {
7051     case GST_PAD_MODE_PUSH:
7052       demux->pullbased = FALSE;
7053       res = TRUE;
7054       break;
7055     case GST_PAD_MODE_PULL:
7056       if (active) {
7057         demux->pullbased = TRUE;
7058         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7059             sinkpad, NULL);
7060       } else {
7061         res = gst_pad_stop_task (sinkpad);
7062       }
7063       break;
7064     default:
7065       res = FALSE;
7066       break;
7067   }
7068   return res;
7069 }
7070
7071 #ifdef HAVE_ZLIB
7072 static void *
7073 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7074 {
7075   guint8 *buffer;
7076   z_stream z;
7077   int ret;
7078
7079   memset (&z, 0, sizeof (z));
7080   z.zalloc = NULL;
7081   z.zfree = NULL;
7082   z.opaque = NULL;
7083
7084   if ((ret = inflateInit (&z)) != Z_OK) {
7085     GST_ERROR ("inflateInit() returned %d", ret);
7086     return NULL;
7087   }
7088
7089   z.next_in = z_buffer;
7090   z.avail_in = z_length;
7091
7092   buffer = (guint8 *) g_malloc (*length);
7093   z.avail_out = *length;
7094   z.next_out = (Bytef *) buffer;
7095   do {
7096     ret = inflate (&z, Z_NO_FLUSH);
7097     if (ret == Z_STREAM_END) {
7098       break;
7099     } else if (ret != Z_OK) {
7100       GST_WARNING ("inflate() returned %d", ret);
7101       break;
7102     }
7103
7104     *length += 4096;
7105     buffer = (guint8 *) g_realloc (buffer, *length);
7106     z.next_out = (Bytef *) (buffer + z.total_out);
7107     z.avail_out += 4096;
7108   } while (z.avail_in > 0);
7109
7110   if (ret != Z_STREAM_END) {
7111     g_free (buffer);
7112     buffer = NULL;
7113     *length = 0;
7114   } else {
7115     *length = z.total_out;
7116   }
7117
7118   inflateEnd (&z);
7119
7120   return buffer;
7121 }
7122 #endif /* HAVE_ZLIB */
7123
7124 static gboolean
7125 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7126 {
7127   GNode *cmov;
7128
7129   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7130
7131   /* counts as header data */
7132   qtdemux->header_size += length;
7133
7134   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7135   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7136
7137   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7138   if (cmov) {
7139     guint32 method;
7140     GNode *dcom;
7141     GNode *cmvd;
7142     guint32 dcom_len;
7143
7144     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7145     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7146     if (dcom == NULL || cmvd == NULL)
7147       goto invalid_compression;
7148
7149     dcom_len = QT_UINT32 (dcom->data);
7150     if (dcom_len < 12)
7151       goto invalid_compression;
7152
7153     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7154     switch (method) {
7155 #ifdef HAVE_ZLIB
7156       case FOURCC_zlib:{
7157         guint uncompressed_length;
7158         guint compressed_length;
7159         guint8 *buf;
7160         guint32 cmvd_len;
7161
7162         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7163         if (cmvd_len < 12)
7164           goto invalid_compression;
7165
7166         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7167         compressed_length = cmvd_len - 12;
7168         GST_LOG ("length = %u", uncompressed_length);
7169
7170         buf =
7171             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7172             compressed_length, &uncompressed_length);
7173
7174         if (buf) {
7175           qtdemux->moov_node_compressed = qtdemux->moov_node;
7176           qtdemux->moov_node = g_node_new (buf);
7177
7178           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7179               uncompressed_length);
7180         }
7181         break;
7182       }
7183 #endif /* HAVE_ZLIB */
7184       default:
7185         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7186             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7187         break;
7188     }
7189   }
7190   return TRUE;
7191
7192   /* ERRORS */
7193 invalid_compression:
7194   {
7195     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7196     return FALSE;
7197   }
7198 }
7199
7200 static gboolean
7201 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7202     const guint8 * end)
7203 {
7204   while (G_UNLIKELY (buf < end)) {
7205     GNode *child;
7206     guint32 len;
7207
7208     if (G_UNLIKELY (buf + 4 > end)) {
7209       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7210       break;
7211     }
7212     len = QT_UINT32 (buf);
7213     if (G_UNLIKELY (len == 0)) {
7214       GST_LOG_OBJECT (qtdemux, "empty container");
7215       break;
7216     }
7217     if (G_UNLIKELY (len < 8)) {
7218       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7219       break;
7220     }
7221     if (G_UNLIKELY (len > (end - buf))) {
7222       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7223           (gint) (end - buf));
7224       break;
7225     }
7226
7227     child = g_node_new ((guint8 *) buf);
7228     g_node_append (node, child);
7229     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7230     qtdemux_parse_node (qtdemux, child, buf, len);
7231
7232     buf += len;
7233   }
7234   return TRUE;
7235 }
7236
7237 static gboolean
7238 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7239     GNode * xdxt)
7240 {
7241   int len = QT_UINT32 (xdxt->data);
7242   guint8 *buf = xdxt->data;
7243   guint8 *end = buf + len;
7244   GstBuffer *buffer;
7245
7246   /* skip size and type */
7247   buf += 8;
7248   end -= 8;
7249
7250   while (buf < end) {
7251     gint size;
7252     guint32 type;
7253
7254     size = QT_UINT32 (buf);
7255     type = QT_FOURCC (buf + 4);
7256
7257     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7258
7259     if (buf + size > end || size <= 0)
7260       break;
7261
7262     buf += 8;
7263     size -= 8;
7264
7265     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7266         GST_FOURCC_ARGS (type));
7267
7268     switch (type) {
7269       case FOURCC_tCtH:
7270         buffer = gst_buffer_new_and_alloc (size);
7271         gst_buffer_fill (buffer, 0, buf, size);
7272         stream->buffers = g_slist_append (stream->buffers, buffer);
7273         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7274         break;
7275       case FOURCC_tCt_:
7276         buffer = gst_buffer_new_and_alloc (size);
7277         gst_buffer_fill (buffer, 0, buf, size);
7278         stream->buffers = g_slist_append (stream->buffers, buffer);
7279         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7280         break;
7281       case FOURCC_tCtC:
7282         buffer = gst_buffer_new_and_alloc (size);
7283         gst_buffer_fill (buffer, 0, buf, size);
7284         stream->buffers = g_slist_append (stream->buffers, buffer);
7285         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7286         break;
7287       default:
7288         GST_WARNING_OBJECT (qtdemux,
7289             "unknown theora cookie %" GST_FOURCC_FORMAT,
7290             GST_FOURCC_ARGS (type));
7291         break;
7292     }
7293     buf += size;
7294   }
7295   return TRUE;
7296 }
7297
7298 static gboolean
7299 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7300     guint length)
7301 {
7302   guint32 fourcc = 0;
7303   guint32 node_length = 0;
7304   const QtNodeType *type;
7305   const guint8 *end;
7306
7307   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7308
7309   if (G_UNLIKELY (length < 8))
7310     goto not_enough_data;
7311
7312   node_length = QT_UINT32 (buffer);
7313   fourcc = QT_FOURCC (buffer + 4);
7314
7315   /* ignore empty nodes */
7316   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7317     return TRUE;
7318
7319   type = qtdemux_type_get (fourcc);
7320
7321   end = buffer + length;
7322
7323   GST_LOG_OBJECT (qtdemux,
7324       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7325       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7326
7327   if (node_length > length)
7328     goto broken_atom_size;
7329
7330   if (type->flags & QT_FLAG_CONTAINER) {
7331     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7332   } else {
7333     switch (fourcc) {
7334       case FOURCC_stsd:
7335       {
7336         if (node_length < 20) {
7337           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7338           break;
7339         }
7340         GST_DEBUG_OBJECT (qtdemux,
7341             "parsing stsd (sample table, sample description) atom");
7342         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7343         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7344         break;
7345       }
7346       case FOURCC_mp4a:
7347       case FOURCC_alac:
7348       case FOURCC_fLaC:
7349       {
7350         guint32 version;
7351         guint32 offset;
7352         guint min_size;
7353
7354         /* also read alac (or whatever) in stead of mp4a in the following,
7355          * since a similar layout is used in other cases as well */
7356         if (fourcc == FOURCC_mp4a)
7357           min_size = 20;
7358         else if (fourcc == FOURCC_fLaC)
7359           min_size = 86;
7360         else
7361           min_size = 40;
7362
7363         /* There are two things we might encounter here: a true mp4a atom, and
7364            an mp4a entry in an stsd atom. The latter is what we're interested
7365            in, and it looks like an atom, but isn't really one. The true mp4a
7366            atom is short, so we detect it based on length here. */
7367         if (length < min_size) {
7368           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7369               GST_FOURCC_ARGS (fourcc));
7370           break;
7371         }
7372
7373         /* 'version' here is the sound sample description version. Types 0 and
7374            1 are documented in the QTFF reference, but type 2 is not: it's
7375            described in Apple header files instead (struct SoundDescriptionV2
7376            in Movies.h) */
7377         version = QT_UINT16 (buffer + 16);
7378
7379         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7380             GST_FOURCC_ARGS (fourcc), version);
7381
7382         /* parse any esds descriptors */
7383         switch (version) {
7384           case 0:
7385             offset = 0x24;
7386             break;
7387           case 1:
7388             offset = 0x34;
7389             break;
7390           case 2:
7391             offset = 0x48;
7392             break;
7393           default:
7394             GST_WARNING_OBJECT (qtdemux,
7395                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7396                 GST_FOURCC_ARGS (fourcc), version);
7397             offset = 0;
7398             break;
7399         }
7400         if (offset)
7401           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7402         break;
7403       }
7404       case FOURCC_mp4v:
7405       case FOURCC_MP4V:
7406       case FOURCC_fmp4:
7407       case FOURCC_FMP4:
7408       case FOURCC_apcs:
7409       case FOURCC_apch:
7410       case FOURCC_apcn:
7411       case FOURCC_apco:
7412       case FOURCC_ap4h:
7413       case FOURCC_xvid:
7414       case FOURCC_XVID:
7415       case FOURCC_H264:
7416       case FOURCC_avc1:
7417       case FOURCC_avc3:
7418       case FOURCC_H265:
7419       case FOURCC_hvc1:
7420       case FOURCC_hev1:
7421       case FOURCC_mjp2:
7422       case FOURCC_encv:
7423       {
7424         guint32 version;
7425         guint32 str_len;
7426
7427         /* codec_data is contained inside these atoms, which all have
7428          * the same format. */
7429         /* video sample description size is 86 bytes without extension.
7430          * node_length have to be bigger than 86 bytes because video sample
7431          * description can include extenstions such as esds, fiel, glbl, etc. */
7432         if (node_length < 86) {
7433           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7434               " sample description length too short (%u < 86)",
7435               GST_FOURCC_ARGS (fourcc), node_length);
7436           break;
7437         }
7438
7439         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7440             GST_FOURCC_ARGS (fourcc));
7441
7442         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7443          *              its data format.
7444          * revision level (2 bytes) : must be set to 0. */
7445         version = QT_UINT32 (buffer + 16);
7446         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7447
7448         /* compressor name : PASCAL string and informative purposes
7449          * first byte : the number of bytes to be displayed.
7450          *              it has to be less than 32 because it is reserved
7451          *              space of 32 bytes total including itself. */
7452         str_len = QT_UINT8 (buffer + 50);
7453         if (str_len < 32)
7454           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7455               (char *) buffer + 51);
7456         else
7457           GST_WARNING_OBJECT (qtdemux,
7458               "compressorname length too big (%u > 31)", str_len);
7459
7460         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7461             end - buffer);
7462         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7463         break;
7464       }
7465       case FOURCC_meta:
7466       {
7467         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7468         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7469         break;
7470       }
7471       case FOURCC_mp4s:
7472       {
7473         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7474         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7475         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7476         break;
7477       }
7478       case FOURCC_XiTh:
7479       {
7480         guint32 version;
7481         guint32 offset;
7482
7483         if (length < 16) {
7484           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7485               GST_FOURCC_ARGS (fourcc));
7486           break;
7487         }
7488
7489         version = QT_UINT32 (buffer + 12);
7490         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7491
7492         switch (version) {
7493           case 0x00000001:
7494             offset = 0x62;
7495             break;
7496           default:
7497             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7498             offset = 0;
7499             break;
7500         }
7501         if (offset) {
7502           if (length < offset) {
7503             GST_WARNING_OBJECT (qtdemux,
7504                 "skipping too small %" GST_FOURCC_FORMAT " box",
7505                 GST_FOURCC_ARGS (fourcc));
7506             break;
7507           }
7508           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7509         }
7510         break;
7511       }
7512       case FOURCC_in24:
7513       {
7514         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7515         break;
7516       }
7517       case FOURCC_uuid:
7518       {
7519         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7520         break;
7521       }
7522       case FOURCC_enca:
7523       {
7524         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7525         break;
7526       }
7527       default:
7528         if (!strcmp (type->name, "unknown"))
7529           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7530         break;
7531     }
7532   }
7533   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7534       GST_FOURCC_ARGS (fourcc));
7535   return TRUE;
7536
7537 /* ERRORS */
7538 not_enough_data:
7539   {
7540     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7541         (_("This file is corrupt and cannot be played.")),
7542         ("Not enough data for an atom header, got only %u bytes", length));
7543     return FALSE;
7544   }
7545 broken_atom_size:
7546   {
7547     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7548         (_("This file is corrupt and cannot be played.")),
7549         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7550             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7551             length));
7552     return FALSE;
7553   }
7554 }
7555
7556 static GNode *
7557 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7558 {
7559   GNode *child;
7560   guint8 *buffer;
7561   guint32 child_fourcc;
7562
7563   for (child = g_node_first_child (node); child;
7564       child = g_node_next_sibling (child)) {
7565     buffer = (guint8 *) child->data;
7566
7567     child_fourcc = QT_FOURCC (buffer + 4);
7568
7569     if (G_UNLIKELY (child_fourcc == fourcc)) {
7570       return child;
7571     }
7572   }
7573   return NULL;
7574 }
7575
7576 static GNode *
7577 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7578     GstByteReader * parser)
7579 {
7580   GNode *child;
7581   guint8 *buffer;
7582   guint32 child_fourcc, child_len;
7583
7584   for (child = g_node_first_child (node); child;
7585       child = g_node_next_sibling (child)) {
7586     buffer = (guint8 *) child->data;
7587
7588     child_len = QT_UINT32 (buffer);
7589     child_fourcc = QT_FOURCC (buffer + 4);
7590
7591     if (G_UNLIKELY (child_fourcc == fourcc)) {
7592       if (G_UNLIKELY (child_len < (4 + 4)))
7593         return NULL;
7594       /* FIXME: must verify if atom length < parent atom length */
7595       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7596       return child;
7597     }
7598   }
7599   return NULL;
7600 }
7601
7602 static GNode *
7603 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7604 {
7605   return g_node_nth_child (node, index);
7606 }
7607
7608 static GNode *
7609 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7610     GstByteReader * parser)
7611 {
7612   GNode *child;
7613   guint8 *buffer;
7614   guint32 child_fourcc, child_len;
7615
7616   for (child = g_node_next_sibling (node); child;
7617       child = g_node_next_sibling (child)) {
7618     buffer = (guint8 *) child->data;
7619
7620     child_fourcc = QT_FOURCC (buffer + 4);
7621
7622     if (child_fourcc == fourcc) {
7623       if (parser) {
7624         child_len = QT_UINT32 (buffer);
7625         if (G_UNLIKELY (child_len < (4 + 4)))
7626           return NULL;
7627         /* FIXME: must verify if atom length < parent atom length */
7628         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7629       }
7630       return child;
7631     }
7632   }
7633   return NULL;
7634 }
7635
7636 static GNode *
7637 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7638 {
7639   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7640 }
7641
7642 static void
7643 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7644 {
7645 /* FIXME: This can only reliably work if demuxers have a
7646  * separate streaming thread per srcpad. This should be
7647  * done in a demuxer base class, which integrates parts
7648  * of multiqueue
7649  *
7650  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7651  */
7652 #if 0
7653   GstQuery *query;
7654
7655   query = gst_query_new_allocation (stream->caps, FALSE);
7656
7657   if (!gst_pad_peer_query (stream->pad, query)) {
7658     /* not a problem, just debug a little */
7659     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7660   }
7661
7662   if (stream->allocator)
7663     gst_object_unref (stream->allocator);
7664
7665   if (gst_query_get_n_allocation_params (query) > 0) {
7666     /* try the allocator */
7667     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7668         &stream->params);
7669     stream->use_allocator = TRUE;
7670   } else {
7671     stream->allocator = NULL;
7672     gst_allocation_params_init (&stream->params);
7673     stream->use_allocator = FALSE;
7674   }
7675   gst_query_unref (query);
7676 #endif
7677 }
7678
7679 static gboolean
7680 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7681     QtDemuxStream * stream)
7682 {
7683   GstStructure *s;
7684   const gchar *selected_system;
7685
7686   g_return_val_if_fail (qtdemux != NULL, FALSE);
7687   g_return_val_if_fail (stream != NULL, FALSE);
7688   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7689       FALSE);
7690
7691   if (stream->protection_scheme_type != FOURCC_cenc) {
7692     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7693     return FALSE;
7694   }
7695   if (qtdemux->protection_system_ids == NULL) {
7696     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7697         "cenc protection system information has been found");
7698     return FALSE;
7699   }
7700   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7701   selected_system = gst_protection_select_system ((const gchar **)
7702       qtdemux->protection_system_ids->pdata);
7703   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7704       qtdemux->protection_system_ids->len - 1);
7705   if (!selected_system) {
7706     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7707         "suitable decryptor element has been found");
7708     return FALSE;
7709   }
7710
7711   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7712   if (!gst_structure_has_name (s, "application/x-cenc")) {
7713     gst_structure_set (s,
7714         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7715         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7716         NULL);
7717     gst_structure_set_name (s, "application/x-cenc");
7718   }
7719   return TRUE;
7720 }
7721
7722 static gboolean
7723 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7724 {
7725   if (stream->subtype == FOURCC_vide) {
7726     /* fps is calculated base on the duration of the average framerate since
7727      * qt does not have a fixed framerate. */
7728     gboolean fps_available = TRUE;
7729
7730     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7731       /* still frame */
7732       CUR_STREAM (stream)->fps_n = 0;
7733       CUR_STREAM (stream)->fps_d = 1;
7734     } else {
7735       if (stream->duration == 0 || stream->n_samples < 2) {
7736         CUR_STREAM (stream)->fps_n = stream->timescale;
7737         CUR_STREAM (stream)->fps_d = 1;
7738         fps_available = FALSE;
7739       } else {
7740         GstClockTime avg_duration;
7741         guint64 duration;
7742         guint32 n_samples;
7743
7744         /* duration and n_samples can be updated for fragmented format
7745          * so, framerate of fragmented format is calculated using data in a moof */
7746         if (qtdemux->fragmented && stream->n_samples_moof > 0
7747             && stream->duration_moof > 0) {
7748           n_samples = stream->n_samples_moof;
7749           duration = stream->duration_moof;
7750         } else {
7751           n_samples = stream->n_samples;
7752           duration = stream->duration;
7753         }
7754
7755         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7756         /* stream->duration is guint64, timescale, n_samples are guint32 */
7757         avg_duration =
7758             gst_util_uint64_scale_round (duration -
7759             stream->first_duration, GST_SECOND,
7760             (guint64) (stream->timescale) * (n_samples - 1));
7761
7762         GST_LOG_OBJECT (qtdemux,
7763             "Calculating avg sample duration based on stream (or moof) duration %"
7764             G_GUINT64_FORMAT
7765             " minus first sample %u, leaving %d samples gives %"
7766             GST_TIME_FORMAT, duration, stream->first_duration,
7767             n_samples - 1, GST_TIME_ARGS (avg_duration));
7768
7769         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7770             &CUR_STREAM (stream)->fps_d);
7771
7772         GST_DEBUG_OBJECT (qtdemux,
7773             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7774             stream->timescale, CUR_STREAM (stream)->fps_n,
7775             CUR_STREAM (stream)->fps_d);
7776       }
7777     }
7778
7779     if (CUR_STREAM (stream)->caps) {
7780       CUR_STREAM (stream)->caps =
7781           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7782
7783       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7784           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7785           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7786
7787       /* set framerate if calculated framerate is reliable */
7788       if (fps_available) {
7789         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7790             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7791             CUR_STREAM (stream)->fps_d, NULL);
7792       }
7793
7794       /* calculate pixel-aspect-ratio using display width and height */
7795       GST_DEBUG_OBJECT (qtdemux,
7796           "video size %dx%d, target display size %dx%d",
7797           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7798           stream->display_width, stream->display_height);
7799       /* qt file might have pasp atom */
7800       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7801         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7802             CUR_STREAM (stream)->par_h);
7803         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7804             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7805             CUR_STREAM (stream)->par_h, NULL);
7806       } else if (stream->display_width > 0 && stream->display_height > 0
7807           && CUR_STREAM (stream)->width > 0
7808           && CUR_STREAM (stream)->height > 0) {
7809         gint n, d;
7810
7811         /* calculate the pixel aspect ratio using the display and pixel w/h */
7812         n = stream->display_width * CUR_STREAM (stream)->height;
7813         d = stream->display_height * CUR_STREAM (stream)->width;
7814         if (n == d)
7815           n = d = 1;
7816         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7817         CUR_STREAM (stream)->par_w = n;
7818         CUR_STREAM (stream)->par_h = d;
7819         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7820             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7821             CUR_STREAM (stream)->par_h, NULL);
7822       }
7823
7824       if (CUR_STREAM (stream)->interlace_mode > 0) {
7825         if (CUR_STREAM (stream)->interlace_mode == 1) {
7826           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7827               G_TYPE_STRING, "progressive", NULL);
7828         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7829           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7830               G_TYPE_STRING, "interleaved", NULL);
7831           if (CUR_STREAM (stream)->field_order == 9) {
7832             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7833                 G_TYPE_STRING, "top-field-first", NULL);
7834           } else if (CUR_STREAM (stream)->field_order == 14) {
7835             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7836                 G_TYPE_STRING, "bottom-field-first", NULL);
7837           }
7838         }
7839       }
7840
7841       /* Create incomplete colorimetry here if needed */
7842       if (CUR_STREAM (stream)->colorimetry.range ||
7843           CUR_STREAM (stream)->colorimetry.matrix ||
7844           CUR_STREAM (stream)->colorimetry.transfer
7845           || CUR_STREAM (stream)->colorimetry.primaries) {
7846         gchar *colorimetry =
7847             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7848         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7849             G_TYPE_STRING, colorimetry, NULL);
7850         g_free (colorimetry);
7851       }
7852
7853       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7854         guint par_w = 1, par_h = 1;
7855
7856         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7857           par_w = CUR_STREAM (stream)->par_w;
7858           par_h = CUR_STREAM (stream)->par_h;
7859         }
7860
7861         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7862                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7863                 par_h)) {
7864           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7865         }
7866
7867         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7868             "multiview-mode", G_TYPE_STRING,
7869             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7870             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7871             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7872       }
7873     }
7874   }
7875
7876   else if (stream->subtype == FOURCC_soun) {
7877     if (CUR_STREAM (stream)->caps) {
7878       CUR_STREAM (stream)->caps =
7879           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7880       if (CUR_STREAM (stream)->rate > 0)
7881         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7882             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
7883       if (CUR_STREAM (stream)->n_channels > 0)
7884         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7885             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
7886       if (CUR_STREAM (stream)->n_channels > 2) {
7887         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7888          * correctly; this is just the minimum we can do - assume
7889          * we don't actually have any channel positions. */
7890         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7891             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7892       }
7893     }
7894   }
7895
7896   if (stream->pad) {
7897     GstCaps *prev_caps = NULL;
7898
7899     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7900     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7901     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7902     gst_pad_set_active (stream->pad, TRUE);
7903
7904     gst_pad_use_fixed_caps (stream->pad);
7905
7906     if (stream->protected) {
7907       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7908         GST_ERROR_OBJECT (qtdemux,
7909             "Failed to configure protected stream caps.");
7910         return FALSE;
7911       }
7912     }
7913
7914     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7915         CUR_STREAM (stream)->caps);
7916     if (stream->new_stream) {
7917       gchar *stream_id;
7918       GstEvent *event;
7919       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7920
7921       event =
7922           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7923           0);
7924       if (event) {
7925         gst_event_parse_stream_flags (event, &stream_flags);
7926         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7927           qtdemux->have_group_id = TRUE;
7928         else
7929           qtdemux->have_group_id = FALSE;
7930         gst_event_unref (event);
7931       } else if (!qtdemux->have_group_id) {
7932         qtdemux->have_group_id = TRUE;
7933         qtdemux->group_id = gst_util_group_id_next ();
7934       }
7935
7936       stream->new_stream = FALSE;
7937       stream_id =
7938           gst_pad_create_stream_id_printf (stream->pad,
7939           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7940       event = gst_event_new_stream_start (stream_id);
7941       if (qtdemux->have_group_id)
7942         gst_event_set_group_id (event, qtdemux->group_id);
7943       if (stream->disabled)
7944         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7945       if (CUR_STREAM (stream)->sparse) {
7946         stream_flags |= GST_STREAM_FLAG_SPARSE;
7947       } else {
7948         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
7949       }
7950       gst_event_set_stream_flags (event, stream_flags);
7951       gst_pad_push_event (stream->pad, event);
7952       g_free (stream_id);
7953     }
7954
7955     prev_caps = gst_pad_get_current_caps (stream->pad);
7956
7957     if (CUR_STREAM (stream)->caps) {
7958       if (!prev_caps
7959           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
7960         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7961             CUR_STREAM (stream)->caps);
7962         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
7963       } else {
7964         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7965       }
7966     } else {
7967       GST_WARNING_OBJECT (qtdemux, "stream without caps");
7968     }
7969
7970     if (prev_caps)
7971       gst_caps_unref (prev_caps);
7972     stream->new_caps = FALSE;
7973   }
7974   return TRUE;
7975 }
7976
7977 static void
7978 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
7979     QtDemuxStream * stream)
7980 {
7981   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
7982     return;
7983
7984   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
7985       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
7986   if (G_UNLIKELY (stream->stsd_sample_description_id >=
7987           stream->stsd_entries_length)) {
7988     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7989         (_("This file is invalid and cannot be played.")),
7990         ("New sample description id is out of bounds (%d >= %d)",
7991             stream->stsd_sample_description_id, stream->stsd_entries_length));
7992   } else {
7993     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
7994     stream->new_caps = TRUE;
7995   }
7996 }
7997
7998 static gboolean
7999 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8000     QtDemuxStream * stream, GstTagList * list)
8001 {
8002   gboolean ret = TRUE;
8003   /* consistent default for push based mode */
8004   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8005
8006   if (stream->subtype == FOURCC_vide) {
8007     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8008
8009     stream->pad =
8010         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8011     g_free (name);
8012
8013     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8014       gst_object_unref (stream->pad);
8015       stream->pad = NULL;
8016       ret = FALSE;
8017       goto done;
8018     }
8019
8020     qtdemux->n_video_streams++;
8021   } else if (stream->subtype == FOURCC_soun) {
8022     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8023
8024     stream->pad =
8025         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8026     g_free (name);
8027     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8028       gst_object_unref (stream->pad);
8029       stream->pad = NULL;
8030       ret = FALSE;
8031       goto done;
8032     }
8033     qtdemux->n_audio_streams++;
8034   } else if (stream->subtype == FOURCC_strm) {
8035     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8036   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8037       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8038     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8039
8040     stream->pad =
8041         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8042     g_free (name);
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     qtdemux->n_sub_streams++;
8050   } else if (CUR_STREAM (stream)->caps) {
8051     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8052
8053     stream->pad =
8054         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8055     g_free (name);
8056     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8057       gst_object_unref (stream->pad);
8058       stream->pad = NULL;
8059       ret = FALSE;
8060       goto done;
8061     }
8062     qtdemux->n_video_streams++;
8063   } else {
8064     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8065     goto done;
8066   }
8067
8068   if (stream->pad) {
8069     GList *l;
8070
8071     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8072         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8073     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8074     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8075
8076     if (stream->stream_tags)
8077       gst_tag_list_unref (stream->stream_tags);
8078     stream->stream_tags = list;
8079     list = NULL;
8080     /* global tags go on each pad anyway */
8081     stream->send_global_tags = TRUE;
8082     /* send upstream GST_EVENT_PROTECTION events that were received before
8083        this source pad was created */
8084     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8085       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8086   }
8087 done:
8088   if (list)
8089     gst_tag_list_unref (list);
8090   return ret;
8091 }
8092
8093 /* find next atom with @fourcc starting at @offset */
8094 static GstFlowReturn
8095 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8096     guint64 * length, guint32 fourcc)
8097 {
8098   GstFlowReturn ret;
8099   guint32 lfourcc;
8100   GstBuffer *buf;
8101
8102   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8103       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8104
8105   while (TRUE) {
8106     GstMapInfo map;
8107
8108     buf = NULL;
8109     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8110     if (G_UNLIKELY (ret != GST_FLOW_OK))
8111       goto locate_failed;
8112     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8113       /* likely EOF */
8114       ret = GST_FLOW_EOS;
8115       gst_buffer_unref (buf);
8116       goto locate_failed;
8117     }
8118     gst_buffer_map (buf, &map, GST_MAP_READ);
8119     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8120     gst_buffer_unmap (buf, &map);
8121     gst_buffer_unref (buf);
8122
8123     if (G_UNLIKELY (*length == 0)) {
8124       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8125       ret = GST_FLOW_ERROR;
8126       goto locate_failed;
8127     }
8128
8129     if (lfourcc == fourcc) {
8130       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8131           *offset);
8132       break;
8133     } else {
8134       GST_LOG_OBJECT (qtdemux,
8135           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8136           GST_FOURCC_ARGS (fourcc), *offset);
8137       *offset += *length;
8138     }
8139   }
8140
8141   return GST_FLOW_OK;
8142
8143 locate_failed:
8144   {
8145     /* might simply have had last one */
8146     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8147     return ret;
8148   }
8149 }
8150
8151 /* should only do something in pull mode */
8152 /* call with OBJECT lock */
8153 static GstFlowReturn
8154 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8155 {
8156   guint64 length, offset;
8157   GstBuffer *buf = NULL;
8158   GstFlowReturn ret = GST_FLOW_OK;
8159   GstFlowReturn res = GST_FLOW_OK;
8160   GstMapInfo map;
8161
8162   offset = qtdemux->moof_offset;
8163   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8164
8165   if (!offset) {
8166     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8167     return GST_FLOW_EOS;
8168   }
8169
8170   /* best not do pull etc with lock held */
8171   GST_OBJECT_UNLOCK (qtdemux);
8172
8173   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8174   if (ret != GST_FLOW_OK)
8175     goto flow_failed;
8176
8177   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8178   if (G_UNLIKELY (ret != GST_FLOW_OK))
8179     goto flow_failed;
8180   gst_buffer_map (buf, &map, GST_MAP_READ);
8181   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8182     gst_buffer_unmap (buf, &map);
8183     gst_buffer_unref (buf);
8184     buf = NULL;
8185     goto parse_failed;
8186   }
8187
8188   gst_buffer_unmap (buf, &map);
8189   gst_buffer_unref (buf);
8190   buf = NULL;
8191
8192   offset += length;
8193   /* look for next moof */
8194   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8195   if (G_UNLIKELY (ret != GST_FLOW_OK))
8196     goto flow_failed;
8197
8198 exit:
8199   GST_OBJECT_LOCK (qtdemux);
8200
8201   qtdemux->moof_offset = offset;
8202
8203   return res;
8204
8205 parse_failed:
8206   {
8207     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8208     offset = 0;
8209     res = GST_FLOW_ERROR;
8210     goto exit;
8211   }
8212 flow_failed:
8213   {
8214     /* maybe upstream temporarily flushing */
8215     if (ret != GST_FLOW_FLUSHING) {
8216       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8217       offset = 0;
8218     } else {
8219       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8220       /* resume at current position next time */
8221     }
8222     res = ret;
8223     goto exit;
8224   }
8225 }
8226
8227 /* initialise bytereaders for stbl sub-atoms */
8228 static gboolean
8229 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8230 {
8231   stream->stbl_index = -1;      /* no samples have yet been parsed */
8232   stream->sample_index = -1;
8233
8234   /* time-to-sample atom */
8235   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8236     goto corrupt_file;
8237
8238   /* copy atom data into a new buffer for later use */
8239   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8240
8241   /* skip version + flags */
8242   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8243       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8244     goto corrupt_file;
8245   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8246
8247   /* make sure there's enough data */
8248   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8249     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8250     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8251         stream->n_sample_times);
8252     if (!stream->n_sample_times)
8253       goto corrupt_file;
8254   }
8255
8256   /* sync sample atom */
8257   stream->stps_present = FALSE;
8258   if ((stream->stss_present =
8259           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8260               &stream->stss) ? TRUE : FALSE) == TRUE) {
8261     /* copy atom data into a new buffer for later use */
8262     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8263
8264     /* skip version + flags */
8265     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8266         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8267       goto corrupt_file;
8268
8269     if (stream->n_sample_syncs) {
8270       /* make sure there's enough data */
8271       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8272         goto corrupt_file;
8273     }
8274
8275     /* partial sync sample atom */
8276     if ((stream->stps_present =
8277             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8278                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8279       /* copy atom data into a new buffer for later use */
8280       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8281
8282       /* skip version + flags */
8283       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8284           !gst_byte_reader_get_uint32_be (&stream->stps,
8285               &stream->n_sample_partial_syncs))
8286         goto corrupt_file;
8287
8288       /* if there are no entries, the stss table contains the real
8289        * sync samples */
8290       if (stream->n_sample_partial_syncs) {
8291         /* make sure there's enough data */
8292         if (!qt_atom_parser_has_chunks (&stream->stps,
8293                 stream->n_sample_partial_syncs, 4))
8294           goto corrupt_file;
8295       }
8296     }
8297   }
8298
8299   /* sample size */
8300   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8301     goto no_samples;
8302
8303   /* copy atom data into a new buffer for later use */
8304   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8305
8306   /* skip version + flags */
8307   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8308       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8309     goto corrupt_file;
8310
8311   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8312     goto corrupt_file;
8313
8314   if (!stream->n_samples)
8315     goto no_samples;
8316
8317   /* sample-to-chunk atom */
8318   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8319     goto corrupt_file;
8320
8321   /* copy atom data into a new buffer for later use */
8322   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8323
8324   /* skip version + flags */
8325   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8326       !gst_byte_reader_get_uint32_be (&stream->stsc,
8327           &stream->n_samples_per_chunk))
8328     goto corrupt_file;
8329
8330   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8331       stream->n_samples_per_chunk);
8332
8333   /* make sure there's enough data */
8334   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8335           12))
8336     goto corrupt_file;
8337
8338
8339   /* chunk offset */
8340   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8341     stream->co_size = sizeof (guint32);
8342   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8343           &stream->stco))
8344     stream->co_size = sizeof (guint64);
8345   else
8346     goto corrupt_file;
8347
8348   /* copy atom data into a new buffer for later use */
8349   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8350
8351   /* skip version + flags */
8352   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8353     goto corrupt_file;
8354
8355   /* chunks_are_samples == TRUE means treat chunks as samples */
8356   stream->chunks_are_samples = stream->sample_size
8357       && !CUR_STREAM (stream)->sampled;
8358   if (stream->chunks_are_samples) {
8359     /* treat chunks as samples */
8360     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8361       goto corrupt_file;
8362   } else {
8363     /* skip number of entries */
8364     if (!gst_byte_reader_skip (&stream->stco, 4))
8365       goto corrupt_file;
8366
8367     /* make sure there are enough data in the stsz atom */
8368     if (!stream->sample_size) {
8369       /* different sizes for each sample */
8370       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8371         goto corrupt_file;
8372     }
8373   }
8374
8375   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8376       stream->n_samples, (guint) sizeof (QtDemuxSample),
8377       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8378
8379   if (stream->n_samples >=
8380       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8381     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8382         "be larger than %uMB (broken file?)", stream->n_samples,
8383         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8384     return FALSE;
8385   }
8386
8387   g_assert (stream->samples == NULL);
8388   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8389   if (!stream->samples) {
8390     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8391         stream->n_samples);
8392     return FALSE;
8393   }
8394
8395   /* composition time-to-sample */
8396   if ((stream->ctts_present =
8397           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8398               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8399     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8400
8401     /* copy atom data into a new buffer for later use */
8402     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8403
8404     /* skip version + flags */
8405     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8406         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8407             &stream->n_composition_times))
8408       goto corrupt_file;
8409
8410     /* make sure there's enough data */
8411     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8412             4 + 4))
8413       goto corrupt_file;
8414
8415     /* This is optional, if missing we iterate the ctts */
8416     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8417       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8418           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8419         g_free ((gpointer) cslg.data);
8420         goto corrupt_file;
8421       }
8422     } else {
8423       gint32 cslg_least = 0;
8424       guint num_entries, pos;
8425       gint i;
8426
8427       pos = gst_byte_reader_get_pos (&stream->ctts);
8428       num_entries = stream->n_composition_times;
8429
8430       stream->cslg_shift = 0;
8431
8432       for (i = 0; i < num_entries; i++) {
8433         gint32 offset;
8434
8435         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8436         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8437
8438         if (offset < cslg_least)
8439           cslg_least = offset;
8440       }
8441
8442       if (cslg_least < 0)
8443         stream->cslg_shift = ABS (cslg_least);
8444       else
8445         stream->cslg_shift = 0;
8446
8447       /* reset the reader so we can generate sample table */
8448       gst_byte_reader_set_pos (&stream->ctts, pos);
8449     }
8450   } else {
8451     /* Ensure the cslg_shift value is consistent so we can use it
8452      * unconditionnally to produce TS and Segment */
8453     stream->cslg_shift = 0;
8454   }
8455
8456   return TRUE;
8457
8458 corrupt_file:
8459   {
8460     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8461         (_("This file is corrupt and cannot be played.")), (NULL));
8462     return FALSE;
8463   }
8464 no_samples:
8465   {
8466     gst_qtdemux_stbl_free (stream);
8467     if (!qtdemux->fragmented) {
8468       /* not quite good */
8469       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8470       return FALSE;
8471     } else {
8472       /* may pick up samples elsewhere */
8473       return TRUE;
8474     }
8475   }
8476 }
8477
8478 /* collect samples from the next sample to be parsed up to sample @n for @stream
8479  * by reading the info from @stbl
8480  *
8481  * This code can be executed from both the streaming thread and the seeking
8482  * thread so it takes the object lock to protect itself
8483  */
8484 static gboolean
8485 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8486 {
8487   gint i, j, k;
8488   QtDemuxSample *samples, *first, *cur, *last;
8489   guint32 n_samples_per_chunk;
8490   guint32 n_samples;
8491
8492   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8493       GST_FOURCC_FORMAT ", pad %s",
8494       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8495       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8496
8497   n_samples = stream->n_samples;
8498
8499   if (n >= n_samples)
8500     goto out_of_samples;
8501
8502   GST_OBJECT_LOCK (qtdemux);
8503   if (n <= stream->stbl_index)
8504     goto already_parsed;
8505
8506   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8507
8508   if (!stream->stsz.data) {
8509     /* so we already parsed and passed all the moov samples;
8510      * onto fragmented ones */
8511     g_assert (qtdemux->fragmented);
8512     goto done;
8513   }
8514
8515   /* pointer to the sample table */
8516   samples = stream->samples;
8517
8518   /* starts from -1, moves to the next sample index to parse */
8519   stream->stbl_index++;
8520
8521   /* keep track of the first and last sample to fill */
8522   first = &samples[stream->stbl_index];
8523   last = &samples[n];
8524
8525   if (!stream->chunks_are_samples) {
8526     /* set the sample sizes */
8527     if (stream->sample_size == 0) {
8528       /* different sizes for each sample */
8529       for (cur = first; cur <= last; cur++) {
8530         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8531         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8532             (guint) (cur - samples), cur->size);
8533       }
8534     } else {
8535       /* samples have the same size */
8536       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8537       for (cur = first; cur <= last; cur++)
8538         cur->size = stream->sample_size;
8539     }
8540   }
8541
8542   n_samples_per_chunk = stream->n_samples_per_chunk;
8543   cur = first;
8544
8545   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8546     guint32 last_chunk;
8547
8548     if (stream->stsc_chunk_index >= stream->last_chunk
8549         || stream->stsc_chunk_index < stream->first_chunk) {
8550       stream->first_chunk =
8551           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8552       stream->samples_per_chunk =
8553           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8554       /* starts from 1 */
8555       stream->stsd_sample_description_id =
8556           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8557
8558       /* chunk numbers are counted from 1 it seems */
8559       if (G_UNLIKELY (stream->first_chunk == 0))
8560         goto corrupt_file;
8561
8562       --stream->first_chunk;
8563
8564       /* the last chunk of each entry is calculated by taking the first chunk
8565        * of the next entry; except if there is no next, where we fake it with
8566        * INT_MAX */
8567       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8568         stream->last_chunk = G_MAXUINT32;
8569       } else {
8570         stream->last_chunk =
8571             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8572         if (G_UNLIKELY (stream->last_chunk == 0))
8573           goto corrupt_file;
8574
8575         --stream->last_chunk;
8576       }
8577
8578       GST_LOG_OBJECT (qtdemux,
8579           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8580           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8581           stream->samples_per_chunk, stream->stsd_sample_description_id);
8582
8583       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8584         goto corrupt_file;
8585
8586       if (stream->last_chunk != G_MAXUINT32) {
8587         if (!qt_atom_parser_peek_sub (&stream->stco,
8588                 stream->first_chunk * stream->co_size,
8589                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8590                 &stream->co_chunk))
8591           goto corrupt_file;
8592
8593       } else {
8594         stream->co_chunk = stream->stco;
8595         if (!gst_byte_reader_skip (&stream->co_chunk,
8596                 stream->first_chunk * stream->co_size))
8597           goto corrupt_file;
8598       }
8599
8600       stream->stsc_chunk_index = stream->first_chunk;
8601     }
8602
8603     last_chunk = stream->last_chunk;
8604
8605     if (stream->chunks_are_samples) {
8606       cur = &samples[stream->stsc_chunk_index];
8607
8608       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8609         if (j > n) {
8610           /* save state */
8611           stream->stsc_chunk_index = j;
8612           goto done;
8613         }
8614
8615         cur->offset =
8616             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8617             stream->co_size);
8618
8619         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8620             "%" G_GUINT64_FORMAT, j, cur->offset);
8621
8622         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8623             CUR_STREAM (stream)->bytes_per_frame > 0) {
8624           cur->size =
8625               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8626               CUR_STREAM (stream)->samples_per_frame *
8627               CUR_STREAM (stream)->bytes_per_frame;
8628         } else {
8629           cur->size = stream->samples_per_chunk;
8630         }
8631
8632         GST_DEBUG_OBJECT (qtdemux,
8633             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8634             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8635                     stream->stco_sample_index)), cur->size);
8636
8637         cur->timestamp = stream->stco_sample_index;
8638         cur->duration = stream->samples_per_chunk;
8639         cur->keyframe = TRUE;
8640         cur++;
8641
8642         stream->stco_sample_index += stream->samples_per_chunk;
8643       }
8644       stream->stsc_chunk_index = j;
8645     } else {
8646       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8647         guint32 samples_per_chunk;
8648         guint64 chunk_offset;
8649
8650         if (!stream->stsc_sample_index
8651             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8652                 &stream->chunk_offset))
8653           goto corrupt_file;
8654
8655         samples_per_chunk = stream->samples_per_chunk;
8656         chunk_offset = stream->chunk_offset;
8657
8658         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8659           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8660               G_GUINT64_FORMAT " and size %d",
8661               (guint) (cur - samples), chunk_offset, cur->size);
8662
8663           cur->offset = chunk_offset;
8664           chunk_offset += cur->size;
8665           cur++;
8666
8667           if (G_UNLIKELY (cur > last)) {
8668             /* save state */
8669             stream->stsc_sample_index = k + 1;
8670             stream->chunk_offset = chunk_offset;
8671             stream->stsc_chunk_index = j;
8672             goto done2;
8673           }
8674         }
8675         stream->stsc_sample_index = 0;
8676       }
8677       stream->stsc_chunk_index = j;
8678     }
8679     stream->stsc_index++;
8680   }
8681
8682   if (stream->chunks_are_samples)
8683     goto ctts;
8684 done2:
8685   {
8686     guint32 n_sample_times;
8687
8688     n_sample_times = stream->n_sample_times;
8689     cur = first;
8690
8691     for (i = stream->stts_index; i < n_sample_times; i++) {
8692       guint32 stts_samples;
8693       gint32 stts_duration;
8694       gint64 stts_time;
8695
8696       if (stream->stts_sample_index >= stream->stts_samples
8697           || !stream->stts_sample_index) {
8698
8699         stream->stts_samples =
8700             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8701         stream->stts_duration =
8702             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8703
8704         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8705             i, stream->stts_samples, stream->stts_duration);
8706
8707         stream->stts_sample_index = 0;
8708       }
8709
8710       stts_samples = stream->stts_samples;
8711       stts_duration = stream->stts_duration;
8712       stts_time = stream->stts_time;
8713
8714       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8715         GST_DEBUG_OBJECT (qtdemux,
8716             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8717             (guint) (cur - samples), j,
8718             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8719
8720         cur->timestamp = stts_time;
8721         cur->duration = stts_duration;
8722
8723         /* avoid 32-bit wrap-around,
8724          * but still mind possible 'negative' duration */
8725         stts_time += (gint64) stts_duration;
8726         cur++;
8727
8728         if (G_UNLIKELY (cur > last)) {
8729           /* save values */
8730           stream->stts_time = stts_time;
8731           stream->stts_sample_index = j + 1;
8732           if (stream->stts_sample_index >= stream->stts_samples)
8733             stream->stts_index++;
8734           goto done3;
8735         }
8736       }
8737       stream->stts_sample_index = 0;
8738       stream->stts_time = stts_time;
8739       stream->stts_index++;
8740     }
8741     /* fill up empty timestamps with the last timestamp, this can happen when
8742      * the last samples do not decode and so we don't have timestamps for them.
8743      * We however look at the last timestamp to estimate the track length so we
8744      * need something in here. */
8745     for (; cur < last; cur++) {
8746       GST_DEBUG_OBJECT (qtdemux,
8747           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8748           (guint) (cur - samples),
8749           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8750       cur->timestamp = stream->stts_time;
8751       cur->duration = -1;
8752     }
8753   }
8754 done3:
8755   {
8756     /* sample sync, can be NULL */
8757     if (stream->stss_present == TRUE) {
8758       guint32 n_sample_syncs;
8759
8760       n_sample_syncs = stream->n_sample_syncs;
8761
8762       if (!n_sample_syncs) {
8763         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8764         stream->all_keyframe = TRUE;
8765       } else {
8766         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8767           /* note that the first sample is index 1, not 0 */
8768           guint32 index;
8769
8770           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8771
8772           if (G_LIKELY (index > 0 && index <= n_samples)) {
8773             index -= 1;
8774             samples[index].keyframe = TRUE;
8775             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8776             /* and exit if we have enough samples */
8777             if (G_UNLIKELY (index >= n)) {
8778               i++;
8779               break;
8780             }
8781           }
8782         }
8783         /* save state */
8784         stream->stss_index = i;
8785       }
8786
8787       /* stps marks partial sync frames like open GOP I-Frames */
8788       if (stream->stps_present == TRUE) {
8789         guint32 n_sample_partial_syncs;
8790
8791         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8792
8793         /* if there are no entries, the stss table contains the real
8794          * sync samples */
8795         if (n_sample_partial_syncs) {
8796           for (i = stream->stps_index; i < n_sample_partial_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->stps);
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->stps_index = i;
8815         }
8816       }
8817     } else {
8818       /* no stss, all samples are keyframes */
8819       stream->all_keyframe = TRUE;
8820       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8821     }
8822   }
8823
8824 ctts:
8825   /* composition time to sample */
8826   if (stream->ctts_present == TRUE) {
8827     guint32 n_composition_times;
8828     guint32 ctts_count;
8829     gint32 ctts_soffset;
8830
8831     /* Fill in the pts_offsets */
8832     cur = first;
8833     n_composition_times = stream->n_composition_times;
8834
8835     for (i = stream->ctts_index; i < n_composition_times; i++) {
8836       if (stream->ctts_sample_index >= stream->ctts_count
8837           || !stream->ctts_sample_index) {
8838         stream->ctts_count =
8839             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8840         stream->ctts_soffset =
8841             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8842         stream->ctts_sample_index = 0;
8843       }
8844
8845       ctts_count = stream->ctts_count;
8846       ctts_soffset = stream->ctts_soffset;
8847
8848       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8849         cur->pts_offset = ctts_soffset;
8850         cur++;
8851
8852         if (G_UNLIKELY (cur > last)) {
8853           /* save state */
8854           stream->ctts_sample_index = j + 1;
8855           goto done;
8856         }
8857       }
8858       stream->ctts_sample_index = 0;
8859       stream->ctts_index++;
8860     }
8861   }
8862 done:
8863   stream->stbl_index = n;
8864   /* if index has been completely parsed, free data that is no-longer needed */
8865   if (n + 1 == stream->n_samples) {
8866     gst_qtdemux_stbl_free (stream);
8867     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8868     if (qtdemux->pullbased) {
8869       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8870       while (n + 1 == stream->n_samples)
8871         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8872           break;
8873     }
8874   }
8875   GST_OBJECT_UNLOCK (qtdemux);
8876
8877   return TRUE;
8878
8879   /* SUCCESS */
8880 already_parsed:
8881   {
8882     GST_LOG_OBJECT (qtdemux,
8883         "Tried to parse up to sample %u but this sample has already been parsed",
8884         n);
8885     /* if fragmented, there may be more */
8886     if (qtdemux->fragmented && n == stream->stbl_index)
8887       goto done;
8888     GST_OBJECT_UNLOCK (qtdemux);
8889     return TRUE;
8890   }
8891   /* ERRORS */
8892 out_of_samples:
8893   {
8894     GST_LOG_OBJECT (qtdemux,
8895         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8896         stream->n_samples);
8897     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8898         (_("This file is corrupt and cannot be played.")), (NULL));
8899     return FALSE;
8900   }
8901 corrupt_file:
8902   {
8903     GST_OBJECT_UNLOCK (qtdemux);
8904     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8905         (_("This file is corrupt and cannot be played.")), (NULL));
8906     return FALSE;
8907   }
8908 }
8909
8910 /* collect all segment info for @stream.
8911  */
8912 static gboolean
8913 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8914     GNode * trak)
8915 {
8916   GNode *edts;
8917   /* accept edts if they contain gaps at start and there is only
8918    * one media segment */
8919   gboolean allow_pushbased_edts = TRUE;
8920   gint media_segments_count = 0;
8921
8922   /* parse and prepare segment info from the edit list */
8923   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8924   stream->n_segments = 0;
8925   stream->segments = NULL;
8926   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8927     GNode *elst;
8928     gint n_segments;
8929     gint i, count, entry_size;
8930     guint64 time;
8931     GstClockTime stime;
8932     const guint8 *buffer;
8933     guint8 version;
8934     guint32 size;
8935
8936     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8937     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8938       goto done;
8939
8940     buffer = elst->data;
8941
8942     size = QT_UINT32 (buffer);
8943     /* version, flags, n_segments */
8944     if (size < 16) {
8945       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8946       goto done;
8947     }
8948     version = QT_UINT8 (buffer + 8);
8949     entry_size = (version == 1) ? 20 : 12;
8950
8951     n_segments = QT_UINT32 (buffer + 12);
8952
8953     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
8954       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8955       goto done;
8956     }
8957
8958     /* we might allocate a bit too much, at least allocate 1 segment */
8959     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8960
8961     /* segments always start from 0 */
8962     time = 0;
8963     stime = 0;
8964     count = 0;
8965     buffer += 16;
8966     for (i = 0; i < n_segments; i++) {
8967       guint64 duration;
8968       guint64 media_time;
8969       gboolean time_valid = TRUE;
8970       QtDemuxSegment *segment;
8971       guint32 rate_int;
8972       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8973
8974       if (version == 1) {
8975         media_time = QT_UINT64 (buffer + 8);
8976         duration = QT_UINT64 (buffer);
8977         if (media_time == G_MAXUINT64)
8978           time_valid = FALSE;
8979       } else {
8980         media_time = QT_UINT32 (buffer + 4);
8981         duration = QT_UINT32 (buffer);
8982         if (media_time == G_MAXUINT32)
8983           time_valid = FALSE;
8984       }
8985
8986       if (time_valid)
8987         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8988
8989       segment = &stream->segments[count++];
8990
8991       /* time and duration expressed in global timescale */
8992       segment->time = stime;
8993       /* add non scaled values so we don't cause roundoff errors */
8994       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8995         time += duration;
8996         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8997         segment->duration = stime - segment->time;
8998       } else {
8999         /* zero duration does not imply media_start == media_stop
9000          * but, only specify media_start.*/
9001         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9002         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9003             && stime >= media_start) {
9004           segment->duration = stime - media_start;
9005         } else {
9006           segment->duration = GST_CLOCK_TIME_NONE;
9007         }
9008       }
9009       segment->stop_time = stime;
9010
9011       segment->trak_media_start = media_time;
9012       /* media_time expressed in stream timescale */
9013       if (time_valid) {
9014         segment->media_start = media_start;
9015         segment->media_stop = segment->media_start + segment->duration;
9016         media_segments_count++;
9017       } else {
9018         segment->media_start = GST_CLOCK_TIME_NONE;
9019         segment->media_stop = GST_CLOCK_TIME_NONE;
9020       }
9021       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9022
9023       if (rate_int <= 1) {
9024         /* 0 is not allowed, some programs write 1 instead of the floating point
9025          * value */
9026         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9027             rate_int);
9028         segment->rate = 1;
9029       } else {
9030         segment->rate = rate_int / 65536.0;
9031       }
9032
9033       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9034           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9035           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9036           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9037           i, GST_TIME_ARGS (segment->time),
9038           GST_TIME_ARGS (segment->duration),
9039           GST_TIME_ARGS (segment->media_start), media_time,
9040           GST_TIME_ARGS (segment->media_stop),
9041           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9042           stream->timescale);
9043       if (segment->stop_time > qtdemux->segment.stop) {
9044         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9045             " extends to %" GST_TIME_FORMAT
9046             " past the end of the file duration %" GST_TIME_FORMAT
9047             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9048             GST_TIME_ARGS (qtdemux->segment.stop));
9049         qtdemux->segment.stop = segment->stop_time;
9050       }
9051
9052       buffer += entry_size;
9053     }
9054     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9055     stream->n_segments = count;
9056     if (media_segments_count != 1)
9057       allow_pushbased_edts = FALSE;
9058   }
9059 done:
9060
9061   /* push based does not handle segments, so act accordingly here,
9062    * and warn if applicable */
9063   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9064     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9065     /* remove and use default one below, we stream like it anyway */
9066     g_free (stream->segments);
9067     stream->segments = NULL;
9068     stream->n_segments = 0;
9069   }
9070
9071   /* no segments, create one to play the complete trak */
9072   if (stream->n_segments == 0) {
9073     GstClockTime stream_duration =
9074         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9075
9076     if (stream->segments == NULL)
9077       stream->segments = g_new (QtDemuxSegment, 1);
9078
9079     /* represent unknown our way */
9080     if (stream_duration == 0)
9081       stream_duration = GST_CLOCK_TIME_NONE;
9082
9083     stream->segments[0].time = 0;
9084     stream->segments[0].stop_time = stream_duration;
9085     stream->segments[0].duration = stream_duration;
9086     stream->segments[0].media_start = 0;
9087     stream->segments[0].media_stop = stream_duration;
9088     stream->segments[0].rate = 1.0;
9089     stream->segments[0].trak_media_start = 0;
9090
9091     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9092         GST_TIME_ARGS (stream_duration));
9093     stream->n_segments = 1;
9094     stream->dummy_segment = TRUE;
9095   }
9096   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9097
9098   return TRUE;
9099 }
9100
9101 /*
9102  * Parses the stsd atom of a svq3 trak looking for
9103  * the SMI and gama atoms.
9104  */
9105 static void
9106 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9107     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9108 {
9109   const guint8 *_gamma = NULL;
9110   GstBuffer *_seqh = NULL;
9111   const guint8 *stsd_data = stsd_entry_data;
9112   guint32 length = QT_UINT32 (stsd_data);
9113   guint16 version;
9114
9115   if (length < 32) {
9116     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9117     goto end;
9118   }
9119
9120   stsd_data += 16;
9121   length -= 16;
9122   version = QT_UINT16 (stsd_data);
9123   if (version == 3) {
9124     if (length >= 70) {
9125       length -= 70;
9126       stsd_data += 70;
9127       while (length > 8) {
9128         guint32 fourcc, size;
9129         const guint8 *data;
9130         size = QT_UINT32 (stsd_data);
9131         fourcc = QT_FOURCC (stsd_data + 4);
9132         data = stsd_data + 8;
9133
9134         if (size == 0) {
9135           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9136               "svq3 atom parsing");
9137           goto end;
9138         }
9139
9140         switch (fourcc) {
9141           case FOURCC_gama:{
9142             if (size == 12) {
9143               _gamma = data;
9144             } else {
9145               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9146                   " for gama atom, expected 12", size);
9147             }
9148             break;
9149           }
9150           case FOURCC_SMI_:{
9151             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9152               guint32 seqh_size;
9153               if (_seqh != NULL) {
9154                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9155                     " found, ignoring");
9156               } else {
9157                 seqh_size = QT_UINT32 (data + 4);
9158                 if (seqh_size > 0) {
9159                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9160                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9161                 }
9162               }
9163             }
9164             break;
9165           }
9166           default:{
9167             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9168                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9169           }
9170         }
9171
9172         if (size <= length) {
9173           length -= size;
9174           stsd_data += size;
9175         }
9176       }
9177     } else {
9178       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9179     }
9180   } else {
9181     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9182         G_GUINT16_FORMAT, version);
9183     goto end;
9184   }
9185
9186 end:
9187   if (gamma) {
9188     *gamma = _gamma;
9189   }
9190   if (seqh) {
9191     *seqh = _seqh;
9192   } else if (_seqh) {
9193     gst_buffer_unref (_seqh);
9194   }
9195 }
9196
9197 static gchar *
9198 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9199 {
9200   GNode *dinf;
9201   GstByteReader dref;
9202   gchar *uri = NULL;
9203
9204   /*
9205    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9206    * atom that might contain a 'data' atom with the rtsp uri.
9207    * This case was reported in bug #597497, some info about
9208    * the hndl atom can be found in TN1195
9209    */
9210   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9211   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9212
9213   if (dinf) {
9214     guint32 dref_num_entries = 0;
9215     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9216         gst_byte_reader_skip (&dref, 4) &&
9217         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9218       gint i;
9219
9220       /* search dref entries for hndl atom */
9221       for (i = 0; i < dref_num_entries; i++) {
9222         guint32 size = 0, type;
9223         guint8 string_len = 0;
9224         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9225             qt_atom_parser_get_fourcc (&dref, &type)) {
9226           if (type == FOURCC_hndl) {
9227             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9228
9229             /* skip data reference handle bytes and the
9230              * following pascal string and some extra 4
9231              * bytes I have no idea what are */
9232             if (!gst_byte_reader_skip (&dref, 4) ||
9233                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9234                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9235               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9236               break;
9237             }
9238
9239             /* iterate over the atoms to find the data atom */
9240             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9241               guint32 atom_size;
9242               guint32 atom_type;
9243
9244               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9245                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9246                 if (atom_type == FOURCC_data) {
9247                   const guint8 *uri_aux = NULL;
9248
9249                   /* found the data atom that might contain the rtsp uri */
9250                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9251                       "hndl atom, interpreting it as an URI");
9252                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9253                           &uri_aux)) {
9254                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9255                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9256                     else
9257                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9258                           "didn't contain a rtsp address");
9259                   } else {
9260                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9261                         "atom contents");
9262                   }
9263                   break;
9264                 }
9265                 /* skipping to the next entry */
9266                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9267                   break;
9268               } else {
9269                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9270                     "atom header");
9271                 break;
9272               }
9273             }
9274             break;
9275           }
9276           /* skip to the next entry */
9277           if (!gst_byte_reader_skip (&dref, size - 8))
9278             break;
9279         } else {
9280           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9281         }
9282       }
9283       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9284     }
9285   }
9286   return uri;
9287 }
9288
9289 #define AMR_NB_ALL_MODES        0x81ff
9290 #define AMR_WB_ALL_MODES        0x83ff
9291 static guint
9292 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9293 {
9294   /* The 'damr' atom is of the form:
9295    *
9296    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9297    *    32 b       8 b          16 b           8 b                 8 b
9298    *
9299    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9300    * represents the highest mode used in the stream (and thus the maximum
9301    * bitrate), with a couple of special cases as seen below.
9302    */
9303
9304   /* Map of frame type ID -> bitrate */
9305   static const guint nb_bitrates[] = {
9306     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9307   };
9308   static const guint wb_bitrates[] = {
9309     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9310   };
9311   GstMapInfo map;
9312   gsize max_mode;
9313   guint16 mode_set;
9314
9315   gst_buffer_map (buf, &map, GST_MAP_READ);
9316
9317   if (map.size != 0x11) {
9318     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9319     goto bad_data;
9320   }
9321
9322   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9323     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9324         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9325     goto bad_data;
9326   }
9327
9328   mode_set = QT_UINT16 (map.data + 13);
9329
9330   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9331     max_mode = 7 + (wb ? 1 : 0);
9332   else
9333     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9334     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9335
9336   if (max_mode == -1) {
9337     GST_DEBUG ("No mode indication was found (mode set) = %x",
9338         (guint) mode_set);
9339     goto bad_data;
9340   }
9341
9342   gst_buffer_unmap (buf, &map);
9343   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9344
9345 bad_data:
9346   gst_buffer_unmap (buf, &map);
9347   return 0;
9348 }
9349
9350 static gboolean
9351 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9352     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9353 {
9354   /*
9355    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9356    * [0 1 2]
9357    * [3 4 5]
9358    * [6 7 8]
9359    */
9360
9361   if (gst_byte_reader_get_remaining (reader) < 36)
9362     return FALSE;
9363
9364   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9365   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9366   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9367   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9368   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9369   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9370   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9371   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9372   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9373
9374   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9375   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9376       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9377       matrix[2] & 0xFF);
9378   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9379       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9380       matrix[5] & 0xFF);
9381   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9382       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9383       matrix[8] & 0xFF);
9384
9385   return TRUE;
9386 }
9387
9388 static void
9389 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9390     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9391 {
9392
9393 /* [a b c]
9394  * [d e f]
9395  * [g h i]
9396  *
9397  * This macro will only compare value abdegh, it expects cfi to have already
9398  * been checked
9399  */
9400 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9401                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9402
9403   /* only handle the cases where the last column has standard values */
9404   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9405     const gchar *rotation_tag = NULL;
9406
9407     /* no rotation needed */
9408     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9409       /* NOP */
9410     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9411       rotation_tag = "rotate-90";
9412     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9413       rotation_tag = "rotate-180";
9414     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9415       rotation_tag = "rotate-270";
9416     } else {
9417       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9418     }
9419
9420     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9421         rotation_tag);
9422     if (rotation_tag != NULL) {
9423       if (*taglist == NULL)
9424         *taglist = gst_tag_list_new_empty ();
9425       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9426           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9427     }
9428   } else {
9429     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9430   }
9431 }
9432
9433 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9434  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9435  * Common Encryption (cenc), the function will also parse the tenc box (defined
9436  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9437  * (typically an enc[v|a|t|s] sample entry); the function will set
9438  * @original_fmt to the fourcc of the original unencrypted stream format.
9439  * Returns TRUE if successful; FALSE otherwise. */
9440 static gboolean
9441 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9442     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9443 {
9444   GNode *sinf;
9445   GNode *frma;
9446   GNode *schm;
9447   GNode *schi;
9448
9449   g_return_val_if_fail (qtdemux != NULL, FALSE);
9450   g_return_val_if_fail (stream != NULL, FALSE);
9451   g_return_val_if_fail (container != NULL, FALSE);
9452   g_return_val_if_fail (original_fmt != NULL, FALSE);
9453
9454   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9455   if (G_UNLIKELY (!sinf)) {
9456     if (stream->protection_scheme_type == FOURCC_cenc) {
9457       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9458           "mandatory for Common Encryption");
9459       return FALSE;
9460     }
9461     return TRUE;
9462   }
9463
9464   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9465   if (G_UNLIKELY (!frma)) {
9466     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9467     return FALSE;
9468   }
9469
9470   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9471   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9472       GST_FOURCC_ARGS (*original_fmt));
9473
9474   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9475   if (!schm) {
9476     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9477     return FALSE;
9478   }
9479   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9480   stream->protection_scheme_version =
9481       QT_UINT32 ((const guint8 *) schm->data + 16);
9482
9483   GST_DEBUG_OBJECT (qtdemux,
9484       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9485       "protection_scheme_version: %#010x",
9486       GST_FOURCC_ARGS (stream->protection_scheme_type),
9487       stream->protection_scheme_version);
9488
9489   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9490   if (!schi) {
9491     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9492     return FALSE;
9493   }
9494   if (stream->protection_scheme_type == FOURCC_cenc) {
9495     QtDemuxCencSampleSetInfo *info;
9496     GNode *tenc;
9497     const guint8 *tenc_data;
9498     guint32 isEncrypted;
9499     guint8 iv_size;
9500     const guint8 *default_kid;
9501     GstBuffer *kid_buf;
9502
9503     if (G_UNLIKELY (!stream->protection_scheme_info))
9504       stream->protection_scheme_info =
9505           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9506
9507     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9508
9509     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9510     if (!tenc) {
9511       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9512           "which is mandatory for Common Encryption");
9513       return FALSE;
9514     }
9515     tenc_data = (const guint8 *) tenc->data + 12;
9516     isEncrypted = QT_UINT24 (tenc_data);
9517     iv_size = QT_UINT8 (tenc_data + 3);
9518     default_kid = (tenc_data + 4);
9519     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9520     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9521     if (info->default_properties)
9522       gst_structure_free (info->default_properties);
9523     info->default_properties =
9524         gst_structure_new ("application/x-cenc",
9525         "iv_size", G_TYPE_UINT, iv_size,
9526         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9527         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9528     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9529         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9530     gst_buffer_unref (kid_buf);
9531   }
9532   return TRUE;
9533 }
9534
9535 /* parse the traks.
9536  * With each track we associate a new QtDemuxStream that contains all the info
9537  * about the trak.
9538  * traks that do not decode to something (like strm traks) will not have a pad.
9539  */
9540 static gboolean
9541 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9542 {
9543   GstByteReader tkhd;
9544   int offset;
9545   GNode *mdia;
9546   GNode *mdhd;
9547   GNode *hdlr;
9548   GNode *minf;
9549   GNode *stbl;
9550   GNode *stsd;
9551   GNode *mp4a;
9552   GNode *mp4v;
9553   GNode *wave;
9554   GNode *esds;
9555   GNode *pasp;
9556   GNode *colr;
9557   GNode *tref;
9558   GNode *udta;
9559   GNode *svmi;
9560   GNode *fiel;
9561
9562   QtDemuxStream *stream = NULL;
9563   gboolean new_stream = FALSE;
9564   gchar *codec = NULL;
9565   const guint8 *stsd_data;
9566   const guint8 *stsd_entry_data;
9567   guint remaining_stsd_len;
9568   guint stsd_entry_count;
9569   guint stsd_index;
9570   guint16 lang_code;            /* quicktime lang code or packed iso code */
9571   guint32 version;
9572   guint32 tkhd_flags = 0;
9573   guint8 tkhd_version = 0;
9574   guint32 w = 0, h = 0;
9575   guint32 fourcc;
9576   guint value_size, stsd_len, len;
9577   guint32 track_id;
9578   guint32 dummy;
9579
9580   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9581
9582   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9583       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9584       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9585     goto corrupt_file;
9586
9587   /* pick between 64 or 32 bits */
9588   value_size = tkhd_version == 1 ? 8 : 4;
9589   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9590       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9591     goto corrupt_file;
9592
9593   if (!qtdemux->got_moov) {
9594     if (qtdemux_find_stream (qtdemux, track_id))
9595       goto existing_stream;
9596     stream = _create_stream ();
9597     stream->track_id = track_id;
9598     new_stream = TRUE;
9599   } else {
9600     stream = qtdemux_find_stream (qtdemux, track_id);
9601     if (!stream) {
9602       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9603       goto skip_track;
9604     }
9605
9606     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
9607
9608     /* flush samples data from this track from previous moov */
9609     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9610     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9611   }
9612   /* need defaults for fragments */
9613   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9614
9615   if ((tkhd_flags & 1) == 0)
9616     stream->disabled = TRUE;
9617
9618   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9619       tkhd_version, tkhd_flags, stream->track_id);
9620
9621   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9622     goto corrupt_file;
9623
9624   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9625     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9626     if (qtdemux->major_brand != FOURCC_mjp2 ||
9627         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9628       goto corrupt_file;
9629   }
9630
9631   len = QT_UINT32 ((guint8 *) mdhd->data);
9632   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9633   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9634   if (version == 0x01000000) {
9635     if (len < 38)
9636       goto corrupt_file;
9637     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9638     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9639     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9640   } else {
9641     if (len < 30)
9642       goto corrupt_file;
9643     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9644     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9645     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9646   }
9647
9648   if (lang_code < 0x400) {
9649     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9650   } else if (lang_code == 0x7fff) {
9651     stream->lang_id[0] = 0;     /* unspecified */
9652   } else {
9653     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9654     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9655     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9656     stream->lang_id[3] = 0;
9657   }
9658
9659   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9660       stream->timescale);
9661   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9662       stream->duration);
9663   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9664       lang_code, stream->lang_id);
9665
9666   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9667     goto corrupt_file;
9668
9669   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9670     /* chapters track reference */
9671     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9672     if (chap) {
9673       gsize length = GST_READ_UINT32_BE (chap->data);
9674       if (qtdemux->chapters_track_id)
9675         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9676
9677       if (length >= 12) {
9678         qtdemux->chapters_track_id =
9679             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9680       }
9681     }
9682   }
9683
9684   /* fragmented files may have bogus duration in moov */
9685   if (!qtdemux->fragmented &&
9686       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9687     guint64 tdur1, tdur2;
9688
9689     /* don't overflow */
9690     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9691     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9692
9693     /* HACK:
9694      * some of those trailers, nowadays, have prologue images that are
9695      * themselves video tracks as well. I haven't really found a way to
9696      * identify those yet, except for just looking at their duration. */
9697     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9698       GST_WARNING_OBJECT (qtdemux,
9699           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9700           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9701           "found, assuming preview image or something; skipping track",
9702           stream->duration, stream->timescale, qtdemux->duration,
9703           qtdemux->timescale);
9704       if (new_stream)
9705         gst_qtdemux_stream_free (qtdemux, stream);
9706       return TRUE;
9707     }
9708   }
9709
9710   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9711     goto corrupt_file;
9712
9713   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9714       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9715
9716   len = QT_UINT32 ((guint8 *) hdlr->data);
9717   if (len >= 20)
9718     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9719   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9720       GST_FOURCC_ARGS (stream->subtype));
9721
9722   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9723     goto corrupt_file;
9724
9725   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9726     goto corrupt_file;
9727
9728   /*parse svmi header if existing */
9729   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9730   if (svmi) {
9731     len = QT_UINT32 ((guint8 *) svmi->data);
9732     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9733     if (!version) {
9734       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9735       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9736       guint8 frame_type, frame_layout;
9737
9738       /* MPEG-A stereo video */
9739       if (qtdemux->major_brand == FOURCC_ss02)
9740         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9741
9742       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9743       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9744       switch (frame_type) {
9745         case 0:
9746           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9747           break;
9748         case 1:
9749           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9750           break;
9751         case 2:
9752           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9753           break;
9754         case 3:
9755           /* mode 3 is primary/secondary view sequence, ie
9756            * left/right views in separate tracks. See section 7.2
9757            * of ISO/IEC 23000-11:2009 */
9758           GST_FIXME_OBJECT (qtdemux,
9759               "Implement stereo video in separate streams");
9760       }
9761
9762       if ((frame_layout & 0x1) == 0)
9763         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9764
9765       GST_LOG_OBJECT (qtdemux,
9766           "StereoVideo: composition type: %u, is_left_first: %u",
9767           frame_type, frame_layout);
9768       stream->multiview_mode = mode;
9769       stream->multiview_flags = flags;
9770     }
9771   }
9772
9773   /* parse rest of tkhd */
9774   if (stream->subtype == FOURCC_vide) {
9775     guint32 matrix[9];
9776
9777     /* version 1 uses some 64-bit ints */
9778     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9779       goto corrupt_file;
9780
9781     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9782       goto corrupt_file;
9783
9784     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9785         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9786       goto corrupt_file;
9787
9788     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9789         &stream->stream_tags);
9790   }
9791
9792   /* parse stsd */
9793   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9794     goto corrupt_file;
9795   stsd_data = (const guint8 *) stsd->data;
9796
9797   /* stsd should at least have one entry */
9798   stsd_len = QT_UINT32 (stsd_data);
9799   if (stsd_len < 24) {
9800     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9801     if (stream->subtype == FOURCC_vivo) {
9802       if (new_stream)
9803         gst_qtdemux_stream_free (qtdemux, stream);
9804       return TRUE;
9805     } else {
9806       goto corrupt_file;
9807     }
9808   }
9809
9810   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9811   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9812   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9813   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9814
9815   stsd_entry_data = stsd_data + 16;
9816   remaining_stsd_len = stsd_len - 16;
9817   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9818     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9819
9820     /* and that entry should fit within stsd */
9821     len = QT_UINT32 (stsd_entry_data);
9822     if (len > remaining_stsd_len)
9823       goto corrupt_file;
9824
9825     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9826     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9827         GST_FOURCC_ARGS (entry->fourcc));
9828     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9829
9830     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9831       goto error_encrypted;
9832
9833     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9834       /* FIXME this looks wrong, there might be multiple children
9835        * with the same type */
9836       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9837       stream->protected = TRUE;
9838       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9839         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9840     }
9841
9842     if (stream->subtype == FOURCC_vide) {
9843       gboolean gray;
9844       gint depth, palette_size, palette_count;
9845       guint32 *palette_data = NULL;
9846
9847       entry->sampled = TRUE;
9848
9849       stream->display_width = w >> 16;
9850       stream->display_height = h >> 16;
9851
9852       offset = 16;
9853       if (len < 86)             /* TODO verify */
9854         goto corrupt_file;
9855
9856       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
9857       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
9858       entry->fps_n = 0;         /* this is filled in later */
9859       entry->fps_d = 0;         /* this is filled in later */
9860       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
9861       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
9862
9863       /* if color_table_id is 0, ctab atom must follow; however some files
9864        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9865        * if color table is not present we'll correct the value */
9866       if (entry->color_table_id == 0 &&
9867           (len < 90
9868               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
9869         entry->color_table_id = -1;
9870       }
9871
9872       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9873           entry->width, entry->height, entry->bits_per_sample,
9874           entry->color_table_id);
9875
9876       depth = entry->bits_per_sample;
9877
9878       /* more than 32 bits means grayscale */
9879       gray = (depth > 32);
9880       /* low 32 bits specify the depth  */
9881       depth &= 0x1F;
9882
9883       /* different number of palette entries is determined by depth. */
9884       palette_count = 0;
9885       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9886         palette_count = (1 << depth);
9887       palette_size = palette_count * 4;
9888
9889       if (entry->color_table_id) {
9890         switch (palette_count) {
9891           case 0:
9892             break;
9893           case 2:
9894             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9895             break;
9896           case 4:
9897             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9898             break;
9899           case 16:
9900             if (gray)
9901               palette_data =
9902                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
9903             else
9904               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9905             break;
9906           case 256:
9907             if (gray)
9908               palette_data =
9909                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
9910             else
9911               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9912             break;
9913           default:
9914             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9915                 (_("The video in this file might not play correctly.")),
9916                 ("unsupported palette depth %d", depth));
9917             break;
9918         }
9919       } else {
9920         gint i, j, start, end;
9921
9922         if (len < 94)
9923           goto corrupt_file;
9924
9925         /* read table */
9926         start = QT_UINT32 (stsd_entry_data + offset + 70);
9927         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
9928         end = QT_UINT16 (stsd_entry_data + offset + 76);
9929
9930         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9931             start, end, palette_count);
9932
9933         if (end > 255)
9934           end = 255;
9935         if (start > end)
9936           start = end;
9937
9938         if (len < 94 + (end - start) * 8)
9939           goto corrupt_file;
9940
9941         /* palette is always the same size */
9942         palette_data = g_malloc0 (256 * 4);
9943         palette_size = 256 * 4;
9944
9945         for (j = 0, i = start; i <= end; j++, i++) {
9946           guint32 a, r, g, b;
9947
9948           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
9949           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
9950           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
9951           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
9952
9953           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9954               (g & 0xff00) | (b >> 8);
9955         }
9956       }
9957
9958       if (entry->caps)
9959         gst_caps_unref (entry->caps);
9960
9961       entry->caps =
9962           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
9963           &codec);
9964       if (G_UNLIKELY (!entry->caps)) {
9965         g_free (palette_data);
9966         goto unknown_stream;
9967       }
9968
9969       if (codec) {
9970         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
9971             GST_TAG_VIDEO_CODEC, codec, NULL);
9972         g_free (codec);
9973         codec = NULL;
9974       }
9975
9976       if (palette_data) {
9977         GstStructure *s;
9978
9979         if (entry->rgb8_palette)
9980           gst_memory_unref (entry->rgb8_palette);
9981         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9982             palette_data, palette_size, 0, palette_size, palette_data, g_free);
9983
9984         s = gst_caps_get_structure (entry->caps, 0);
9985
9986         /* non-raw video has a palette_data property. raw video has the palette as
9987          * an extra plane that we append to the output buffers before we push
9988          * them*/
9989         if (!gst_structure_has_name (s, "video/x-raw")) {
9990           GstBuffer *palette;
9991
9992           palette = gst_buffer_new ();
9993           gst_buffer_append_memory (palette, entry->rgb8_palette);
9994           entry->rgb8_palette = NULL;
9995
9996           gst_caps_set_simple (entry->caps, "palette_data",
9997               GST_TYPE_BUFFER, palette, NULL);
9998           gst_buffer_unref (palette);
9999         }
10000       } else if (palette_count != 0) {
10001         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10002             (NULL), ("Unsupported palette depth %d", depth));
10003       }
10004
10005       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10006           QT_UINT16 (stsd_entry_data + offset + 32));
10007
10008       esds = NULL;
10009       pasp = NULL;
10010       colr = NULL;
10011       fiel = NULL;
10012       /* pick 'the' stsd child */
10013       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10014       if (!stream->protected) {
10015         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10016           mp4v = NULL;
10017         }
10018       } else {
10019         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10020           mp4v = NULL;
10021         }
10022       }
10023
10024       if (mp4v) {
10025         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10026         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10027         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10028         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10029       }
10030
10031       if (pasp) {
10032         const guint8 *pasp_data = (const guint8 *) pasp->data;
10033         gint len = QT_UINT32 (pasp_data);
10034
10035         if (len == 16) {
10036           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10037           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10038         } else {
10039           CUR_STREAM (stream)->par_w = 0;
10040           CUR_STREAM (stream)->par_h = 0;
10041         }
10042       } else {
10043         CUR_STREAM (stream)->par_w = 0;
10044         CUR_STREAM (stream)->par_h = 0;
10045       }
10046
10047       if (fiel) {
10048         const guint8 *fiel_data = (const guint8 *) fiel->data;
10049         gint len = QT_UINT32 (fiel_data);
10050
10051         if (len == 10) {
10052           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10053           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10054         }
10055       }
10056
10057       if (colr) {
10058         const guint8 *colr_data = (const guint8 *) colr->data;
10059         gint len = QT_UINT32 (colr_data);
10060
10061         if (len == 19 || len == 18) {
10062           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10063
10064           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10065             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10066             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10067             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10068             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10069
10070             switch (primaries) {
10071               case 1:
10072                 CUR_STREAM (stream)->colorimetry.primaries =
10073                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10074                 break;
10075               case 5:
10076                 CUR_STREAM (stream)->colorimetry.primaries =
10077                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10078                 break;
10079               case 6:
10080                 CUR_STREAM (stream)->colorimetry.primaries =
10081                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10082                 break;
10083               case 9:
10084                 CUR_STREAM (stream)->colorimetry.primaries =
10085                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10086                 break;
10087               default:
10088                 break;
10089             }
10090
10091             switch (transfer_function) {
10092               case 1:
10093                 CUR_STREAM (stream)->colorimetry.transfer =
10094                     GST_VIDEO_TRANSFER_BT709;
10095                 break;
10096               case 7:
10097                 CUR_STREAM (stream)->colorimetry.transfer =
10098                     GST_VIDEO_TRANSFER_SMPTE240M;
10099                 break;
10100               default:
10101                 break;
10102             }
10103
10104             switch (matrix) {
10105               case 1:
10106                 CUR_STREAM (stream)->colorimetry.matrix =
10107                     GST_VIDEO_COLOR_MATRIX_BT709;
10108                 break;
10109               case 6:
10110                 CUR_STREAM (stream)->colorimetry.matrix =
10111                     GST_VIDEO_COLOR_MATRIX_BT601;
10112                 break;
10113               case 7:
10114                 CUR_STREAM (stream)->colorimetry.matrix =
10115                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10116                 break;
10117               case 9:
10118                 CUR_STREAM (stream)->colorimetry.matrix =
10119                     GST_VIDEO_COLOR_MATRIX_BT2020;
10120                 break;
10121               default:
10122                 break;
10123             }
10124
10125             CUR_STREAM (stream)->colorimetry.range =
10126                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10127                 GST_VIDEO_COLOR_RANGE_16_235;
10128           } else {
10129             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10130           }
10131         } else {
10132           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10133         }
10134       }
10135
10136       if (esds) {
10137         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10138             stream->stream_tags);
10139       } else {
10140         switch (fourcc) {
10141           case FOURCC_H264:
10142           case FOURCC_avc1:
10143           case FOURCC_avc3:
10144           {
10145             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10146             const guint8 *avc_data = stsd_entry_data + 0x56;
10147
10148             /* find avcC */
10149             while (len >= 0x8) {
10150               gint size;
10151
10152               if (QT_UINT32 (avc_data) <= len)
10153                 size = QT_UINT32 (avc_data) - 0x8;
10154               else
10155                 size = len - 0x8;
10156
10157               if (size < 1)
10158                 /* No real data, so break out */
10159                 break;
10160
10161               switch (QT_FOURCC (avc_data + 0x4)) {
10162                 case FOURCC_avcC:
10163                 {
10164                   /* parse, if found */
10165                   GstBuffer *buf;
10166
10167                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10168
10169                   /* First 4 bytes are the length of the atom, the next 4 bytes
10170                    * are the fourcc, the next 1 byte is the version, and the
10171                    * subsequent bytes are profile_tier_level structure like data. */
10172                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10173                       avc_data + 8 + 1, size - 1);
10174                   buf = gst_buffer_new_and_alloc (size);
10175                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10176                   gst_caps_set_simple (entry->caps,
10177                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10178                   gst_buffer_unref (buf);
10179
10180                   break;
10181                 }
10182                 case FOURCC_strf:
10183                 {
10184                   GstBuffer *buf;
10185
10186                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10187
10188                   /* First 4 bytes are the length of the atom, the next 4 bytes
10189                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10190                    * next 1 byte is the version, and the
10191                    * subsequent bytes are sequence parameter set like data. */
10192
10193                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10194                   if (size > 1) {
10195                     gst_codec_utils_h264_caps_set_level_and_profile
10196                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10197
10198                     buf = gst_buffer_new_and_alloc (size);
10199                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10200                     gst_caps_set_simple (entry->caps,
10201                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10202                     gst_buffer_unref (buf);
10203                   }
10204                   break;
10205                 }
10206                 case FOURCC_btrt:
10207                 {
10208                   guint avg_bitrate, max_bitrate;
10209
10210                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10211                   if (size < 12)
10212                     break;
10213
10214                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10215                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10216
10217                   if (!max_bitrate && !avg_bitrate)
10218                     break;
10219
10220                   /* Some muxers seem to swap the average and maximum bitrates
10221                    * (I'm looking at you, YouTube), so we swap for sanity. */
10222                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10223                     guint temp = avg_bitrate;
10224
10225                     avg_bitrate = max_bitrate;
10226                     max_bitrate = temp;
10227                   }
10228
10229                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10230                     gst_tag_list_add (stream->stream_tags,
10231                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10232                         max_bitrate, NULL);
10233                   }
10234                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10235                     gst_tag_list_add (stream->stream_tags,
10236                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10237                         NULL);
10238                   }
10239
10240                   break;
10241                 }
10242
10243                 default:
10244                   break;
10245               }
10246
10247               len -= size + 8;
10248               avc_data += size + 8;
10249             }
10250
10251             break;
10252           }
10253           case FOURCC_H265:
10254           case FOURCC_hvc1:
10255           case FOURCC_hev1:
10256           {
10257             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10258             const guint8 *hevc_data = stsd_entry_data + 0x56;
10259
10260             /* find hevc */
10261             while (len >= 0x8) {
10262               gint size;
10263
10264               if (QT_UINT32 (hevc_data) <= len)
10265                 size = QT_UINT32 (hevc_data) - 0x8;
10266               else
10267                 size = len - 0x8;
10268
10269               if (size < 1)
10270                 /* No real data, so break out */
10271                 break;
10272
10273               switch (QT_FOURCC (hevc_data + 0x4)) {
10274                 case FOURCC_hvcC:
10275                 {
10276                   /* parse, if found */
10277                   GstBuffer *buf;
10278
10279                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10280
10281                   /* First 4 bytes are the length of the atom, the next 4 bytes
10282                    * are the fourcc, the next 1 byte is the version, and the
10283                    * subsequent bytes are sequence parameter set like data. */
10284                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10285                       (entry->caps, hevc_data + 8 + 1, size - 1);
10286
10287                   buf = gst_buffer_new_and_alloc (size);
10288                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10289                   gst_caps_set_simple (entry->caps,
10290                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10291                   gst_buffer_unref (buf);
10292                   break;
10293                 }
10294                 default:
10295                   break;
10296               }
10297               len -= size + 8;
10298               hevc_data += size + 8;
10299             }
10300             break;
10301           }
10302           case FOURCC_mp4v:
10303           case FOURCC_MP4V:
10304           case FOURCC_fmp4:
10305           case FOURCC_FMP4:
10306           case FOURCC_xvid:
10307           case FOURCC_XVID:
10308           {
10309             GNode *glbl;
10310
10311             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10312                 GST_FOURCC_ARGS (fourcc));
10313
10314             /* codec data might be in glbl extension atom */
10315             glbl = mp4v ?
10316                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10317             if (glbl) {
10318               guint8 *data;
10319               GstBuffer *buf;
10320               gint len;
10321
10322               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10323               data = glbl->data;
10324               len = QT_UINT32 (data);
10325               if (len > 0x8) {
10326                 len -= 0x8;
10327                 buf = gst_buffer_new_and_alloc (len);
10328                 gst_buffer_fill (buf, 0, data + 8, len);
10329                 gst_caps_set_simple (entry->caps,
10330                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10331                 gst_buffer_unref (buf);
10332               }
10333             }
10334             break;
10335           }
10336           case FOURCC_mjp2:
10337           {
10338             /* see annex I of the jpeg2000 spec */
10339             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10340             const guint8 *data;
10341             const gchar *colorspace = NULL;
10342             gint ncomp = 0;
10343             guint32 ncomp_map = 0;
10344             gint32 *comp_map = NULL;
10345             guint32 nchan_def = 0;
10346             gint32 *chan_def = NULL;
10347
10348             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10349             /* some required atoms */
10350             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10351             if (!mjp2)
10352               break;
10353             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10354             if (!jp2h)
10355               break;
10356
10357             /* number of components; redundant with info in codestream, but useful
10358                to a muxer */
10359             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10360             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10361               break;
10362             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10363
10364             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10365             if (!colr)
10366               break;
10367             GST_DEBUG_OBJECT (qtdemux, "found colr");
10368             /* extract colour space info */
10369             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10370               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10371                 case 16:
10372                   colorspace = "sRGB";
10373                   break;
10374                 case 17:
10375                   colorspace = "GRAY";
10376                   break;
10377                 case 18:
10378                   colorspace = "sYUV";
10379                   break;
10380                 default:
10381                   colorspace = NULL;
10382                   break;
10383               }
10384             }
10385             if (!colorspace)
10386               /* colr is required, and only values 16, 17, and 18 are specified,
10387                  so error if we have no colorspace */
10388               break;
10389
10390             /* extract component mapping */
10391             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10392             if (cmap) {
10393               guint32 cmap_len = 0;
10394               int i;
10395               cmap_len = QT_UINT32 (cmap->data);
10396               if (cmap_len >= 8) {
10397                 /* normal box, subtract off header */
10398                 cmap_len -= 8;
10399                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10400                 if (cmap_len % 4 == 0) {
10401                   ncomp_map = (cmap_len / 4);
10402                   comp_map = g_new0 (gint32, ncomp_map);
10403                   for (i = 0; i < ncomp_map; i++) {
10404                     guint16 cmp;
10405                     guint8 mtyp, pcol;
10406                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10407                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10408                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10409                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10410                   }
10411                 }
10412               }
10413             }
10414             /* extract channel definitions */
10415             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10416             if (cdef) {
10417               guint32 cdef_len = 0;
10418               int i;
10419               cdef_len = QT_UINT32 (cdef->data);
10420               if (cdef_len >= 10) {
10421                 /* normal box, subtract off header and len */
10422                 cdef_len -= 10;
10423                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10424                 if (cdef_len % 6 == 0) {
10425                   nchan_def = (cdef_len / 6);
10426                   chan_def = g_new0 (gint32, nchan_def);
10427                   for (i = 0; i < nchan_def; i++)
10428                     chan_def[i] = -1;
10429                   for (i = 0; i < nchan_def; i++) {
10430                     guint16 cn, typ, asoc;
10431                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10432                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10433                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10434                     if (cn < nchan_def) {
10435                       switch (typ) {
10436                         case 0:
10437                           chan_def[cn] = asoc;
10438                           break;
10439                         case 1:
10440                           chan_def[cn] = 0;     /* alpha */
10441                           break;
10442                         default:
10443                           chan_def[cn] = -typ;
10444                       }
10445                     }
10446                   }
10447                 }
10448               }
10449             }
10450
10451             gst_caps_set_simple (entry->caps,
10452                 "num-components", G_TYPE_INT, ncomp, NULL);
10453             gst_caps_set_simple (entry->caps,
10454                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10455
10456             if (comp_map) {
10457               GValue arr = { 0, };
10458               GValue elt = { 0, };
10459               int i;
10460               g_value_init (&arr, GST_TYPE_ARRAY);
10461               g_value_init (&elt, G_TYPE_INT);
10462               for (i = 0; i < ncomp_map; i++) {
10463                 g_value_set_int (&elt, comp_map[i]);
10464                 gst_value_array_append_value (&arr, &elt);
10465               }
10466               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10467                   "component-map", &arr);
10468               g_value_unset (&elt);
10469               g_value_unset (&arr);
10470               g_free (comp_map);
10471             }
10472
10473             if (chan_def) {
10474               GValue arr = { 0, };
10475               GValue elt = { 0, };
10476               int i;
10477               g_value_init (&arr, GST_TYPE_ARRAY);
10478               g_value_init (&elt, G_TYPE_INT);
10479               for (i = 0; i < nchan_def; i++) {
10480                 g_value_set_int (&elt, chan_def[i]);
10481                 gst_value_array_append_value (&arr, &elt);
10482               }
10483               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10484                   "channel-definitions", &arr);
10485               g_value_unset (&elt);
10486               g_value_unset (&arr);
10487               g_free (chan_def);
10488             }
10489
10490             /* some optional atoms */
10491             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10492             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10493
10494             /* indicate possible fields in caps */
10495             if (field) {
10496               data = (guint8 *) field->data + 8;
10497               if (*data != 1)
10498                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10499                     (gint) * data, NULL);
10500             }
10501             /* add codec_data if provided */
10502             if (prefix) {
10503               GstBuffer *buf;
10504               gint len;
10505
10506               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10507               data = prefix->data;
10508               len = QT_UINT32 (data);
10509               if (len > 0x8) {
10510                 len -= 0x8;
10511                 buf = gst_buffer_new_and_alloc (len);
10512                 gst_buffer_fill (buf, 0, data + 8, len);
10513                 gst_caps_set_simple (entry->caps,
10514                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10515                 gst_buffer_unref (buf);
10516               }
10517             }
10518             break;
10519           }
10520           case FOURCC_SVQ3:
10521           case FOURCC_VP31:
10522           {
10523             GstBuffer *buf;
10524             GstBuffer *seqh = NULL;
10525             const guint8 *gamma_data = NULL;
10526             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10527
10528             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10529                 &seqh);
10530             if (gamma_data) {
10531               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10532                   QT_FP32 (gamma_data), NULL);
10533             }
10534             if (seqh) {
10535               /* sorry for the bad name, but we don't know what this is, other
10536                * than its own fourcc */
10537               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10538                   NULL);
10539               gst_buffer_unref (seqh);
10540             }
10541
10542             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10543             buf = gst_buffer_new_and_alloc (len);
10544             gst_buffer_fill (buf, 0, stsd_data, len);
10545             gst_caps_set_simple (entry->caps,
10546                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10547             gst_buffer_unref (buf);
10548             break;
10549           }
10550           case FOURCC_jpeg:
10551           {
10552             /* https://developer.apple.com/standards/qtff-2001.pdf,
10553              * page 92, "Video Sample Description", under table 3.1 */
10554             GstByteReader br;
10555
10556             const gint compressor_offset =
10557                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10558             const gint min_size = compressor_offset + 32 + 2 + 2;
10559             GNode *jpeg;
10560             guint32 len;
10561             guint16 color_table_id = 0;
10562             gboolean ok;
10563
10564             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10565
10566             /* recover information on interlaced/progressive */
10567             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10568             if (!jpeg)
10569               break;
10570
10571             len = QT_UINT32 (jpeg->data);
10572             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10573                 min_size);
10574             if (len >= min_size) {
10575               gst_byte_reader_init (&br, jpeg->data, len);
10576
10577               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10578               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10579               if (color_table_id != 0) {
10580                 /* the spec says there can be concatenated chunks in the data, and we want
10581                  * to find one called field. Walk through them. */
10582                 gint offset = min_size;
10583                 while (offset + 8 < len) {
10584                   guint32 size = 0, tag;
10585                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10586                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10587                   if (!ok || size < 8) {
10588                     GST_WARNING_OBJECT (qtdemux,
10589                         "Failed to walk optional chunk list");
10590                     break;
10591                   }
10592                   GST_DEBUG_OBJECT (qtdemux,
10593                       "Found optional %4.4s chunk, size %u",
10594                       (const char *) &tag, size);
10595                   if (tag == FOURCC_fiel) {
10596                     guint8 n_fields = 0, ordering = 0;
10597                     gst_byte_reader_get_uint8 (&br, &n_fields);
10598                     gst_byte_reader_get_uint8 (&br, &ordering);
10599                     if (n_fields == 1 || n_fields == 2) {
10600                       GST_DEBUG_OBJECT (qtdemux,
10601                           "Found fiel tag with %u fields, ordering %u",
10602                           n_fields, ordering);
10603                       if (n_fields == 2)
10604                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10605                             "interlace-mode", G_TYPE_STRING, "interleaved",
10606                             NULL);
10607                     } else {
10608                       GST_WARNING_OBJECT (qtdemux,
10609                           "Found fiel tag with invalid fields (%u)", n_fields);
10610                     }
10611                   }
10612                   offset += size;
10613                 }
10614               } else {
10615                 GST_DEBUG_OBJECT (qtdemux,
10616                     "Color table ID is 0, not trying to get interlacedness");
10617               }
10618             } else {
10619               GST_WARNING_OBJECT (qtdemux,
10620                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10621             }
10622
10623             break;
10624           }
10625           case FOURCC_rle_:
10626           case FOURCC_WRLE:
10627           {
10628             gst_caps_set_simple (entry->caps,
10629                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 82),
10630                 NULL);
10631             break;
10632           }
10633           case FOURCC_XiTh:
10634           {
10635             GNode *xith, *xdxt;
10636
10637             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10638             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10639             if (!xith)
10640               break;
10641
10642             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10643             if (!xdxt)
10644               break;
10645
10646             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10647             /* collect the headers and store them in a stream list so that we can
10648              * send them out first */
10649             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10650             break;
10651           }
10652           case FOURCC_ovc1:
10653           {
10654             GNode *ovc1;
10655             guint8 *ovc1_data;
10656             guint ovc1_len;
10657             GstBuffer *buf;
10658
10659             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10660             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10661             if (!ovc1)
10662               break;
10663             ovc1_data = ovc1->data;
10664             ovc1_len = QT_UINT32 (ovc1_data);
10665             if (ovc1_len <= 198) {
10666               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10667               break;
10668             }
10669             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10670             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10671             gst_caps_set_simple (entry->caps,
10672                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10673             gst_buffer_unref (buf);
10674             break;
10675           }
10676           case FOURCC_vc_1:
10677           {
10678             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10679             const guint8 *vc1_data = stsd_entry_data + 0x56;
10680
10681             /* find dvc1 */
10682             while (len >= 8) {
10683               gint size;
10684
10685               if (QT_UINT32 (vc1_data) <= len)
10686                 size = QT_UINT32 (vc1_data) - 8;
10687               else
10688                 size = len - 8;
10689
10690               if (size < 1)
10691                 /* No real data, so break out */
10692                 break;
10693
10694               switch (QT_FOURCC (vc1_data + 0x4)) {
10695                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10696                 {
10697                   GstBuffer *buf;
10698
10699                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10700                   buf = gst_buffer_new_and_alloc (size);
10701                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10702                   gst_caps_set_simple (entry->caps,
10703                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10704                   gst_buffer_unref (buf);
10705                   break;
10706                 }
10707                 default:
10708                   break;
10709               }
10710               len -= size + 8;
10711               vc1_data += size + 8;
10712             }
10713             break;
10714           }
10715           default:
10716             break;
10717         }
10718       }
10719
10720       GST_INFO_OBJECT (qtdemux,
10721           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10722           GST_FOURCC_ARGS (fourcc), entry->caps);
10723
10724     } else if (stream->subtype == FOURCC_soun) {
10725       int version, samplesize;
10726       guint16 compression_id;
10727       gboolean amrwb = FALSE;
10728
10729       offset = 16;
10730       /* sample description entry (16) + sound sample description v0 (20) */
10731       if (len < 36)
10732         goto corrupt_file;
10733
10734       version = QT_UINT32 (stsd_entry_data + offset);
10735       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10736       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10737       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10738       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10739
10740       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10741       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10742           QT_UINT32 (stsd_entry_data + offset + 4));
10743       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10744       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10745       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10746       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10747           QT_UINT16 (stsd_entry_data + offset + 14));
10748       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10749
10750       if (compression_id == 0xfffe)
10751         entry->sampled = TRUE;
10752
10753       /* first assume uncompressed audio */
10754       entry->bytes_per_sample = samplesize / 8;
10755       entry->samples_per_frame = entry->n_channels;
10756       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10757       entry->samples_per_packet = entry->samples_per_frame;
10758       entry->bytes_per_packet = entry->bytes_per_sample;
10759
10760       offset = 36;
10761       switch (fourcc) {
10762           /* Yes, these have to be hard-coded */
10763         case FOURCC_MAC6:
10764         {
10765           entry->samples_per_packet = 6;
10766           entry->bytes_per_packet = 1;
10767           entry->bytes_per_frame = 1 * entry->n_channels;
10768           entry->bytes_per_sample = 1;
10769           entry->samples_per_frame = 6 * entry->n_channels;
10770           break;
10771         }
10772         case FOURCC_MAC3:
10773         {
10774           entry->samples_per_packet = 3;
10775           entry->bytes_per_packet = 1;
10776           entry->bytes_per_frame = 1 * entry->n_channels;
10777           entry->bytes_per_sample = 1;
10778           entry->samples_per_frame = 3 * entry->n_channels;
10779           break;
10780         }
10781         case FOURCC_ima4:
10782         {
10783           entry->samples_per_packet = 64;
10784           entry->bytes_per_packet = 34;
10785           entry->bytes_per_frame = 34 * entry->n_channels;
10786           entry->bytes_per_sample = 2;
10787           entry->samples_per_frame = 64 * entry->n_channels;
10788           break;
10789         }
10790         case FOURCC_ulaw:
10791         case FOURCC_alaw:
10792         {
10793           entry->samples_per_packet = 1;
10794           entry->bytes_per_packet = 1;
10795           entry->bytes_per_frame = 1 * entry->n_channels;
10796           entry->bytes_per_sample = 1;
10797           entry->samples_per_frame = 1 * entry->n_channels;
10798           break;
10799         }
10800         case FOURCC_agsm:
10801         {
10802           entry->samples_per_packet = 160;
10803           entry->bytes_per_packet = 33;
10804           entry->bytes_per_frame = 33 * entry->n_channels;
10805           entry->bytes_per_sample = 2;
10806           entry->samples_per_frame = 160 * entry->n_channels;
10807           break;
10808         }
10809         default:
10810           break;
10811       }
10812
10813       if (version == 0x00010000) {
10814         /* sample description entry (16) + sound sample description v1 (20+16) */
10815         if (len < 52)
10816           goto corrupt_file;
10817
10818         switch (fourcc) {
10819           case FOURCC_twos:
10820           case FOURCC_sowt:
10821           case FOURCC_raw_:
10822             break;
10823           default:
10824           {
10825             /* only parse extra decoding config for non-pcm audio */
10826             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10827             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10828             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10829             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10830
10831             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10832                 entry->samples_per_packet);
10833             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10834                 entry->bytes_per_packet);
10835             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10836                 entry->bytes_per_frame);
10837             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10838                 entry->bytes_per_sample);
10839
10840             if (!entry->sampled && entry->bytes_per_packet) {
10841               entry->samples_per_frame = (entry->bytes_per_frame /
10842                   entry->bytes_per_packet) * entry->samples_per_packet;
10843               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10844                   entry->samples_per_frame);
10845             }
10846             break;
10847           }
10848         }
10849       } else if (version == 0x00020000) {
10850         union
10851         {
10852           gdouble fp;
10853           guint64 val;
10854         } qtfp;
10855
10856         /* sample description entry (16) + sound sample description v2 (56) */
10857         if (len < 72)
10858           goto corrupt_file;
10859
10860         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
10861         entry->rate = qtfp.fp;
10862         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
10863
10864         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10865         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
10866         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
10867         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10868             QT_UINT32 (stsd_entry_data + offset + 20));
10869         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10870             QT_UINT32 (stsd_entry_data + offset + 24));
10871         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10872             QT_UINT32 (stsd_entry_data + offset + 28));
10873         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10874             QT_UINT32 (stsd_entry_data + offset + 32));
10875       } else if (version != 0x00000) {
10876         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
10877             version);
10878       }
10879
10880       if (entry->caps)
10881         gst_caps_unref (entry->caps);
10882
10883       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
10884           stsd_entry_data + 32, len - 16, &codec);
10885
10886       switch (fourcc) {
10887         case FOURCC_in24:
10888         {
10889           GNode *enda;
10890           GNode *in24;
10891
10892           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10893
10894           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10895           if (!enda) {
10896             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10897             if (wave)
10898               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10899           }
10900           if (enda) {
10901             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10902             gst_caps_set_simple (entry->caps,
10903                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
10904                 NULL);
10905           }
10906           break;
10907         }
10908         case FOURCC_owma:
10909         {
10910           const guint8 *owma_data;
10911           const gchar *codec_name = NULL;
10912           guint owma_len;
10913           GstBuffer *buf;
10914           gint version = 1;
10915           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10916           /* FIXME this should also be gst_riff_strf_auds,
10917            * but the latter one is actually missing bits-per-sample :( */
10918           typedef struct
10919           {
10920             gint16 wFormatTag;
10921             gint16 nChannels;
10922             gint32 nSamplesPerSec;
10923             gint32 nAvgBytesPerSec;
10924             gint16 nBlockAlign;
10925             gint16 wBitsPerSample;
10926             gint16 cbSize;
10927           } WAVEFORMATEX;
10928           WAVEFORMATEX *wfex;
10929
10930           GST_DEBUG_OBJECT (qtdemux, "parse owma");
10931           owma_data = stsd_entry_data;
10932           owma_len = QT_UINT32 (owma_data);
10933           if (owma_len <= 54) {
10934             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10935             break;
10936           }
10937           wfex = (WAVEFORMATEX *) (owma_data + 36);
10938           buf = gst_buffer_new_and_alloc (owma_len - 54);
10939           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10940           if (wfex->wFormatTag == 0x0161) {
10941             codec_name = "Windows Media Audio";
10942             version = 2;
10943           } else if (wfex->wFormatTag == 0x0162) {
10944             codec_name = "Windows Media Audio 9 Pro";
10945             version = 3;
10946           } else if (wfex->wFormatTag == 0x0163) {
10947             codec_name = "Windows Media Audio 9 Lossless";
10948             /* is that correct? gstffmpegcodecmap.c is missing it, but
10949              * fluendo codec seems to support it */
10950             version = 4;
10951           }
10952
10953           gst_caps_set_simple (entry->caps,
10954               "codec_data", GST_TYPE_BUFFER, buf,
10955               "wmaversion", G_TYPE_INT, version,
10956               "block_align", G_TYPE_INT,
10957               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
10958               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
10959               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
10960               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
10961           gst_buffer_unref (buf);
10962
10963           if (codec_name) {
10964             g_free (codec);
10965             codec = g_strdup (codec_name);
10966           }
10967           break;
10968         }
10969         case FOURCC_wma_:
10970         {
10971           gint len = QT_UINT32 (stsd_entry_data) - offset;
10972           const guint8 *wfex_data = stsd_entry_data + offset;
10973           const gchar *codec_name = NULL;
10974           gint version = 1;
10975           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10976           /* FIXME this should also be gst_riff_strf_auds,
10977            * but the latter one is actually missing bits-per-sample :( */
10978           typedef struct
10979           {
10980             gint16 wFormatTag;
10981             gint16 nChannels;
10982             gint32 nSamplesPerSec;
10983             gint32 nAvgBytesPerSec;
10984             gint16 nBlockAlign;
10985             gint16 wBitsPerSample;
10986             gint16 cbSize;
10987           } WAVEFORMATEX;
10988           WAVEFORMATEX wfex;
10989
10990           /* FIXME: unify with similar wavformatex parsing code above */
10991           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10992
10993           /* find wfex */
10994           while (len >= 8) {
10995             gint size;
10996
10997             if (QT_UINT32 (wfex_data) <= len)
10998               size = QT_UINT32 (wfex_data) - 8;
10999             else
11000               size = len - 8;
11001
11002             if (size < 1)
11003               /* No real data, so break out */
11004               break;
11005
11006             switch (QT_FOURCC (wfex_data + 4)) {
11007               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11008               {
11009                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11010
11011                 if (size < 8 + 18)
11012                   break;
11013
11014                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11015                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11016                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11017                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11018                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11019                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11020                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11021
11022                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11023                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11024                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11025                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11026                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11027                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11028
11029                 if (wfex.wFormatTag == 0x0161) {
11030                   codec_name = "Windows Media Audio";
11031                   version = 2;
11032                 } else if (wfex.wFormatTag == 0x0162) {
11033                   codec_name = "Windows Media Audio 9 Pro";
11034                   version = 3;
11035                 } else if (wfex.wFormatTag == 0x0163) {
11036                   codec_name = "Windows Media Audio 9 Lossless";
11037                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11038                    * fluendo codec seems to support it */
11039                   version = 4;
11040                 }
11041
11042                 gst_caps_set_simple (entry->caps,
11043                     "wmaversion", G_TYPE_INT, version,
11044                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11045                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11046                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11047                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11048
11049                 if (size > wfex.cbSize) {
11050                   GstBuffer *buf;
11051
11052                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11053                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11054                       size - wfex.cbSize);
11055                   gst_caps_set_simple (entry->caps,
11056                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11057                   gst_buffer_unref (buf);
11058                 } else {
11059                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11060                 }
11061
11062                 if (codec_name) {
11063                   g_free (codec);
11064                   codec = g_strdup (codec_name);
11065                 }
11066                 break;
11067               }
11068               default:
11069                 break;
11070             }
11071             len -= size + 8;
11072             wfex_data += size + 8;
11073           }
11074           break;
11075         }
11076         case FOURCC_opus:
11077         {
11078           const guint8 *opus_data;
11079           guint8 *channel_mapping = NULL;
11080           guint32 rate;
11081           guint8 channels;
11082           guint8 channel_mapping_family;
11083           guint8 stream_count;
11084           guint8 coupled_count;
11085           guint8 i;
11086
11087           opus_data = stsd_entry_data;
11088
11089           channels = GST_READ_UINT8 (opus_data + 45);
11090           rate = GST_READ_UINT32_LE (opus_data + 48);
11091           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11092           stream_count = GST_READ_UINT8 (opus_data + 55);
11093           coupled_count = GST_READ_UINT8 (opus_data + 56);
11094
11095           if (channels > 0) {
11096             channel_mapping = g_malloc (channels * sizeof (guint8));
11097             for (i = 0; i < channels; i++)
11098               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11099           }
11100
11101           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11102               channel_mapping_family, stream_count, coupled_count,
11103               channel_mapping);
11104           break;
11105         }
11106         default:
11107           break;
11108       }
11109
11110       if (codec) {
11111         GstStructure *s;
11112         gint bitrate = 0;
11113
11114         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11115             GST_TAG_AUDIO_CODEC, codec, NULL);
11116         g_free (codec);
11117         codec = NULL;
11118
11119         /* some bitrate info may have ended up in caps */
11120         s = gst_caps_get_structure (entry->caps, 0);
11121         gst_structure_get_int (s, "bitrate", &bitrate);
11122         if (bitrate > 0)
11123           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11124               GST_TAG_BITRATE, bitrate, NULL);
11125       }
11126
11127       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11128       if (!stream->protected) {
11129       } else {
11130         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11131           mp4v = NULL;
11132         }
11133       }
11134       if (stream->protected && fourcc == FOURCC_mp4a) {
11135         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11136           mp4a = NULL;
11137         }
11138       } else {
11139         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11140           mp4a = NULL;
11141         }
11142       }
11143
11144       wave = NULL;
11145       esds = NULL;
11146       if (mp4a) {
11147         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11148         if (wave)
11149           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11150         if (!esds)
11151           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11152       }
11153
11154
11155       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11156          16 bits is a byte-swapped wave-style codec identifier,
11157          and we can find a WAVE header internally to a 'wave' atom here.
11158          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11159          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11160          is big-endian).
11161        */
11162       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11163         if (len < offset + 20) {
11164           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11165         } else {
11166           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11167           const guint8 *data = stsd_entry_data + offset + 16;
11168           GNode *wavenode;
11169           GNode *waveheadernode;
11170
11171           wavenode = g_node_new ((guint8 *) data);
11172           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11173             const guint8 *waveheader;
11174             guint32 headerlen;
11175
11176             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11177             if (waveheadernode) {
11178               waveheader = (const guint8 *) waveheadernode->data;
11179               headerlen = QT_UINT32 (waveheader);
11180
11181               if (headerlen > 8) {
11182                 gst_riff_strf_auds *header = NULL;
11183                 GstBuffer *headerbuf;
11184                 GstBuffer *extra;
11185
11186                 waveheader += 8;
11187                 headerlen -= 8;
11188
11189                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11190                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11191
11192                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11193                         headerbuf, &header, &extra)) {
11194                   gst_caps_unref (entry->caps);
11195                   /* FIXME: Need to do something with the channel reorder map */
11196                   entry->caps =
11197                       gst_riff_create_audio_caps (header->format, NULL, header,
11198                       extra, NULL, NULL, NULL);
11199
11200                   if (extra)
11201                     gst_buffer_unref (extra);
11202                   g_free (header);
11203                 }
11204               }
11205             } else
11206               GST_DEBUG ("Didn't find waveheadernode for this codec");
11207           }
11208           g_node_destroy (wavenode);
11209         }
11210       } else if (esds) {
11211         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11212             stream->stream_tags);
11213       } else {
11214         switch (fourcc) {
11215 #if 0
11216             /* FIXME: what is in the chunk? */
11217           case FOURCC_QDMC:
11218           {
11219             gint len = QT_UINT32 (stsd_data);
11220
11221             /* seems to be always = 116 = 0x74 */
11222             break;
11223           }
11224 #endif
11225           case FOURCC_QDM2:
11226           {
11227             gint len = QT_UINT32 (stsd_entry_data);
11228
11229             if (len > 0x3C) {
11230               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11231
11232               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11233               gst_caps_set_simple (entry->caps,
11234                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11235               gst_buffer_unref (buf);
11236             }
11237             gst_caps_set_simple (entry->caps,
11238                 "samplesize", G_TYPE_INT, samplesize, NULL);
11239             break;
11240           }
11241           case FOURCC_alac:
11242           {
11243             GNode *alac, *wave = NULL;
11244
11245             /* apparently, m4a has this atom appended directly in the stsd entry,
11246              * while mov has it in a wave atom */
11247             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11248             if (alac) {
11249               /* alac now refers to stsd entry atom */
11250               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11251               if (wave)
11252                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11253               else
11254                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11255             }
11256             if (alac) {
11257               const guint8 *alac_data = alac->data;
11258               gint len = QT_UINT32 (alac->data);
11259               GstBuffer *buf;
11260
11261               if (len < 36) {
11262                 GST_DEBUG_OBJECT (qtdemux,
11263                     "discarding alac atom with unexpected len %d", len);
11264               } else {
11265                 /* codec-data contains alac atom size and prefix,
11266                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11267                 buf = gst_buffer_new_and_alloc (len);
11268                 gst_buffer_fill (buf, 0, alac->data, len);
11269                 gst_caps_set_simple (entry->caps,
11270                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11271                 gst_buffer_unref (buf);
11272
11273                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11274                 entry->n_channels = QT_UINT8 (alac_data + 21);
11275                 entry->rate = QT_UINT32 (alac_data + 32);
11276               }
11277             }
11278             gst_caps_set_simple (entry->caps,
11279                 "samplesize", G_TYPE_INT, samplesize, NULL);
11280             break;
11281           }
11282           case FOURCC_fLaC:
11283           {
11284             /* The codingname of the sample entry is 'fLaC' */
11285             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11286
11287             if (flac) {
11288               /* The 'dfLa' box is added to the sample entry to convey
11289                  initializing information for the decoder. */
11290               const GNode *dfla =
11291                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11292
11293               if (dfla) {
11294                 const guint32 len = QT_UINT32 (dfla->data);
11295
11296                 /* Must contain at least dfLa box header (12),
11297                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11298                 if (len < 50) {
11299                   GST_DEBUG_OBJECT (qtdemux,
11300                       "discarding dfla atom with unexpected len %d", len);
11301                 } else {
11302                   /* skip dfLa header to get the METADATA_BLOCKs */
11303                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11304                   const guint32 metadata_blocks_len = len - 12;
11305
11306                   gchar *stream_marker = g_strdup ("fLaC");
11307                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11308                       strlen (stream_marker));
11309
11310                   guint32 index = 0;
11311                   guint32 remainder = 0;
11312                   guint32 block_size = 0;
11313                   gboolean is_last = FALSE;
11314
11315                   GValue array = G_VALUE_INIT;
11316                   GValue value = G_VALUE_INIT;
11317
11318                   g_value_init (&array, GST_TYPE_ARRAY);
11319                   g_value_init (&value, GST_TYPE_BUFFER);
11320
11321                   gst_value_set_buffer (&value, block);
11322                   gst_value_array_append_value (&array, &value);
11323                   g_value_reset (&value);
11324
11325                   gst_buffer_unref (block);
11326
11327                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11328                    * of data, and we haven't already finished parsing */
11329                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11330                     remainder = metadata_blocks_len - index;
11331
11332                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11333                     block_size = 4 +
11334                         (metadata_blocks[index + 1] << 16) +
11335                         (metadata_blocks[index + 2] << 8) +
11336                         metadata_blocks[index + 3];
11337
11338                     /* be careful not to read off end of box */
11339                     if (block_size > remainder) {
11340                       break;
11341                     }
11342
11343                     is_last = metadata_blocks[index] >> 7;
11344
11345                     block = gst_buffer_new_and_alloc (block_size);
11346
11347                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11348                         block_size);
11349
11350                     gst_value_set_buffer (&value, block);
11351                     gst_value_array_append_value (&array, &value);
11352                     g_value_reset (&value);
11353
11354                     gst_buffer_unref (block);
11355
11356                     index += block_size;
11357                   }
11358
11359                   /* only append the metadata if we successfully read all of it */
11360                   if (is_last) {
11361                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11362                             (stream)->caps, 0), "streamheader", &array);
11363                   } else {
11364                     GST_WARNING_OBJECT (qtdemux,
11365                         "discarding all METADATA_BLOCKs due to invalid "
11366                         "block_size %d at idx %d, rem %d", block_size, index,
11367                         remainder);
11368                   }
11369
11370                   g_value_unset (&value);
11371                   g_value_unset (&array);
11372
11373                   /* The sample rate obtained from the stsd may not be accurate
11374                    * since it cannot represent rates greater than 65535Hz, so
11375                    * override that value with the sample rate from the
11376                    * METADATA_BLOCK_STREAMINFO block */
11377                   CUR_STREAM (stream)->rate =
11378                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11379                 }
11380               }
11381             }
11382             break;
11383           }
11384           case FOURCC_sawb:
11385             /* Fallthrough! */
11386             amrwb = TRUE;
11387           case FOURCC_samr:
11388           {
11389             gint len = QT_UINT32 (stsd_entry_data);
11390
11391             if (len > 0x24) {
11392               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11393               guint bitrate;
11394
11395               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11396
11397               /* If we have enough data, let's try to get the 'damr' atom. See
11398                * the 3GPP container spec (26.244) for more details. */
11399               if ((len - 0x34) > 8 &&
11400                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11401                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11402                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11403               }
11404
11405               gst_caps_set_simple (entry->caps,
11406                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11407               gst_buffer_unref (buf);
11408             }
11409             break;
11410           }
11411           case FOURCC_mp4a:
11412           {
11413             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11414             gint len = QT_UINT32 (stsd_entry_data);
11415
11416             if (len >= 34) {
11417               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11418
11419               if (sound_version == 1) {
11420                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11421                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11422                 guint8 codec_data[2];
11423                 GstBuffer *buf;
11424                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11425
11426                 gint sample_rate_index =
11427                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11428
11429                 /* build AAC codec data */
11430                 codec_data[0] = profile << 3;
11431                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11432                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11433                 codec_data[1] |= (channels & 0xF) << 3;
11434
11435                 buf = gst_buffer_new_and_alloc (2);
11436                 gst_buffer_fill (buf, 0, codec_data, 2);
11437                 gst_caps_set_simple (entry->caps,
11438                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11439                 gst_buffer_unref (buf);
11440               }
11441             }
11442             break;
11443           }
11444           default:
11445             GST_INFO_OBJECT (qtdemux,
11446                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11447             break;
11448         }
11449       }
11450       GST_INFO_OBJECT (qtdemux,
11451           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11452           GST_FOURCC_ARGS (fourcc), entry->caps);
11453
11454     } else if (stream->subtype == FOURCC_strm) {
11455       if (fourcc == FOURCC_rtsp) {
11456         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11457       } else {
11458         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11459             GST_FOURCC_ARGS (fourcc));
11460         goto unknown_stream;
11461       }
11462       entry->sampled = TRUE;
11463     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11464         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11465
11466       entry->sampled = TRUE;
11467       entry->sparse = TRUE;
11468
11469       entry->caps =
11470           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11471           &codec);
11472       if (codec) {
11473         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11474             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11475         g_free (codec);
11476         codec = NULL;
11477       }
11478
11479       /* hunt for sort-of codec data */
11480       switch (fourcc) {
11481         case FOURCC_mp4s:
11482         {
11483           GNode *mp4s = NULL;
11484           GNode *esds = NULL;
11485
11486           /* look for palette in a stsd->mp4s->esds sub-atom */
11487           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11488           if (mp4s)
11489             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11490           if (esds == NULL) {
11491             /* Invalid STSD */
11492             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11493             break;
11494           }
11495
11496           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11497               stream->stream_tags);
11498           break;
11499         }
11500         default:
11501           GST_INFO_OBJECT (qtdemux,
11502               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11503           break;
11504       }
11505       GST_INFO_OBJECT (qtdemux,
11506           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11507           GST_FOURCC_ARGS (fourcc), entry->caps);
11508     } else {
11509       /* everything in 1 sample */
11510       entry->sampled = TRUE;
11511
11512       entry->caps =
11513           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11514           &codec);
11515
11516       if (entry->caps == NULL)
11517         goto unknown_stream;
11518
11519       if (codec) {
11520         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11521             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11522         g_free (codec);
11523         codec = NULL;
11524       }
11525     }
11526
11527     /* promote to sampled format */
11528     if (entry->fourcc == FOURCC_samr) {
11529       /* force mono 8000 Hz for AMR */
11530       entry->sampled = TRUE;
11531       entry->n_channels = 1;
11532       entry->rate = 8000;
11533     } else if (entry->fourcc == FOURCC_sawb) {
11534       /* force mono 16000 Hz for AMR-WB */
11535       entry->sampled = TRUE;
11536       entry->n_channels = 1;
11537       entry->rate = 16000;
11538     } else if (entry->fourcc == FOURCC_mp4a) {
11539       entry->sampled = TRUE;
11540     }
11541
11542
11543     stsd_entry_data += len;
11544     remaining_stsd_len -= len;
11545
11546   }
11547
11548   /* collect sample information */
11549   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11550     goto samples_failed;
11551
11552   if (qtdemux->fragmented) {
11553     guint64 offset;
11554
11555     /* need all moov samples as basis; probably not many if any at all */
11556     /* prevent moof parsing taking of at this time */
11557     offset = qtdemux->moof_offset;
11558     qtdemux->moof_offset = 0;
11559     if (stream->n_samples &&
11560         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11561       qtdemux->moof_offset = offset;
11562       goto samples_failed;
11563     }
11564     qtdemux->moof_offset = 0;
11565     /* movie duration more reliable in this case (e.g. mehd) */
11566     if (qtdemux->segment.duration &&
11567         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11568       stream->duration =
11569           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11570   }
11571
11572   /* configure segments */
11573   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11574     goto segments_failed;
11575
11576   /* add some language tag, if useful */
11577   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11578       strcmp (stream->lang_id, "und")) {
11579     const gchar *lang_code;
11580
11581     /* convert ISO 639-2 code to ISO 639-1 */
11582     lang_code = gst_tag_get_language_code (stream->lang_id);
11583     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11584         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11585   }
11586
11587   /* Check for UDTA tags */
11588   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11589     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11590   }
11591
11592   /* now we are ready to add the stream */
11593   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11594     goto too_many_streams;
11595
11596   if (!qtdemux->got_moov) {
11597     qtdemux->streams[qtdemux->n_streams] = stream;
11598     qtdemux->n_streams++;
11599     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11600   }
11601
11602   return TRUE;
11603
11604 /* ERRORS */
11605 skip_track:
11606   {
11607     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11608     if (new_stream)
11609       gst_qtdemux_stream_free (qtdemux, stream);
11610     return TRUE;
11611   }
11612 corrupt_file:
11613   {
11614     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11615         (_("This file is corrupt and cannot be played.")), (NULL));
11616     if (new_stream)
11617       gst_qtdemux_stream_free (qtdemux, stream);
11618     return FALSE;
11619   }
11620 error_encrypted:
11621   {
11622     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11623     if (new_stream)
11624       gst_qtdemux_stream_free (qtdemux, stream);
11625     return FALSE;
11626   }
11627 samples_failed:
11628 segments_failed:
11629   {
11630     /* we posted an error already */
11631     /* free stbl sub-atoms */
11632     gst_qtdemux_stbl_free (stream);
11633     if (new_stream)
11634       gst_qtdemux_stream_free (qtdemux, stream);
11635     return FALSE;
11636   }
11637 existing_stream:
11638   {
11639     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11640         track_id);
11641     if (new_stream)
11642       gst_qtdemux_stream_free (qtdemux, stream);
11643     return TRUE;
11644   }
11645 unknown_stream:
11646   {
11647     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11648         GST_FOURCC_ARGS (stream->subtype));
11649     if (new_stream)
11650       gst_qtdemux_stream_free (qtdemux, stream);
11651     return TRUE;
11652   }
11653 too_many_streams:
11654   {
11655     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11656         (_("This file contains too many streams. Only playing first %d"),
11657             GST_QTDEMUX_MAX_STREAMS), (NULL));
11658     return TRUE;
11659   }
11660 }
11661
11662 /* If we can estimate the overall bitrate, and don't have information about the
11663  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11664  * the overall bitrate minus the sum of the bitrates of all other streams. This
11665  * should be useful for the common case where we have one audio and one video
11666  * stream and can estimate the bitrate of one, but not the other. */
11667 static void
11668 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11669 {
11670   QtDemuxStream *stream = NULL;
11671   gint64 size, sys_bitrate, sum_bitrate = 0;
11672   GstClockTime duration;
11673   gint i;
11674   guint bitrate;
11675
11676   if (qtdemux->fragmented)
11677     return;
11678
11679   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11680
11681   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11682       || size <= 0) {
11683     GST_DEBUG_OBJECT (qtdemux,
11684         "Size in bytes of the stream not known - bailing");
11685     return;
11686   }
11687
11688   /* Subtract the header size */
11689   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11690       size, qtdemux->header_size);
11691
11692   if (size < qtdemux->header_size)
11693     return;
11694
11695   size = size - qtdemux->header_size;
11696
11697   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11698     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11699     return;
11700   }
11701
11702   for (i = 0; i < qtdemux->n_streams; i++) {
11703     switch (qtdemux->streams[i]->subtype) {
11704       case FOURCC_soun:
11705       case FOURCC_vide:
11706         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11707             CUR_STREAM (qtdemux->streams[i])->caps);
11708         /* retrieve bitrate, prefer avg then max */
11709         bitrate = 0;
11710         if (qtdemux->streams[i]->stream_tags) {
11711           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11712               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11713           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11714           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11715               GST_TAG_NOMINAL_BITRATE, &bitrate);
11716           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11717           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11718               GST_TAG_BITRATE, &bitrate);
11719           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11720         }
11721         if (bitrate)
11722           sum_bitrate += bitrate;
11723         else {
11724           if (stream) {
11725             GST_DEBUG_OBJECT (qtdemux,
11726                 ">1 stream with unknown bitrate - bailing");
11727             return;
11728           } else
11729             stream = qtdemux->streams[i];
11730         }
11731
11732       default:
11733         /* For other subtypes, we assume no significant impact on bitrate */
11734         break;
11735     }
11736   }
11737
11738   if (!stream) {
11739     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11740     return;
11741   }
11742
11743   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11744
11745   if (sys_bitrate < sum_bitrate) {
11746     /* This can happen, since sum_bitrate might be derived from maximum
11747      * bitrates and not average bitrates */
11748     GST_DEBUG_OBJECT (qtdemux,
11749         "System bitrate less than sum bitrate - bailing");
11750     return;
11751   }
11752
11753   bitrate = sys_bitrate - sum_bitrate;
11754   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11755       ", Stream bitrate = %u", sys_bitrate, bitrate);
11756
11757   if (!stream->stream_tags)
11758     stream->stream_tags = gst_tag_list_new_empty ();
11759   else
11760     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11761
11762   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11763       GST_TAG_BITRATE, bitrate, NULL);
11764 }
11765
11766 static GstFlowReturn
11767 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11768 {
11769   gint i;
11770   GstFlowReturn ret = GST_FLOW_OK;
11771
11772   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11773
11774   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11775     QtDemuxStream *stream = qtdemux->streams[i];
11776     guint32 sample_num = 0;
11777
11778     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11779         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11780
11781     if (qtdemux->fragmented) {
11782       /* need all moov samples first */
11783       GST_OBJECT_LOCK (qtdemux);
11784       while (stream->n_samples == 0)
11785         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11786           break;
11787       GST_OBJECT_UNLOCK (qtdemux);
11788     } else {
11789       /* discard any stray moof */
11790       qtdemux->moof_offset = 0;
11791     }
11792
11793     /* prepare braking */
11794     if (ret != GST_FLOW_ERROR)
11795       ret = GST_FLOW_OK;
11796
11797     /* in pull mode, we should have parsed some sample info by now;
11798      * and quite some code will not handle no samples.
11799      * in push mode, we'll just have to deal with it */
11800     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11801       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11802       gst_qtdemux_remove_stream (qtdemux, i);
11803       i--;
11804       continue;
11805     }
11806
11807     /* parse the initial sample for use in setting the frame rate cap */
11808     while (sample_num == 0 && sample_num < stream->n_samples) {
11809       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11810         break;
11811       ++sample_num;
11812     }
11813     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11814       stream->first_duration = stream->samples[0].duration;
11815       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11816           stream->track_id, stream->first_duration);
11817     }
11818   }
11819
11820   return ret;
11821 }
11822
11823 static GstFlowReturn
11824 qtdemux_expose_streams (GstQTDemux * qtdemux)
11825 {
11826   gint i;
11827   GSList *oldpads = NULL;
11828   GSList *iter;
11829
11830   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11831
11832   for (i = 0; i < qtdemux->n_streams; i++) {
11833     QtDemuxStream *stream = qtdemux->streams[i];
11834     GstPad *oldpad = stream->pad;
11835     GstTagList *list;
11836
11837     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11838         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11839
11840     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11841         stream->track_id == qtdemux->chapters_track_id) {
11842       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11843          so that it doesn't look like a subtitle track */
11844       gst_qtdemux_remove_stream (qtdemux, i);
11845       i--;
11846       continue;
11847     }
11848
11849     /* now we have all info and can expose */
11850     list = stream->stream_tags;
11851     stream->stream_tags = NULL;
11852     if (oldpad)
11853       oldpads = g_slist_prepend (oldpads, oldpad);
11854     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11855       return GST_FLOW_ERROR;
11856   }
11857
11858   gst_qtdemux_guess_bitrate (qtdemux);
11859
11860   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11861
11862   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11863     GstPad *oldpad = iter->data;
11864     GstEvent *event;
11865
11866     event = gst_event_new_eos ();
11867     if (qtdemux->segment_seqnum)
11868       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11869
11870     gst_pad_push_event (oldpad, event);
11871     gst_pad_set_active (oldpad, FALSE);
11872     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11873     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11874     gst_object_unref (oldpad);
11875   }
11876
11877   /* check if we should post a redirect in case there is a single trak
11878    * and it is a redirecting trak */
11879   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11880     GstMessage *m;
11881
11882     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11883         "an external content");
11884     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11885         gst_structure_new ("redirect",
11886             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11887             NULL));
11888     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11889     qtdemux->posted_redirect = TRUE;
11890   }
11891
11892   for (i = 0; i < qtdemux->n_streams; i++) {
11893     QtDemuxStream *stream = qtdemux->streams[i];
11894
11895     qtdemux_do_allocation (qtdemux, stream);
11896   }
11897
11898   qtdemux->exposed = TRUE;
11899   return GST_FLOW_OK;
11900 }
11901
11902 /* check if major or compatible brand is 3GP */
11903 static inline gboolean
11904 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11905 {
11906   if (major) {
11907     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11908         FOURCC_3g__);
11909   } else if (qtdemux->comp_brands != NULL) {
11910     GstMapInfo map;
11911     guint8 *data;
11912     gsize size;
11913     gboolean res = FALSE;
11914
11915     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11916     data = map.data;
11917     size = map.size;
11918     while (size >= 4) {
11919       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11920           FOURCC_3g__);
11921       data += 4;
11922       size -= 4;
11923     }
11924     gst_buffer_unmap (qtdemux->comp_brands, &map);
11925     return res;
11926   } else {
11927     return FALSE;
11928   }
11929 }
11930
11931 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11932 static inline gboolean
11933 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11934 {
11935   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11936       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11937       || fourcc == FOURCC_albm;
11938 }
11939
11940 static void
11941 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11942     const char *tag, const char *dummy, GNode * node)
11943 {
11944   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11945   int offset;
11946   char *name;
11947   gchar *data;
11948   gdouble longitude, latitude, altitude;
11949   gint len;
11950
11951   len = QT_UINT32 (node->data);
11952   if (len <= 14)
11953     goto short_read;
11954
11955   data = node->data;
11956   offset = 14;
11957
11958   /* TODO: language code skipped */
11959
11960   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11961
11962   if (!name) {
11963     /* do not alarm in trivial case, but bail out otherwise */
11964     if (*(data + offset) != 0) {
11965       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11966           "giving up", tag);
11967     }
11968   } else {
11969     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11970         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11971     offset += strlen (name);
11972     g_free (name);
11973   }
11974
11975   if (len < offset + 2 + 4 + 4 + 4)
11976     goto short_read;
11977
11978   /* +1 +1 = skip null-terminator and location role byte */
11979   offset += 1 + 1;
11980   /* table in spec says unsigned, semantics say negative has meaning ... */
11981   longitude = QT_SFP32 (data + offset);
11982
11983   offset += 4;
11984   latitude = QT_SFP32 (data + offset);
11985
11986   offset += 4;
11987   altitude = QT_SFP32 (data + offset);
11988
11989   /* one invalid means all are invalid */
11990   if (longitude >= -180.0 && longitude <= 180.0 &&
11991       latitude >= -90.0 && latitude <= 90.0) {
11992     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11993         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11994         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11995         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11996   }
11997
11998   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11999
12000   return;
12001
12002   /* ERRORS */
12003 short_read:
12004   {
12005     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12006     return;
12007   }
12008 }
12009
12010
12011 static void
12012 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12013     const char *tag, const char *dummy, GNode * node)
12014 {
12015   guint16 y;
12016   GDate *date;
12017   gint len;
12018
12019   len = QT_UINT32 (node->data);
12020   if (len < 14)
12021     return;
12022
12023   y = QT_UINT16 ((guint8 *) node->data + 12);
12024   if (y == 0) {
12025     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12026     return;
12027   }
12028   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12029
12030   date = g_date_new_dmy (1, 1, y);
12031   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12032   g_date_free (date);
12033 }
12034
12035 static void
12036 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12037     const char *tag, const char *dummy, GNode * node)
12038 {
12039   int offset;
12040   char *tag_str = NULL;
12041   guint8 *entity;
12042   guint16 table;
12043   gint len;
12044
12045   len = QT_UINT32 (node->data);
12046   if (len <= 20)
12047     goto short_read;
12048
12049   offset = 12;
12050   entity = (guint8 *) node->data + offset;
12051   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12052     GST_DEBUG_OBJECT (qtdemux,
12053         "classification info: %c%c%c%c invalid classification entity",
12054         entity[0], entity[1], entity[2], entity[3]);
12055     return;
12056   }
12057
12058   offset += 4;
12059   table = QT_UINT16 ((guint8 *) node->data + offset);
12060
12061   /* Language code skipped */
12062
12063   offset += 4;
12064
12065   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12066    * XXXX: classification entity, fixed length 4 chars.
12067    * Y[YYYY]: classification table, max 5 chars.
12068    */
12069   tag_str = g_strdup_printf ("----://%u/%s",
12070       table, (char *) node->data + offset);
12071
12072   /* memcpy To be sure we're preserving byte order */
12073   memcpy (tag_str, entity, 4);
12074   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12075
12076   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12077
12078   g_free (tag_str);
12079
12080   return;
12081
12082   /* ERRORS */
12083 short_read:
12084   {
12085     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12086     return;
12087   }
12088 }
12089
12090 static gboolean
12091 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12092     const char *tag, const char *dummy, GNode * node)
12093 {
12094   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12095   GNode *data;
12096   char *s;
12097   int len;
12098   guint32 type;
12099   int offset;
12100   gboolean ret = TRUE;
12101   const gchar *charset = NULL;
12102
12103   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12104   if (data) {
12105     len = QT_UINT32 (data->data);
12106     type = QT_UINT32 ((guint8 *) data->data + 8);
12107     if (type == 0x00000001 && len > 16) {
12108       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12109           env_vars);
12110       if (s) {
12111         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12112         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12113         g_free (s);
12114       } else {
12115         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12116       }
12117     }
12118   } else {
12119     len = QT_UINT32 (node->data);
12120     type = QT_UINT32 ((guint8 *) node->data + 4);
12121     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12122       gint str_len;
12123       gint lang_code;
12124
12125       /* Type starts with the (C) symbol, so the next data is a list
12126        * of (string size(16), language code(16), string) */
12127
12128       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12129       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12130
12131       /* the string + fourcc + size + 2 16bit fields,
12132        * means that there are more tags in this atom */
12133       if (len > str_len + 8 + 4) {
12134         /* TODO how to represent the same tag in different languages? */
12135         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12136             "text alternatives, reading only first one");
12137       }
12138
12139       offset = 12;
12140       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12141       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12142
12143       if (lang_code < 0x800) {  /* MAC encoded string */
12144         charset = "mac";
12145       }
12146     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12147             QT_FOURCC ((guint8 *) node->data + 4))) {
12148       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12149
12150       /* we go for 3GP style encoding if major brands claims so,
12151        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12152       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12153           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12154               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12155         offset = 14;
12156         /* 16-bit Language code is ignored here as well */
12157         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12158       } else {
12159         goto normal;
12160       }
12161     } else {
12162     normal:
12163       offset = 8;
12164       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12165       ret = FALSE;              /* may have to fallback */
12166     }
12167     if (charset) {
12168       GError *err = NULL;
12169
12170       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12171           charset, NULL, NULL, &err);
12172       if (err) {
12173         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12174             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12175             err->message);
12176         g_error_free (err);
12177       }
12178     } else {
12179       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12180           len - offset, env_vars);
12181     }
12182     if (s) {
12183       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12184       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12185       g_free (s);
12186       ret = TRUE;
12187     } else {
12188       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12189     }
12190   }
12191   return ret;
12192 }
12193
12194 static void
12195 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12196     const char *tag, const char *dummy, GNode * node)
12197 {
12198   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12199 }
12200
12201 static void
12202 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12203     const char *tag, const char *dummy, GNode * node)
12204 {
12205   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12206   guint8 *data;
12207   char *s, *t, *k = NULL;
12208   int len;
12209   int offset;
12210   int count;
12211
12212   /* first try normal string tag if major brand not 3GP */
12213   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12214     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12215       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12216        * let's try it 3gpp way after minor safety check */
12217       data = node->data;
12218       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12219         return;
12220     } else
12221       return;
12222   }
12223
12224   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12225
12226   data = node->data;
12227
12228   len = QT_UINT32 (data);
12229   if (len < 15)
12230     goto short_read;
12231
12232   count = QT_UINT8 (data + 14);
12233   offset = 15;
12234   for (; count; count--) {
12235     gint slen;
12236
12237     if (offset + 1 > len)
12238       goto short_read;
12239     slen = QT_UINT8 (data + offset);
12240     offset += 1;
12241     if (offset + slen > len)
12242       goto short_read;
12243     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12244         slen, env_vars);
12245     if (s) {
12246       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12247       if (k) {
12248         t = g_strjoin (",", k, s, NULL);
12249         g_free (s);
12250         g_free (k);
12251         k = t;
12252       } else {
12253         k = s;
12254       }
12255     } else {
12256       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12257     }
12258     offset += slen;
12259   }
12260
12261 done:
12262   if (k) {
12263     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12264     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12265   }
12266   g_free (k);
12267
12268   return;
12269
12270   /* ERRORS */
12271 short_read:
12272   {
12273     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12274     goto done;
12275   }
12276 }
12277
12278 static void
12279 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12280     const char *tag1, const char *tag2, GNode * node)
12281 {
12282   GNode *data;
12283   int len;
12284   int type;
12285   int n1, n2;
12286
12287   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12288   if (data) {
12289     len = QT_UINT32 (data->data);
12290     type = QT_UINT32 ((guint8 *) data->data + 8);
12291     if (type == 0x00000000 && len >= 22) {
12292       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12293       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12294       if (n1 > 0) {
12295         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12296         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12297       }
12298       if (n2 > 0) {
12299         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12300         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12301       }
12302     }
12303   }
12304 }
12305
12306 static void
12307 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12308     const char *tag1, const char *dummy, GNode * node)
12309 {
12310   GNode *data;
12311   int len;
12312   int type;
12313   int n1;
12314
12315   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12316   if (data) {
12317     len = QT_UINT32 (data->data);
12318     type = QT_UINT32 ((guint8 *) data->data + 8);
12319     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12320     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12321     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12322       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12323       if (n1) {
12324         /* do not add bpm=0 */
12325         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12326         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12327             NULL);
12328       }
12329     }
12330   }
12331 }
12332
12333 static void
12334 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12335     const char *tag1, const char *dummy, GNode * node)
12336 {
12337   GNode *data;
12338   int len;
12339   int type;
12340   guint32 num;
12341
12342   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12343   if (data) {
12344     len = QT_UINT32 (data->data);
12345     type = QT_UINT32 ((guint8 *) data->data + 8);
12346     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12347     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12348     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12349       num = QT_UINT32 ((guint8 *) data->data + 16);
12350       if (num) {
12351         /* do not add num=0 */
12352         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12353         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12354       }
12355     }
12356   }
12357 }
12358
12359 static void
12360 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12361     const char *tag1, const char *dummy, GNode * node)
12362 {
12363   GNode *data;
12364   int len;
12365   int type;
12366   GstSample *sample;
12367
12368   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12369   if (data) {
12370     len = QT_UINT32 (data->data);
12371     type = QT_UINT32 ((guint8 *) data->data + 8);
12372     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12373     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12374       GstTagImageType image_type;
12375
12376       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12377         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12378       else
12379         image_type = GST_TAG_IMAGE_TYPE_NONE;
12380
12381       if ((sample =
12382               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12383                   len - 16, image_type))) {
12384         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12385         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12386         gst_sample_unref (sample);
12387       }
12388     }
12389   }
12390 }
12391
12392 static void
12393 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12394     const char *tag, const char *dummy, GNode * node)
12395 {
12396   GNode *data;
12397   char *s;
12398   int len;
12399   int type;
12400
12401   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12402   if (data) {
12403     len = QT_UINT32 (data->data);
12404     type = QT_UINT32 ((guint8 *) data->data + 8);
12405     if (type == 0x00000001 && len > 16) {
12406       guint y, m = 1, d = 1;
12407       gint ret;
12408
12409       s = g_strndup ((char *) data->data + 16, len - 16);
12410       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12411       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12412       if (ret >= 1 && y > 1500 && y < 3000) {
12413         GDate *date;
12414
12415         date = g_date_new_dmy (d, m, y);
12416         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12417         g_date_free (date);
12418       } else {
12419         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12420       }
12421       g_free (s);
12422     }
12423   }
12424 }
12425
12426 static void
12427 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12428     const char *tag, const char *dummy, GNode * node)
12429 {
12430   GNode *data;
12431
12432   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12433
12434   /* re-route to normal string tag if major brand says so
12435    * or no data atom and compatible brand suggests so */
12436   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12437       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12438     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12439     return;
12440   }
12441
12442   if (data) {
12443     guint len, type, n;
12444
12445     len = QT_UINT32 (data->data);
12446     type = QT_UINT32 ((guint8 *) data->data + 8);
12447     if (type == 0x00000000 && len >= 18) {
12448       n = QT_UINT16 ((guint8 *) data->data + 16);
12449       if (n > 0) {
12450         const gchar *genre;
12451
12452         genre = gst_tag_id3_genre_get (n - 1);
12453         if (genre != NULL) {
12454           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12455           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12456         }
12457       }
12458     }
12459   }
12460 }
12461
12462 static void
12463 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12464     const gchar * tag, guint8 * data, guint32 datasize)
12465 {
12466   gdouble value;
12467   gchar *datacopy;
12468
12469   /* make a copy to have \0 at the end */
12470   datacopy = g_strndup ((gchar *) data, datasize);
12471
12472   /* convert the str to double */
12473   if (sscanf (datacopy, "%lf", &value) == 1) {
12474     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12475     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12476   } else {
12477     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12478         datacopy);
12479   }
12480   g_free (datacopy);
12481 }
12482
12483
12484 static void
12485 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12486     const char *tag, const char *tag_bis, GNode * node)
12487 {
12488   GNode *mean;
12489   GNode *name;
12490   GNode *data;
12491   guint32 meansize;
12492   guint32 namesize;
12493   guint32 datatype;
12494   guint32 datasize;
12495   const gchar *meanstr;
12496   const gchar *namestr;
12497
12498   /* checking the whole ---- atom size for consistency */
12499   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12500     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12501     return;
12502   }
12503
12504   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12505   if (!mean) {
12506     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12507     return;
12508   }
12509
12510   meansize = QT_UINT32 (mean->data);
12511   if (meansize <= 12) {
12512     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12513     return;
12514   }
12515   meanstr = ((gchar *) mean->data) + 12;
12516   meansize -= 12;
12517
12518   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12519   if (!name) {
12520     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12521     return;
12522   }
12523
12524   namesize = QT_UINT32 (name->data);
12525   if (namesize <= 12) {
12526     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12527     return;
12528   }
12529   namestr = ((gchar *) name->data) + 12;
12530   namesize -= 12;
12531
12532   /*
12533    * Data atom is:
12534    * uint32 - size
12535    * uint32 - name
12536    * uint8  - version
12537    * uint24 - data type
12538    * uint32 - all 0
12539    * rest   - the data
12540    */
12541   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12542   if (!data) {
12543     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12544     return;
12545   }
12546   datasize = QT_UINT32 (data->data);
12547   if (datasize <= 16) {
12548     GST_WARNING_OBJECT (demux, "Data atom too small");
12549     return;
12550   }
12551   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12552
12553   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12554       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12555     static const struct
12556     {
12557       const gchar name[28];
12558       const gchar tag[28];
12559     } tags[] = {
12560       {
12561       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12562       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12563       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12564       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12565       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12566       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12567       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12568       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12569     };
12570     int i;
12571
12572     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12573       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12574         switch (gst_tag_get_type (tags[i].tag)) {
12575           case G_TYPE_DOUBLE:
12576             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12577                 ((guint8 *) data->data) + 16, datasize - 16);
12578             break;
12579           case G_TYPE_STRING:
12580             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12581             break;
12582           default:
12583             /* not reached */
12584             break;
12585         }
12586         break;
12587       }
12588     }
12589     if (i == G_N_ELEMENTS (tags))
12590       goto unknown_tag;
12591   } else {
12592     goto unknown_tag;
12593   }
12594
12595   return;
12596
12597 /* errors */
12598 unknown_tag:
12599 #ifndef GST_DISABLE_GST_DEBUG
12600   {
12601     gchar *namestr_dbg;
12602     gchar *meanstr_dbg;
12603
12604     meanstr_dbg = g_strndup (meanstr, meansize);
12605     namestr_dbg = g_strndup (namestr, namesize);
12606
12607     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12608         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12609
12610     g_free (namestr_dbg);
12611     g_free (meanstr_dbg);
12612   }
12613 #endif
12614   return;
12615 }
12616
12617 static void
12618 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12619     const char *tag_bis, GNode * node)
12620 {
12621   guint8 *data;
12622   GstBuffer *buf;
12623   guint len;
12624   GstTagList *id32_taglist = NULL;
12625
12626   GST_LOG_OBJECT (demux, "parsing ID32");
12627
12628   data = node->data;
12629   len = GST_READ_UINT32_BE (data);
12630
12631   /* need at least full box and language tag */
12632   if (len < 12 + 2)
12633     return;
12634
12635   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12636   gst_buffer_fill (buf, 0, data + 14, len - 14);
12637
12638   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12639   if (id32_taglist) {
12640     GST_LOG_OBJECT (demux, "parsing ok");
12641     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12642     gst_tag_list_unref (id32_taglist);
12643   } else {
12644     GST_LOG_OBJECT (demux, "parsing failed");
12645   }
12646
12647   gst_buffer_unref (buf);
12648 }
12649
12650 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12651     const char *tag, const char *tag_bis, GNode * node);
12652
12653 /* unmapped tags
12654 FOURCC_pcst -> if media is a podcast -> bool
12655 FOURCC_cpil -> if media is part of a compilation -> bool
12656 FOURCC_pgap -> if media is part of a gapless context -> bool
12657 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12658 */
12659
12660 static const struct
12661 {
12662   guint32 fourcc;
12663   const gchar *gst_tag;
12664   const gchar *gst_tag_bis;
12665   const GstQTDemuxAddTagFunc func;
12666 } add_funcs[] = {
12667   {
12668   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12669   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12670   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12671   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12672   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12673   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12674   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12675   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12676   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12677   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12678   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12679   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12680   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12681   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12682   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12683   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12684   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12685   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12686   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12687   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12688   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12689   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12690   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12691         qtdemux_tag_add_num}, {
12692   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12693         qtdemux_tag_add_num}, {
12694   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12695   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12696   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12697   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12698   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12699   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12700   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12701   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12702   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12703   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12704   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12705   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12706   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12707   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12708   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12709   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12710   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12711   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12712         qtdemux_tag_add_classification}, {
12713   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12714   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12715   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12716
12717     /* This is a special case, some tags are stored in this
12718      * 'reverse dns naming', according to:
12719      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12720      * bug #614471
12721      */
12722   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12723     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12724   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12725 };
12726
12727 struct _GstQtDemuxTagList
12728 {
12729   GstQTDemux *demux;
12730   GstTagList *taglist;
12731 };
12732 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12733
12734 static void
12735 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12736 {
12737   gint len;
12738   guint8 *data;
12739   GstBuffer *buf;
12740   gchar *media_type;
12741   const gchar *style;
12742   GstSample *sample;
12743   GstStructure *s;
12744   guint i;
12745   guint8 ndata[4];
12746   GstQTDemux *demux = qtdemuxtaglist->demux;
12747   GstTagList *taglist = qtdemuxtaglist->taglist;
12748
12749   data = node->data;
12750   len = QT_UINT32 (data);
12751   buf = gst_buffer_new_and_alloc (len);
12752   gst_buffer_fill (buf, 0, data, len);
12753
12754   /* heuristic to determine style of tag */
12755   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12756       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12757     style = "itunes";
12758   else if (demux->major_brand == FOURCC_qt__)
12759     style = "quicktime";
12760   /* fall back to assuming iso/3gp tag style */
12761   else
12762     style = "iso";
12763
12764   /* santize the name for the caps. */
12765   for (i = 0; i < 4; i++) {
12766     guint8 d = data[4 + i];
12767     if (g_ascii_isalnum (d))
12768       ndata[i] = g_ascii_tolower (d);
12769     else
12770       ndata[i] = '_';
12771   }
12772
12773   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12774       ndata[0], ndata[1], ndata[2], ndata[3]);
12775   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12776
12777   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12778   sample = gst_sample_new (buf, NULL, NULL, s);
12779   gst_buffer_unref (buf);
12780   g_free (media_type);
12781
12782   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12783       len, s);
12784
12785   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12786       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12787
12788   gst_sample_unref (sample);
12789 }
12790
12791 static void
12792 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12793 {
12794   GNode *meta;
12795   GNode *ilst;
12796   GNode *xmp_;
12797   GNode *node;
12798   gint i;
12799   GstQtDemuxTagList demuxtaglist;
12800
12801   demuxtaglist.demux = qtdemux;
12802   demuxtaglist.taglist = taglist;
12803
12804   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12805   if (meta != NULL) {
12806     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12807     if (ilst == NULL) {
12808       GST_LOG_OBJECT (qtdemux, "no ilst");
12809       return;
12810     }
12811   } else {
12812     ilst = udta;
12813     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12814   }
12815
12816   i = 0;
12817   while (i < G_N_ELEMENTS (add_funcs)) {
12818     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12819     if (node) {
12820       gint len;
12821
12822       len = QT_UINT32 (node->data);
12823       if (len < 12) {
12824         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12825             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12826       } else {
12827         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12828             add_funcs[i].gst_tag_bis, node);
12829       }
12830       g_node_destroy (node);
12831     } else {
12832       i++;
12833     }
12834   }
12835
12836   /* parsed nodes have been removed, pass along remainder as blob */
12837   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12838       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12839
12840   /* parse up XMP_ node if existing */
12841   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12842   if (xmp_ != NULL) {
12843     GstBuffer *buf;
12844     GstTagList *xmptaglist;
12845
12846     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12847         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12848     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12849     gst_buffer_unref (buf);
12850
12851     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12852   } else {
12853     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12854   }
12855 }
12856
12857 typedef struct
12858 {
12859   GstStructure *structure;      /* helper for sort function */
12860   gchar *location;
12861   guint min_req_bitrate;
12862   guint min_req_qt_version;
12863 } GstQtReference;
12864
12865 static gint
12866 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12867 {
12868   GstQtReference *ref_a = (GstQtReference *) a;
12869   GstQtReference *ref_b = (GstQtReference *) b;
12870
12871   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12872     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12873
12874   /* known bitrates go before unknown; higher bitrates go first */
12875   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12876 }
12877
12878 /* sort the redirects and post a message for the application.
12879  */
12880 static void
12881 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12882 {
12883   GstQtReference *best;
12884   GstStructure *s;
12885   GstMessage *msg;
12886   GValue list_val = { 0, };
12887   GList *l;
12888
12889   g_assert (references != NULL);
12890
12891   references = g_list_sort (references, qtdemux_redirects_sort_func);
12892
12893   best = (GstQtReference *) references->data;
12894
12895   g_value_init (&list_val, GST_TYPE_LIST);
12896
12897   for (l = references; l != NULL; l = l->next) {
12898     GstQtReference *ref = (GstQtReference *) l->data;
12899     GValue struct_val = { 0, };
12900
12901     ref->structure = gst_structure_new ("redirect",
12902         "new-location", G_TYPE_STRING, ref->location, NULL);
12903
12904     if (ref->min_req_bitrate > 0) {
12905       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12906           ref->min_req_bitrate, NULL);
12907     }
12908
12909     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12910     g_value_set_boxed (&struct_val, ref->structure);
12911     gst_value_list_append_value (&list_val, &struct_val);
12912     g_value_unset (&struct_val);
12913     /* don't free anything here yet, since we need best->structure below */
12914   }
12915
12916   g_assert (best != NULL);
12917   s = gst_structure_copy (best->structure);
12918
12919   if (g_list_length (references) > 1) {
12920     gst_structure_set_value (s, "locations", &list_val);
12921   }
12922
12923   g_value_unset (&list_val);
12924
12925   for (l = references; l != NULL; l = l->next) {
12926     GstQtReference *ref = (GstQtReference *) l->data;
12927
12928     gst_structure_free (ref->structure);
12929     g_free (ref->location);
12930     g_free (ref);
12931   }
12932   g_list_free (references);
12933
12934   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12935   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12936   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12937   qtdemux->posted_redirect = TRUE;
12938 }
12939
12940 /* look for redirect nodes, collect all redirect information and
12941  * process it.
12942  */
12943 static gboolean
12944 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12945 {
12946   GNode *rmra, *rmda, *rdrf;
12947
12948   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12949   if (rmra) {
12950     GList *redirects = NULL;
12951
12952     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12953     while (rmda) {
12954       GstQtReference ref = { NULL, NULL, 0, 0 };
12955       GNode *rmdr, *rmvc;
12956
12957       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12958         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12959         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12960             ref.min_req_bitrate);
12961       }
12962
12963       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12964         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12965         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12966
12967 #ifndef GST_DISABLE_GST_DEBUG
12968         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12969 #endif
12970         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12971
12972         GST_LOG_OBJECT (qtdemux,
12973             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12974             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12975             bitmask, check_type);
12976         if (package == FOURCC_qtim && check_type == 0) {
12977           ref.min_req_qt_version = version;
12978         }
12979       }
12980
12981       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12982       if (rdrf) {
12983         guint32 ref_type;
12984         guint8 *ref_data;
12985         guint ref_len;
12986
12987         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12988         if (ref_len > 20) {
12989           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12990           ref_data = (guint8 *) rdrf->data + 20;
12991           if (ref_type == FOURCC_alis) {
12992             guint record_len, record_version, fn_len;
12993
12994             if (ref_len > 70) {
12995               /* MacOSX alias record, google for alias-layout.txt */
12996               record_len = QT_UINT16 (ref_data + 4);
12997               record_version = QT_UINT16 (ref_data + 4 + 2);
12998               fn_len = QT_UINT8 (ref_data + 50);
12999               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13000                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13001               }
13002             } else {
13003               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13004                   ref_len);
13005             }
13006           } else if (ref_type == FOURCC_url_) {
13007             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13008           } else {
13009             GST_DEBUG_OBJECT (qtdemux,
13010                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13011                 GST_FOURCC_ARGS (ref_type));
13012           }
13013           if (ref.location != NULL) {
13014             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13015             redirects =
13016                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13017           } else {
13018             GST_WARNING_OBJECT (qtdemux,
13019                 "Failed to extract redirect location from rdrf atom");
13020           }
13021         } else {
13022           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13023         }
13024       }
13025
13026       /* look for others */
13027       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13028     }
13029
13030     if (redirects != NULL) {
13031       qtdemux_process_redirects (qtdemux, redirects);
13032     }
13033   }
13034   return TRUE;
13035 }
13036
13037 static GstTagList *
13038 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13039 {
13040   const gchar *fmt;
13041
13042   if (tags == NULL) {
13043     tags = gst_tag_list_new_empty ();
13044     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13045   }
13046
13047   if (qtdemux->major_brand == FOURCC_mjp2)
13048     fmt = "Motion JPEG 2000";
13049   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13050     fmt = "3GP";
13051   else if (qtdemux->major_brand == FOURCC_qt__)
13052     fmt = "Quicktime";
13053   else if (qtdemux->fragmented)
13054     fmt = "ISO fMP4";
13055   else
13056     fmt = "ISO MP4/M4A";
13057
13058   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13059       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13060
13061   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13062       fmt, NULL);
13063
13064   return tags;
13065 }
13066
13067 /* we have read the complete moov node now.
13068  * This function parses all of the relevant info, creates the traks and
13069  * prepares all data structures for playback
13070  */
13071 static gboolean
13072 qtdemux_parse_tree (GstQTDemux * qtdemux)
13073 {
13074   GNode *mvhd;
13075   GNode *trak;
13076   GNode *udta;
13077   GNode *mvex;
13078   GstClockTime duration;
13079   GNode *pssh;
13080   guint64 creation_time;
13081   GstDateTime *datetime = NULL;
13082   gint version;
13083
13084   /* make sure we have a usable taglist */
13085   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13086
13087   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13088   if (mvhd == NULL) {
13089     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13090     return qtdemux_parse_redirects (qtdemux);
13091   }
13092
13093   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13094   if (version == 1) {
13095     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13096     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13097     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13098   } else if (version == 0) {
13099     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13100     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13101     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13102   } else {
13103     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13104     return FALSE;
13105   }
13106
13107   /* Moving qt creation time (secs since 1904) to unix time */
13108   if (creation_time != 0) {
13109     /* Try to use epoch first as it should be faster and more commonly found */
13110     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13111       GTimeVal now;
13112
13113       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13114       /* some data cleansing sanity */
13115       g_get_current_time (&now);
13116       if (now.tv_sec + 24 * 3600 < creation_time) {
13117         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13118       } else {
13119         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13120       }
13121     } else {
13122       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13123       GDateTime *dt, *dt_local;
13124
13125       dt = g_date_time_add_seconds (base_dt, creation_time);
13126       dt_local = g_date_time_to_local (dt);
13127       datetime = gst_date_time_new_from_g_date_time (dt_local);
13128
13129       g_date_time_unref (base_dt);
13130       g_date_time_unref (dt);
13131     }
13132   }
13133   if (datetime) {
13134     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13135     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13136         datetime, NULL);
13137     gst_date_time_unref (datetime);
13138   }
13139
13140   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13141   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13142
13143   /* check for fragmented file and get some (default) data */
13144   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13145   if (mvex) {
13146     GNode *mehd;
13147     GstByteReader mehd_data;
13148
13149     /* let track parsing or anyone know weird stuff might happen ... */
13150     qtdemux->fragmented = TRUE;
13151
13152     /* compensate for total duration */
13153     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13154     if (mehd)
13155       qtdemux_parse_mehd (qtdemux, &mehd_data);
13156   }
13157
13158   /* set duration in the segment info */
13159   gst_qtdemux_get_duration (qtdemux, &duration);
13160   if (duration) {
13161     qtdemux->segment.duration = duration;
13162     /* also do not exceed duration; stop is set that way post seek anyway,
13163      * and segment activation falls back to duration,
13164      * whereas loop only checks stop, so let's align this here as well */
13165     qtdemux->segment.stop = duration;
13166   }
13167
13168   /* parse all traks */
13169   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13170   while (trak) {
13171     qtdemux_parse_trak (qtdemux, trak);
13172     /* iterate all siblings */
13173     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13174   }
13175
13176   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13177
13178   /* find tags */
13179   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13180   if (udta) {
13181     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13182   } else {
13183     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13184   }
13185
13186   /* maybe also some tags in meta box */
13187   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13188   if (udta) {
13189     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13190     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13191   } else {
13192     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13193   }
13194
13195   /* parse any protection system info */
13196   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13197   while (pssh) {
13198     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13199     qtdemux_parse_pssh (qtdemux, pssh);
13200     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13201   }
13202
13203   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13204
13205   return TRUE;
13206 }
13207
13208 /* taken from ffmpeg */
13209 static int
13210 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13211 {
13212   int count = 4;
13213   int len = 0;
13214
13215   while (count--) {
13216     int c;
13217
13218     if (ptr >= end)
13219       return -1;
13220
13221     c = *ptr++;
13222     len = (len << 7) | (c & 0x7f);
13223     if (!(c & 0x80))
13224       break;
13225   }
13226   *end_out = ptr;
13227   return len;
13228 }
13229
13230 /* this can change the codec originally present in @list */
13231 static void
13232 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13233     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13234 {
13235   int len = QT_UINT32 (esds->data);
13236   guint8 *ptr = esds->data;
13237   guint8 *end = ptr + len;
13238   int tag;
13239   guint8 *data_ptr = NULL;
13240   int data_len = 0;
13241   guint8 object_type_id = 0;
13242   const char *codec_name = NULL;
13243   GstCaps *caps = NULL;
13244
13245   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13246   ptr += 8;
13247   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13248   ptr += 4;
13249   while (ptr + 1 < end) {
13250     tag = QT_UINT8 (ptr);
13251     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13252     ptr++;
13253     len = read_descr_size (ptr, end, &ptr);
13254     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13255
13256     /* Check the stated amount of data is available for reading */
13257     if (len < 0 || ptr + len > end)
13258       break;
13259
13260     switch (tag) {
13261       case ES_DESCRIPTOR_TAG:
13262         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13263         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13264         ptr += 3;
13265         break;
13266       case DECODER_CONFIG_DESC_TAG:{
13267         guint max_bitrate, avg_bitrate;
13268
13269         object_type_id = QT_UINT8 (ptr);
13270         max_bitrate = QT_UINT32 (ptr + 5);
13271         avg_bitrate = QT_UINT32 (ptr + 9);
13272         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13273         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13274         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13275         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13276         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13277         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13278           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13279               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13280         }
13281         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13282           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13283               avg_bitrate, NULL);
13284         }
13285         ptr += 13;
13286         break;
13287       }
13288       case DECODER_SPECIFIC_INFO_TAG:
13289         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13290         if (object_type_id == 0xe0 && len == 0x40) {
13291           guint8 *data;
13292           GstStructure *s;
13293           guint32 clut[16];
13294           gint i;
13295
13296           GST_DEBUG_OBJECT (qtdemux,
13297               "Have VOBSUB palette. Creating palette event");
13298           /* move to decConfigDescr data and read palette */
13299           data = ptr;
13300           for (i = 0; i < 16; i++) {
13301             clut[i] = QT_UINT32 (data);
13302             data += 4;
13303           }
13304
13305           s = gst_structure_new ("application/x-gst-dvd", "event",
13306               G_TYPE_STRING, "dvd-spu-clut-change",
13307               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13308               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13309               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13310               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13311               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13312               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13313               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13314               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13315               NULL);
13316
13317           /* store event and trigger custom processing */
13318           stream->pending_event =
13319               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13320         } else {
13321           /* Generic codec_data handler puts it on the caps */
13322           data_ptr = ptr;
13323           data_len = len;
13324         }
13325
13326         ptr += len;
13327         break;
13328       case SL_CONFIG_DESC_TAG:
13329         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13330         ptr += 1;
13331         break;
13332       default:
13333         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13334             tag);
13335         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13336         ptr += len;
13337         break;
13338     }
13339   }
13340
13341   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13342    * in use, and should also be used to override some other parameters for some
13343    * codecs. */
13344   switch (object_type_id) {
13345     case 0x20:                 /* MPEG-4 */
13346       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13347        * profile_and_level_indication */
13348       if (data_ptr != NULL && data_len >= 5 &&
13349           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13350         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13351             data_ptr + 4, data_len - 4);
13352       }
13353       break;                    /* Nothing special needed here */
13354     case 0x21:                 /* H.264 */
13355       codec_name = "H.264 / AVC";
13356       caps = gst_caps_new_simple ("video/x-h264",
13357           "stream-format", G_TYPE_STRING, "avc",
13358           "alignment", G_TYPE_STRING, "au", NULL);
13359       break;
13360     case 0x40:                 /* AAC (any) */
13361     case 0x66:                 /* AAC Main */
13362     case 0x67:                 /* AAC LC */
13363     case 0x68:                 /* AAC SSR */
13364       /* Override channels and rate based on the codec_data, as it's often
13365        * wrong. */
13366       /* Only do so for basic setup without HE-AAC extension */
13367       if (data_ptr && data_len == 2) {
13368         guint channels, rate;
13369
13370         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13371         if (channels > 0)
13372           entry->n_channels = channels;
13373
13374         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13375         if (rate > 0)
13376           entry->rate = rate;
13377       }
13378
13379       /* Set level and profile if possible */
13380       if (data_ptr != NULL && data_len >= 2) {
13381         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13382             data_ptr, data_len);
13383       } else {
13384         const gchar *profile_str = NULL;
13385         GstBuffer *buffer;
13386         GstMapInfo map;
13387         guint8 *codec_data;
13388         gint rate_idx, profile;
13389
13390         /* No codec_data, let's invent something.
13391          * FIXME: This is wrong for SBR! */
13392
13393         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13394
13395         buffer = gst_buffer_new_and_alloc (2);
13396         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13397         codec_data = map.data;
13398
13399         rate_idx =
13400             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13401             (stream)->rate);
13402
13403         switch (object_type_id) {
13404           case 0x66:
13405             profile_str = "main";
13406             profile = 0;
13407             break;
13408           case 0x67:
13409             profile_str = "lc";
13410             profile = 1;
13411             break;
13412           case 0x68:
13413             profile_str = "ssr";
13414             profile = 2;
13415             break;
13416           default:
13417             profile = 3;
13418             break;
13419         }
13420
13421         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13422         codec_data[1] =
13423             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13424
13425         gst_buffer_unmap (buffer, &map);
13426         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13427             GST_TYPE_BUFFER, buffer, NULL);
13428         gst_buffer_unref (buffer);
13429
13430         if (profile_str) {
13431           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13432               G_TYPE_STRING, profile_str, NULL);
13433         }
13434       }
13435       break;
13436     case 0x60:                 /* MPEG-2, various profiles */
13437     case 0x61:
13438     case 0x62:
13439     case 0x63:
13440     case 0x64:
13441     case 0x65:
13442       codec_name = "MPEG-2 video";
13443       caps = gst_caps_new_simple ("video/mpeg",
13444           "mpegversion", G_TYPE_INT, 2,
13445           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13446       break;
13447     case 0x69:                 /* MPEG-2 BC audio */
13448     case 0x6B:                 /* MPEG-1 audio */
13449       caps = gst_caps_new_simple ("audio/mpeg",
13450           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13451       codec_name = "MPEG-1 audio";
13452       break;
13453     case 0x6A:                 /* MPEG-1 */
13454       codec_name = "MPEG-1 video";
13455       caps = gst_caps_new_simple ("video/mpeg",
13456           "mpegversion", G_TYPE_INT, 1,
13457           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13458       break;
13459     case 0x6C:                 /* MJPEG */
13460       caps =
13461           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13462           NULL);
13463       codec_name = "Motion-JPEG";
13464       break;
13465     case 0x6D:                 /* PNG */
13466       caps =
13467           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13468           NULL);
13469       codec_name = "PNG still images";
13470       break;
13471     case 0x6E:                 /* JPEG2000 */
13472       codec_name = "JPEG-2000";
13473       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13474       break;
13475     case 0xA4:                 /* Dirac */
13476       codec_name = "Dirac";
13477       caps = gst_caps_new_empty_simple ("video/x-dirac");
13478       break;
13479     case 0xA5:                 /* AC3 */
13480       codec_name = "AC-3 audio";
13481       caps = gst_caps_new_simple ("audio/x-ac3",
13482           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13483       break;
13484     case 0xA9:                 /* AC3 */
13485       codec_name = "DTS audio";
13486       caps = gst_caps_new_simple ("audio/x-dts",
13487           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13488       break;
13489     case 0xE1:                 /* QCELP */
13490       /* QCELP, the codec_data is a riff tag (little endian) with
13491        * 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). */
13492       caps = gst_caps_new_empty_simple ("audio/qcelp");
13493       codec_name = "QCELP";
13494       break;
13495     default:
13496       break;
13497   }
13498
13499   /* If we have a replacement caps, then change our caps for this stream */
13500   if (caps) {
13501     gst_caps_unref (entry->caps);
13502     entry->caps = caps;
13503   }
13504
13505   if (codec_name && list)
13506     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13507         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13508
13509   /* Add the codec_data attribute to caps, if we have it */
13510   if (data_ptr) {
13511     GstBuffer *buffer;
13512
13513     buffer = gst_buffer_new_and_alloc (data_len);
13514     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13515
13516     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13517     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13518
13519     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13520         buffer, NULL);
13521     gst_buffer_unref (buffer);
13522   }
13523
13524 }
13525
13526 static inline GstCaps *
13527 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13528 {
13529   GstCaps *caps;
13530   guint i;
13531   char *s, fourstr[5];
13532
13533   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13534   for (i = 0; i < 4; i++) {
13535     if (!g_ascii_isalnum (fourstr[i]))
13536       fourstr[i] = '_';
13537   }
13538   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13539   caps = gst_caps_new_empty_simple (s);
13540   g_free (s);
13541   return caps;
13542 }
13543
13544 #define _codec(name) \
13545   do { \
13546     if (codec_name) { \
13547       *codec_name = g_strdup (name); \
13548     } \
13549   } while (0)
13550
13551 static GstCaps *
13552 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13553     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13554     const guint8 * stsd_entry_data, gchar ** codec_name)
13555 {
13556   GstCaps *caps = NULL;
13557   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13558
13559   switch (fourcc) {
13560     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
13561       _codec ("PNG still images");
13562       caps = gst_caps_new_empty_simple ("image/png");
13563       break;
13564     case FOURCC_jpeg:
13565       _codec ("JPEG still images");
13566       caps =
13567           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13568           NULL);
13569       break;
13570     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13571     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13572     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13573     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13574       _codec ("Motion-JPEG");
13575       caps =
13576           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13577           NULL);
13578       break;
13579     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13580       _codec ("Motion-JPEG format B");
13581       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13582       break;
13583     case FOURCC_mjp2:
13584       _codec ("JPEG-2000");
13585       /* override to what it should be according to spec, avoid palette_data */
13586       entry->bits_per_sample = 24;
13587       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13588       break;
13589     case FOURCC_SVQ3:
13590       _codec ("Sorensen video v.3");
13591       caps = gst_caps_new_simple ("video/x-svq",
13592           "svqversion", G_TYPE_INT, 3, NULL);
13593       break;
13594     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13595     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13596       _codec ("Sorensen video v.1");
13597       caps = gst_caps_new_simple ("video/x-svq",
13598           "svqversion", G_TYPE_INT, 1, NULL);
13599       break;
13600     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13601       caps = gst_caps_new_empty_simple ("video/x-raw");
13602       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13603       _codec ("Windows Raw RGB");
13604       stream->alignment = 32;
13605       break;
13606     case FOURCC_raw_:
13607     {
13608       guint16 bps;
13609
13610       bps = QT_UINT16 (stsd_entry_data + 82);
13611       switch (bps) {
13612         case 15:
13613           format = GST_VIDEO_FORMAT_RGB15;
13614           break;
13615         case 16:
13616           format = GST_VIDEO_FORMAT_RGB16;
13617           break;
13618         case 24:
13619           format = GST_VIDEO_FORMAT_RGB;
13620           break;
13621         case 32:
13622           format = GST_VIDEO_FORMAT_ARGB;
13623           break;
13624         default:
13625           /* unknown */
13626           break;
13627       }
13628       break;
13629     }
13630     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13631       format = GST_VIDEO_FORMAT_I420;
13632       break;
13633     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13634     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13635       format = GST_VIDEO_FORMAT_I420;
13636       break;
13637     case FOURCC_2vuy:
13638     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13639       format = GST_VIDEO_FORMAT_UYVY;
13640       break;
13641     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13642       format = GST_VIDEO_FORMAT_v308;
13643       break;
13644     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13645       format = GST_VIDEO_FORMAT_v216;
13646       break;
13647     case FOURCC_v210:
13648       format = GST_VIDEO_FORMAT_v210;
13649       break;
13650     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13651       format = GST_VIDEO_FORMAT_r210;
13652       break;
13653       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13654          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13655          format = GST_VIDEO_FORMAT_v410;
13656          break;
13657        */
13658       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13659        * but different order than AYUV
13660        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13661        format = GST_VIDEO_FORMAT_v408;
13662        break;
13663        */
13664     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13665     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13666       _codec ("MPEG-1 video");
13667       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13668           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13669       break;
13670     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13671     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13672     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13673     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13674     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13675     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13676     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13677     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13678     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13679     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13680     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13681     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13682     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13683     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13684     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13685     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13686     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13687     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13688     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13689     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13690     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13691     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13692     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13693     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13694     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13695     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13696     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13697     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13698     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13699     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13700     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13701     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13702     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13703     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13704     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13705     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13706     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13707     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13708     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13709     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13710     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13711     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13712     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13713     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13714     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13715     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13716     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13717       _codec ("MPEG-2 video");
13718       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13719           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13720       break;
13721     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13722       _codec ("GIF still images");
13723       caps = gst_caps_new_empty_simple ("image/gif");
13724       break;
13725     case FOURCC_h263:
13726     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13727     case FOURCC_s263:
13728     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13729       _codec ("H.263");
13730       /* ffmpeg uses the height/width props, don't know why */
13731       caps = gst_caps_new_simple ("video/x-h263",
13732           "variant", G_TYPE_STRING, "itu", NULL);
13733       break;
13734     case FOURCC_mp4v:
13735     case FOURCC_MP4V:
13736       _codec ("MPEG-4 video");
13737       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13738           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13739       break;
13740     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13741     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13742       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13743       caps = gst_caps_new_simple ("video/x-msmpeg",
13744           "msmpegversion", G_TYPE_INT, 43, NULL);
13745       break;
13746     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13747       _codec ("DivX 3");
13748       caps = gst_caps_new_simple ("video/x-divx",
13749           "divxversion", G_TYPE_INT, 3, NULL);
13750       break;
13751     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13752     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13753       _codec ("DivX 4");
13754       caps = gst_caps_new_simple ("video/x-divx",
13755           "divxversion", G_TYPE_INT, 4, NULL);
13756       break;
13757     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13758       _codec ("DivX 5");
13759       caps = gst_caps_new_simple ("video/x-divx",
13760           "divxversion", G_TYPE_INT, 5, NULL);
13761       break;
13762
13763     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13764       _codec ("FFV1");
13765       caps = gst_caps_new_simple ("video/x-ffv",
13766           "ffvversion", G_TYPE_INT, 1, NULL);
13767       break;
13768
13769     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13770     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13771     case FOURCC_XVID:
13772     case FOURCC_xvid:
13773     case FOURCC_FMP4:
13774     case FOURCC_fmp4:
13775     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13776       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13777           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13778       _codec ("MPEG-4");
13779       break;
13780
13781     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13782       _codec ("Cinepak");
13783       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13784       break;
13785     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13786       _codec ("Apple QuickDraw");
13787       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13788       break;
13789     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13790       _codec ("Apple video");
13791       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13792       break;
13793     case FOURCC_H264:
13794     case FOURCC_avc1:
13795       _codec ("H.264 / AVC");
13796       caps = gst_caps_new_simple ("video/x-h264",
13797           "stream-format", G_TYPE_STRING, "avc",
13798           "alignment", G_TYPE_STRING, "au", NULL);
13799       break;
13800     case FOURCC_avc3:
13801       _codec ("H.264 / AVC");
13802       caps = gst_caps_new_simple ("video/x-h264",
13803           "stream-format", G_TYPE_STRING, "avc3",
13804           "alignment", G_TYPE_STRING, "au", NULL);
13805       break;
13806     case FOURCC_H265:
13807     case FOURCC_hvc1:
13808       _codec ("H.265 / HEVC");
13809       caps = gst_caps_new_simple ("video/x-h265",
13810           "stream-format", G_TYPE_STRING, "hvc1",
13811           "alignment", G_TYPE_STRING, "au", NULL);
13812       break;
13813     case FOURCC_hev1:
13814       _codec ("H.265 / HEVC");
13815       caps = gst_caps_new_simple ("video/x-h265",
13816           "stream-format", G_TYPE_STRING, "hev1",
13817           "alignment", G_TYPE_STRING, "au", NULL);
13818       break;
13819     case FOURCC_rle_:
13820       _codec ("Run-length encoding");
13821       caps = gst_caps_new_simple ("video/x-rle",
13822           "layout", G_TYPE_STRING, "quicktime", NULL);
13823       break;
13824     case FOURCC_WRLE:
13825       _codec ("Run-length encoding");
13826       caps = gst_caps_new_simple ("video/x-rle",
13827           "layout", G_TYPE_STRING, "microsoft", NULL);
13828       break;
13829     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13830     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13831       _codec ("Indeo Video 3");
13832       caps = gst_caps_new_simple ("video/x-indeo",
13833           "indeoversion", G_TYPE_INT, 3, NULL);
13834       break;
13835     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13836     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13837       _codec ("Intel Video 4");
13838       caps = gst_caps_new_simple ("video/x-indeo",
13839           "indeoversion", G_TYPE_INT, 4, NULL);
13840       break;
13841     case FOURCC_dvcp:
13842     case FOURCC_dvc_:
13843     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13844     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13845     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13846     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13847     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13848     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13849       _codec ("DV Video");
13850       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13851           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13852       break;
13853     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13854     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13855       _codec ("DVCPro50 Video");
13856       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13857           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13858       break;
13859     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13860     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13861       _codec ("DVCProHD Video");
13862       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13863           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13864       break;
13865     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13866       _codec ("Apple Graphics (SMC)");
13867       caps = gst_caps_new_empty_simple ("video/x-smc");
13868       break;
13869     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13870       _codec ("VP3");
13871       caps = gst_caps_new_empty_simple ("video/x-vp3");
13872       break;
13873     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13874       _codec ("VP6 Flash");
13875       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13876       break;
13877     case FOURCC_XiTh:
13878       _codec ("Theora");
13879       caps = gst_caps_new_empty_simple ("video/x-theora");
13880       /* theora uses one byte of padding in the data stream because it does not
13881        * allow 0 sized packets while theora does */
13882       entry->padding = 1;
13883       break;
13884     case FOURCC_drac:
13885       _codec ("Dirac");
13886       caps = gst_caps_new_empty_simple ("video/x-dirac");
13887       break;
13888     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13889       _codec ("TIFF still images");
13890       caps = gst_caps_new_empty_simple ("image/tiff");
13891       break;
13892     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13893       _codec ("Apple Intermediate Codec");
13894       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13895       break;
13896     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13897       _codec ("AVID DNxHD");
13898       caps = gst_caps_from_string ("video/x-dnxhd");
13899       break;
13900     case FOURCC_VP80:
13901       _codec ("On2 VP8");
13902       caps = gst_caps_from_string ("video/x-vp8");
13903       break;
13904     case FOURCC_apcs:
13905       _codec ("Apple ProRes LT");
13906       caps =
13907           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13908           NULL);
13909       break;
13910     case FOURCC_apch:
13911       _codec ("Apple ProRes HQ");
13912       caps =
13913           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13914           NULL);
13915       break;
13916     case FOURCC_apcn:
13917       _codec ("Apple ProRes");
13918       caps =
13919           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13920           "standard", NULL);
13921       break;
13922     case FOURCC_apco:
13923       _codec ("Apple ProRes Proxy");
13924       caps =
13925           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13926           "proxy", NULL);
13927       break;
13928     case FOURCC_ap4h:
13929       _codec ("Apple ProRes 4444");
13930       caps =
13931           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13932           "4444", NULL);
13933       break;
13934     case FOURCC_ap4x:
13935       _codec ("Apple ProRes 4444 XQ");
13936       caps =
13937           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13938           "4444xq", NULL);
13939       break;
13940     case FOURCC_cfhd:
13941       _codec ("GoPro CineForm");
13942       caps = gst_caps_from_string ("video/x-cineform");
13943       break;
13944     case FOURCC_vc_1:
13945     case FOURCC_ovc1:
13946       _codec ("VC-1");
13947       caps = gst_caps_new_simple ("video/x-wmv",
13948           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13949       break;
13950     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13951     default:
13952     {
13953       caps = _get_unknown_codec_name ("video", fourcc);
13954       break;
13955     }
13956   }
13957
13958   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13959     GstVideoInfo info;
13960
13961     gst_video_info_init (&info);
13962     gst_video_info_set_format (&info, format, entry->width, entry->height);
13963
13964     caps = gst_video_info_to_caps (&info);
13965     *codec_name = gst_pb_utils_get_codec_description (caps);
13966
13967     /* enable clipping for raw video streams */
13968     stream->need_clip = TRUE;
13969     stream->alignment = 32;
13970   }
13971
13972   return caps;
13973 }
13974
13975 static guint
13976 round_up_pow2 (guint n)
13977 {
13978   n = n - 1;
13979   n = n | (n >> 1);
13980   n = n | (n >> 2);
13981   n = n | (n >> 4);
13982   n = n | (n >> 8);
13983   n = n | (n >> 16);
13984   return n + 1;
13985 }
13986
13987 static GstCaps *
13988 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13989     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
13990     int len, gchar ** codec_name)
13991 {
13992   GstCaps *caps;
13993   const GstStructure *s;
13994   const gchar *name;
13995   gint endian = 0;
13996   GstAudioFormat format = 0;
13997   gint depth;
13998
13999   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14000
14001   depth = entry->bytes_per_packet * 8;
14002
14003   switch (fourcc) {
14004     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14005     case FOURCC_raw_:
14006       /* 8-bit audio is unsigned */
14007       if (depth == 8)
14008         format = GST_AUDIO_FORMAT_U8;
14009       /* otherwise it's signed and big-endian just like 'twos' */
14010     case FOURCC_twos:
14011       endian = G_BIG_ENDIAN;
14012       /* fall-through */
14013     case FOURCC_sowt:
14014     {
14015       gchar *str;
14016
14017       if (!endian)
14018         endian = G_LITTLE_ENDIAN;
14019
14020       if (!format)
14021         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14022
14023       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14024       _codec (str);
14025       g_free (str);
14026
14027       caps = gst_caps_new_simple ("audio/x-raw",
14028           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14029           "layout", G_TYPE_STRING, "interleaved", NULL);
14030       stream->alignment = GST_ROUND_UP_8 (depth);
14031       stream->alignment = round_up_pow2 (stream->alignment);
14032       break;
14033     }
14034     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14035       _codec ("Raw 64-bit floating-point audio");
14036       caps = gst_caps_new_simple ("audio/x-raw",
14037           "format", G_TYPE_STRING, "F64BE",
14038           "layout", G_TYPE_STRING, "interleaved", NULL);
14039       stream->alignment = 8;
14040       break;
14041     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14042       _codec ("Raw 32-bit floating-point audio");
14043       caps = gst_caps_new_simple ("audio/x-raw",
14044           "format", G_TYPE_STRING, "F32BE",
14045           "layout", G_TYPE_STRING, "interleaved", NULL);
14046       stream->alignment = 4;
14047       break;
14048     case FOURCC_in24:
14049       _codec ("Raw 24-bit PCM audio");
14050       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14051        * endian later */
14052       caps = gst_caps_new_simple ("audio/x-raw",
14053           "format", G_TYPE_STRING, "S24BE",
14054           "layout", G_TYPE_STRING, "interleaved", NULL);
14055       stream->alignment = 4;
14056       break;
14057     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14058       _codec ("Raw 32-bit PCM audio");
14059       caps = gst_caps_new_simple ("audio/x-raw",
14060           "format", G_TYPE_STRING, "S32BE",
14061           "layout", G_TYPE_STRING, "interleaved", NULL);
14062       stream->alignment = 4;
14063       break;
14064     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14065       _codec ("Raw 16-bit PCM audio");
14066       caps = gst_caps_new_simple ("audio/x-raw",
14067           "format", G_TYPE_STRING, "S16LE",
14068           "layout", G_TYPE_STRING, "interleaved", NULL);
14069       stream->alignment = 2;
14070       break;
14071     case FOURCC_ulaw:
14072       _codec ("Mu-law audio");
14073       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14074       break;
14075     case FOURCC_alaw:
14076       _codec ("A-law audio");
14077       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14078       break;
14079     case 0x0200736d:
14080     case 0x6d730002:
14081       _codec ("Microsoft ADPCM");
14082       /* Microsoft ADPCM-ACM code 2 */
14083       caps = gst_caps_new_simple ("audio/x-adpcm",
14084           "layout", G_TYPE_STRING, "microsoft", NULL);
14085       break;
14086     case 0x1100736d:
14087     case 0x6d730011:
14088       _codec ("DVI/IMA ADPCM");
14089       caps = gst_caps_new_simple ("audio/x-adpcm",
14090           "layout", G_TYPE_STRING, "dvi", NULL);
14091       break;
14092     case 0x1700736d:
14093     case 0x6d730017:
14094       _codec ("DVI/Intel IMA ADPCM");
14095       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14096       caps = gst_caps_new_simple ("audio/x-adpcm",
14097           "layout", G_TYPE_STRING, "quicktime", NULL);
14098       break;
14099     case 0x5500736d:
14100     case 0x6d730055:
14101       /* MPEG layer 3, CBR only (pre QT4.1) */
14102     case FOURCC__mp3:
14103       _codec ("MPEG-1 layer 3");
14104       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14105       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14106           "mpegversion", G_TYPE_INT, 1, NULL);
14107       break;
14108     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14109       _codec ("MPEG-1 layer 2");
14110       /* MPEG layer 2 */
14111       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14112           "mpegversion", G_TYPE_INT, 1, NULL);
14113       break;
14114     case 0x20736d:
14115     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14116       _codec ("EAC-3 audio");
14117       caps = gst_caps_new_simple ("audio/x-eac3",
14118           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14119       entry->sampled = TRUE;
14120       break;
14121     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14122     case FOURCC_ac_3:
14123       _codec ("AC-3 audio");
14124       caps = gst_caps_new_simple ("audio/x-ac3",
14125           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14126       entry->sampled = TRUE;
14127       break;
14128     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14129     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14130       _codec ("DTS audio");
14131       caps = gst_caps_new_simple ("audio/x-dts",
14132           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14133       entry->sampled = TRUE;
14134       break;
14135     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14136     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14137       _codec ("DTS-HD audio");
14138       caps = gst_caps_new_simple ("audio/x-dts",
14139           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14140       entry->sampled = TRUE;
14141       break;
14142     case FOURCC_MAC3:
14143       _codec ("MACE-3");
14144       caps = gst_caps_new_simple ("audio/x-mace",
14145           "maceversion", G_TYPE_INT, 3, NULL);
14146       break;
14147     case FOURCC_MAC6:
14148       _codec ("MACE-6");
14149       caps = gst_caps_new_simple ("audio/x-mace",
14150           "maceversion", G_TYPE_INT, 6, NULL);
14151       break;
14152     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14153       /* ogg/vorbis */
14154       caps = gst_caps_new_empty_simple ("application/ogg");
14155       break;
14156     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14157       _codec ("DV audio");
14158       caps = gst_caps_new_empty_simple ("audio/x-dv");
14159       break;
14160     case FOURCC_mp4a:
14161       _codec ("MPEG-4 AAC audio");
14162       caps = gst_caps_new_simple ("audio/mpeg",
14163           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14164           "stream-format", G_TYPE_STRING, "raw", NULL);
14165       break;
14166     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14167       _codec ("QDesign Music");
14168       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14169       break;
14170     case FOURCC_QDM2:
14171       _codec ("QDesign Music v.2");
14172       /* FIXME: QDesign music version 2 (no constant) */
14173       if (FALSE && data) {
14174         caps = gst_caps_new_simple ("audio/x-qdm2",
14175             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14176             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14177             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14178       } else {
14179         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14180       }
14181       break;
14182     case FOURCC_agsm:
14183       _codec ("GSM audio");
14184       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14185       break;
14186     case FOURCC_samr:
14187       _codec ("AMR audio");
14188       caps = gst_caps_new_empty_simple ("audio/AMR");
14189       break;
14190     case FOURCC_sawb:
14191       _codec ("AMR-WB audio");
14192       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14193       break;
14194     case FOURCC_ima4:
14195       _codec ("Quicktime IMA ADPCM");
14196       caps = gst_caps_new_simple ("audio/x-adpcm",
14197           "layout", G_TYPE_STRING, "quicktime", NULL);
14198       break;
14199     case FOURCC_alac:
14200       _codec ("Apple lossless audio");
14201       caps = gst_caps_new_empty_simple ("audio/x-alac");
14202       break;
14203     case FOURCC_fLaC:
14204       _codec ("Free Lossless Audio Codec");
14205       caps = gst_caps_new_simple ("audio/x-flac",
14206           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14207       break;
14208     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14209       _codec ("QualComm PureVoice");
14210       caps = gst_caps_from_string ("audio/qcelp");
14211       break;
14212     case FOURCC_wma_:
14213     case FOURCC_owma:
14214       _codec ("WMA");
14215       caps = gst_caps_new_empty_simple ("audio/x-wma");
14216       break;
14217     case FOURCC_opus:
14218       _codec ("Opus");
14219       caps = gst_caps_new_empty_simple ("audio/x-opus");
14220       break;
14221     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
14222     {
14223       guint32 flags = 0;
14224       guint32 depth = 0;
14225       guint32 width = 0;
14226       GstAudioFormat format;
14227       enum
14228       {
14229         FLAG_IS_FLOAT = 0x1,
14230         FLAG_IS_BIG_ENDIAN = 0x2,
14231         FLAG_IS_SIGNED = 0x4,
14232         FLAG_IS_PACKED = 0x8,
14233         FLAG_IS_ALIGNED_HIGH = 0x10,
14234         FLAG_IS_NON_INTERLEAVED = 0x20
14235       };
14236       _codec ("Raw LPCM audio");
14237
14238       if (data && len >= 56) {
14239         depth = QT_UINT32 (data + 40);
14240         flags = QT_UINT32 (data + 44);
14241         width = QT_UINT32 (data + 48) * 8 / entry->n_channels;
14242       }
14243       if ((flags & FLAG_IS_FLOAT) == 0) {
14244         if (depth == 0)
14245           depth = 16;
14246         if (width == 0)
14247           width = 16;
14248         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14249             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14250             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14251         caps = gst_caps_new_simple ("audio/x-raw",
14252             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14253             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14254             "non-interleaved" : "interleaved", NULL);
14255         stream->alignment = GST_ROUND_UP_8 (depth);
14256         stream->alignment = round_up_pow2 (stream->alignment);
14257       } else {
14258         if (width == 0)
14259           width = 32;
14260         if (width == 64) {
14261           if (flags & FLAG_IS_BIG_ENDIAN)
14262             format = GST_AUDIO_FORMAT_F64BE;
14263           else
14264             format = GST_AUDIO_FORMAT_F64LE;
14265         } else {
14266           if (flags & FLAG_IS_BIG_ENDIAN)
14267             format = GST_AUDIO_FORMAT_F32BE;
14268           else
14269             format = GST_AUDIO_FORMAT_F32LE;
14270         }
14271         caps = gst_caps_new_simple ("audio/x-raw",
14272             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14273             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14274             "non-interleaved" : "interleaved", NULL);
14275         stream->alignment = width / 8;
14276       }
14277       break;
14278     }
14279     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14280       /* ? */
14281     default:
14282     {
14283       caps = _get_unknown_codec_name ("audio", fourcc);
14284       break;
14285     }
14286   }
14287
14288   if (caps) {
14289     GstCaps *templ_caps =
14290         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14291     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14292     gst_caps_unref (caps);
14293     gst_caps_unref (templ_caps);
14294     caps = intersection;
14295   }
14296
14297   /* enable clipping for raw audio streams */
14298   s = gst_caps_get_structure (caps, 0);
14299   name = gst_structure_get_name (s);
14300   if (g_str_has_prefix (name, "audio/x-raw")) {
14301     stream->need_clip = TRUE;
14302     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14303     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14304   }
14305   return caps;
14306 }
14307
14308 static GstCaps *
14309 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14310     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14311     const guint8 * stsd_entry_data, gchar ** codec_name)
14312 {
14313   GstCaps *caps;
14314
14315   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14316
14317   switch (fourcc) {
14318     case FOURCC_mp4s:
14319       _codec ("DVD subtitle");
14320       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14321       stream->need_process = TRUE;
14322       break;
14323     case FOURCC_text:
14324       _codec ("Quicktime timed text");
14325       goto text;
14326     case FOURCC_tx3g:
14327       _codec ("3GPP timed text");
14328     text:
14329       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14330           "utf8", NULL);
14331       /* actual text piece needs to be extracted */
14332       stream->need_process = TRUE;
14333       break;
14334     case FOURCC_stpp:
14335       _codec ("XML subtitles");
14336       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14337       break;
14338     default:
14339     {
14340       caps = _get_unknown_codec_name ("text", fourcc);
14341       break;
14342     }
14343   }
14344   return caps;
14345 }
14346
14347 static GstCaps *
14348 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14349     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14350     const guint8 * stsd_entry_data, gchar ** codec_name)
14351 {
14352   GstCaps *caps;
14353
14354   switch (fourcc) {
14355     case FOURCC_m1v:
14356       _codec ("MPEG 1 video");
14357       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14358           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14359       break;
14360     default:
14361       caps = NULL;
14362       break;
14363   }
14364   return caps;
14365 }
14366
14367 static void
14368 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14369     const gchar * system_id)
14370 {
14371   gint i;
14372
14373   if (!qtdemux->protection_system_ids)
14374     qtdemux->protection_system_ids =
14375         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14376   /* Check whether we already have an entry for this system ID. */
14377   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14378     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14379     if (g_ascii_strcasecmp (system_id, id) == 0) {
14380       return;
14381     }
14382   }
14383   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14384   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14385           -1));
14386 }