qtdemux: Apply qtdemux debug category to gstisoff
[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 (200*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 #define GST_CAT_DEFAULT qtdemux_debug
105
106 typedef struct _QtDemuxSegment QtDemuxSegment;
107 typedef struct _QtDemuxSample QtDemuxSample;
108
109 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
110
111 struct _QtDemuxSample
112 {
113   guint32 size;
114   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
115   guint64 offset;
116   guint64 timestamp;            /* DTS In mov time */
117   guint32 duration;             /* In mov time */
118   gboolean keyframe;            /* TRUE when this packet is a keyframe */
119 };
120
121 /* Macros for converting to/from timescale */
122 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
123 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
124
125 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
126 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
127
128 /* timestamp is the DTS */
129 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
130 /* timestamp + offset + cslg_shift is the outgoing PTS */
131 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
132 /* timestamp + offset is the PTS used for internal seek calcuations */
133 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
134 /* timestamp + duration - dts is the duration */
135 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
136
137 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
138
139 /*
140  * Quicktime has tracks and segments. A track is a continuous piece of
141  * multimedia content. The track is not always played from start to finish but
142  * instead, pieces of the track are 'cut out' and played in sequence. This is
143  * what the segments do.
144  *
145  * Inside the track we have keyframes (K) and delta frames. The track has its
146  * own timing, which starts from 0 and extends to end. The position in the track
147  * is called the media_time.
148  *
149  * The segments now describe the pieces that should be played from this track
150  * and are basically tuples of media_time/duration/rate entries. We can have
151  * multiple segments and they are all played after one another. An example:
152  *
153  * segment 1: media_time: 1 second, duration: 1 second, rate 1
154  * segment 2: media_time: 3 second, duration: 2 second, rate 2
155  *
156  * To correctly play back this track, one must play: 1 second of media starting
157  * from media_time 1 followed by 2 seconds of media starting from media_time 3
158  * at a rate of 2.
159  *
160  * Each of the segments will be played at a specific time, the first segment at
161  * time 0, the second one after the duration of the first one, etc.. Note that
162  * the time in resulting playback is not identical to the media_time of the
163  * track anymore.
164  *
165  * Visually, assuming the track has 4 second of media_time:
166  *
167  *                (a)                   (b)          (c)              (d)
168  *         .-----------------------------------------------------------.
169  * track:  | K.....K.........K........K.......K.......K...........K... |
170  *         '-----------------------------------------------------------'
171  *         0              1              2              3              4
172  *           .------------^              ^   .----------^              ^
173  *          /              .-------------'  /       .------------------'
174  *         /              /          .-----'       /
175  *         .--------------.         .--------------.
176  *         | segment 1    |         | segment 2    |
177  *         '--------------'         '--------------'
178  *
179  * The challenge here is to cut out the right pieces of the track for each of
180  * the playback segments. This fortunately can easily be done with the SEGMENT
181  * events of GStreamer.
182  *
183  * For playback of segment 1, we need to provide the decoder with the keyframe
184  * (a), in the above figure, but we must instruct it only to output the decoded
185  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
186  * position set to the time of the segment: 0.
187  *
188  * We then proceed to push data from keyframe (a) to frame (b). The decoder
189  * decodes but clips all before media_time 1.
190  *
191  * After finishing a segment, we push out a new SEGMENT event with the clipping
192  * boundaries of the new data.
193  *
194  * This is a good usecase for the GStreamer accumulated SEGMENT events.
195  */
196
197 struct _QtDemuxSegment
198 {
199   /* global time and duration, all gst time */
200   GstClockTime time;
201   GstClockTime stop_time;
202   GstClockTime duration;
203   /* media time of trak, all gst time */
204   GstClockTime media_start;
205   GstClockTime media_stop;
206   gdouble rate;
207   /* Media start time in trak timescale units */
208   guint32 trak_media_start;
209 };
210
211 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
212
213 /* Used with fragmented MP4 files (mfra atom) */
214 typedef struct
215 {
216   GstClockTime ts;
217   guint64 moof_offset;
218 } QtDemuxRandomAccessEntry;
219
220 typedef struct _QtDemuxStreamStsdEntry
221 {
222   GstCaps *caps;
223   guint32 fourcc;
224   gboolean sparse;
225
226   /* video info */
227   gint width;
228   gint height;
229   gint par_w;
230   gint par_h;
231   /* Numerator/denominator framerate */
232   gint fps_n;
233   gint fps_d;
234   GstVideoColorimetry colorimetry;
235   guint16 bits_per_sample;
236   guint16 color_table_id;
237   GstMemory *rgb8_palette;
238   guint interlace_mode;
239   guint field_order;
240
241   /* audio info */
242   gdouble rate;
243   gint n_channels;
244   guint samples_per_packet;
245   guint samples_per_frame;
246   guint bytes_per_packet;
247   guint bytes_per_sample;
248   guint bytes_per_frame;
249   guint compression;
250
251   /* if we use chunks or samples */
252   gboolean sampled;
253   guint padding;
254
255 } QtDemuxStreamStsdEntry;
256
257 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
258
259 struct _QtDemuxStream
260 {
261   GstPad *pad;
262
263   QtDemuxStreamStsdEntry *stsd_entries;
264   guint stsd_entries_length;
265   guint cur_stsd_entry_index;
266
267   /* stream type */
268   guint32 subtype;
269
270   gboolean new_caps;            /* If TRUE, caps need to be generated (by
271                                  * calling _configure_stream()) This happens
272                                  * for MSS and fragmented streams */
273
274   gboolean new_stream;          /* signals that a stream_start is required */
275   gboolean on_keyframe;         /* if this stream last pushed buffer was a
276                                  * keyframe. This is important to identify
277                                  * where to stop pushing buffers after a
278                                  * segment stop time */
279
280   /* if the stream has a redirect URI in its headers, we store it here */
281   gchar *redirect_uri;
282
283   /* track id */
284   guint track_id;
285
286   /* duration/scale */
287   guint64 duration;             /* in timescale units */
288   guint32 timescale;
289
290   /* language */
291   gchar lang_id[4];             /* ISO 639-2T language code */
292
293   /* our samples */
294   guint32 n_samples;
295   QtDemuxSample *samples;
296   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
297   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
298                                    the framerate */
299   guint32 n_samples_moof;       /* sample count in a moof */
300   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
301                                  * the framerate of fragmented format stream */
302   guint64 duration_last_moof;
303
304   guint32 offset_in_sample;     /* Offset in the current sample, used for
305                                  * streams which have got exceedingly big
306                                  * sample size (such as 24s of raw audio).
307                                  * Only used when max_buffer_size is non-NULL */
308   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
309                                  * Currently only set for raw audio streams*/
310
311   /* video info */
312   /* aspect ratio */
313   gint display_width;
314   gint display_height;
315
316   /* allocation */
317   gboolean use_allocator;
318   GstAllocator *allocator;
319   GstAllocationParams params;
320
321   gsize alignment;
322
323   /* when a discontinuity is pending */
324   gboolean discont;
325
326   /* list of buffers to push first */
327   GSList *buffers;
328
329   /* if we need to clip this buffer. This is only needed for uncompressed
330    * data */
331   gboolean need_clip;
332
333   /* buffer needs some custom processing, e.g. subtitles */
334   gboolean need_process;
335
336   /* current position */
337   guint32 segment_index;
338   guint32 sample_index;
339   GstClockTime time_position;   /* in gst time */
340   guint64 accumulated_base;
341
342   /* the Gst segment we are processing out, used for clipping */
343   GstSegment segment;
344
345   /* quicktime segments */
346   guint32 n_segments;
347   QtDemuxSegment *segments;
348   gboolean dummy_segment;
349   guint32 from_sample;
350   guint32 to_sample;
351
352   gboolean sent_eos;
353   GstTagList *stream_tags;
354   gboolean send_global_tags;
355
356   GstEvent *pending_event;
357
358   GstByteReader stco;
359   GstByteReader stsz;
360   GstByteReader stsc;
361   GstByteReader stts;
362   GstByteReader stss;
363   GstByteReader stps;
364   GstByteReader ctts;
365
366   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
367   gint64 stbl_index;
368   /* stco */
369   guint co_size;
370   GstByteReader co_chunk;
371   guint32 first_chunk;
372   guint32 current_chunk;
373   guint32 last_chunk;
374   guint32 samples_per_chunk;
375   guint32 stsd_sample_description_id;
376   guint32 stco_sample_index;
377   /* stsz */
378   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
379   /* stsc */
380   guint32 stsc_index;
381   guint32 n_samples_per_chunk;
382   guint32 stsc_chunk_index;
383   guint32 stsc_sample_index;
384   guint64 chunk_offset;
385   /* stts */
386   guint32 stts_index;
387   guint32 stts_samples;
388   guint32 n_sample_times;
389   guint32 stts_sample_index;
390   guint64 stts_time;
391   guint32 stts_duration;
392   /* stss */
393   gboolean stss_present;
394   guint32 n_sample_syncs;
395   guint32 stss_index;
396   /* stps */
397   gboolean stps_present;
398   guint32 n_sample_partial_syncs;
399   guint32 stps_index;
400   QtDemuxRandomAccessEntry *ra_entries;
401   guint n_ra_entries;
402
403   const QtDemuxRandomAccessEntry *pending_seek;
404
405   /* ctts */
406   gboolean ctts_present;
407   guint32 n_composition_times;
408   guint32 ctts_index;
409   guint32 ctts_sample_index;
410   guint32 ctts_count;
411   gint32 ctts_soffset;
412
413   /* cslg */
414   guint32 cslg_shift;
415
416   /* fragmented */
417   gboolean parsed_trex;
418   guint32 def_sample_description_index; /* index is 1-based */
419   guint32 def_sample_duration;
420   guint32 def_sample_size;
421   guint32 def_sample_flags;
422
423   gboolean disabled;
424
425   /* stereoscopic video streams */
426   GstVideoMultiviewMode multiview_mode;
427   GstVideoMultiviewFlags multiview_flags;
428
429   /* protected streams */
430   gboolean protected;
431   guint32 protection_scheme_type;
432   guint32 protection_scheme_version;
433   gpointer protection_scheme_info;      /* specific to the protection scheme */
434   GQueue protection_scheme_event_queue;
435 };
436
437 /* Contains properties and cryptographic info for a set of samples from a
438  * track protected using Common Encryption (cenc) */
439 struct _QtDemuxCencSampleSetInfo
440 {
441   GstStructure *default_properties;
442
443   /* @crypto_info holds one GstStructure per sample */
444   GPtrArray *crypto_info;
445 };
446
447 static const gchar *
448 qt_demux_state_string (enum QtDemuxState state)
449 {
450   switch (state) {
451     case QTDEMUX_STATE_INITIAL:
452       return "<INITIAL>";
453     case QTDEMUX_STATE_HEADER:
454       return "<HEADER>";
455     case QTDEMUX_STATE_MOVIE:
456       return "<MOVIE>";
457     case QTDEMUX_STATE_BUFFER_MDAT:
458       return "<BUFFER_MDAT>";
459     default:
460       return "<UNKNOWN>";
461   }
462 }
463
464 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
465 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
466     guint32 fourcc, GstByteReader * parser);
467 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
468 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
469     guint32 fourcc, GstByteReader * parser);
470
471 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
472
473 static GstStaticPadTemplate gst_qtdemux_sink_template =
474     GST_STATIC_PAD_TEMPLATE ("sink",
475     GST_PAD_SINK,
476     GST_PAD_ALWAYS,
477     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
478         "application/x-3gp")
479     );
480
481 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
482 GST_STATIC_PAD_TEMPLATE ("video_%u",
483     GST_PAD_SRC,
484     GST_PAD_SOMETIMES,
485     GST_STATIC_CAPS_ANY);
486
487 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
488 GST_STATIC_PAD_TEMPLATE ("audio_%u",
489     GST_PAD_SRC,
490     GST_PAD_SOMETIMES,
491     GST_STATIC_CAPS_ANY);
492
493 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
494 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
495     GST_PAD_SRC,
496     GST_PAD_SOMETIMES,
497     GST_STATIC_CAPS_ANY);
498
499 #define gst_qtdemux_parent_class parent_class
500 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
501
502 static void gst_qtdemux_dispose (GObject * object);
503
504 static guint32
505 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
506     GstClockTime media_time);
507 static guint32
508 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
509     QtDemuxStream * str, gint64 media_offset);
510
511 #if 0
512 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
513 static GstIndex *gst_qtdemux_get_index (GstElement * element);
514 #endif
515 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
516     GstStateChange transition);
517 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
518 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
519     GstObject * parent, GstPadMode mode, gboolean active);
520
521 static void gst_qtdemux_loop (GstPad * pad);
522 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
523     GstBuffer * inbuf);
524 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
525     GstEvent * event);
526 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
527 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
528     QtDemuxStream * stream);
529 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
530     QtDemuxStream * stream);
531 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
532     gboolean force);
533
534 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
535     const guint8 * buffer, guint length);
536 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
537     const guint8 * buffer, guint length);
538 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
539 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
540     GNode * udta);
541
542 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
543     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
544     GstTagList * list);
545 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
546     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
547     const guint8 * stsd_entry_data, gchar ** codec_name);
548 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
549     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
550     const guint8 * data, int len, gchar ** codec_name);
551 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
552     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
553     gchar ** codec_name);
554 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
555     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
556     const guint8 * stsd_entry_data, gchar ** codec_name);
557
558 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
559     QtDemuxStream * stream, guint32 n);
560 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
561 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
562     QtDemuxStream * stream);
563 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
564     QtDemuxStream * stream);
565 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
566 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
567 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
568     QtDemuxStream * stream);
569 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
570     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
571 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
572     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
573     GstClockTime * _start, GstClockTime * _stop);
574 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
575     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
576
577 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
578 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
579
580 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
581
582 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
583     QtDemuxStream * stream, guint sample_index);
584 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
585     const gchar * id);
586 static void qtdemux_gst_structure_free (GstStructure * gststructure);
587
588 static void
589 gst_qtdemux_class_init (GstQTDemuxClass * klass)
590 {
591   GObjectClass *gobject_class;
592   GstElementClass *gstelement_class;
593
594   gobject_class = (GObjectClass *) klass;
595   gstelement_class = (GstElementClass *) klass;
596
597   parent_class = g_type_class_peek_parent (klass);
598
599   gobject_class->dispose = gst_qtdemux_dispose;
600
601   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
602 #if 0
603   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
604   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
605 #endif
606
607   gst_tag_register_musicbrainz_tags ();
608
609   gst_element_class_add_static_pad_template (gstelement_class,
610       &gst_qtdemux_sink_template);
611   gst_element_class_add_static_pad_template (gstelement_class,
612       &gst_qtdemux_videosrc_template);
613   gst_element_class_add_static_pad_template (gstelement_class,
614       &gst_qtdemux_audiosrc_template);
615   gst_element_class_add_static_pad_template (gstelement_class,
616       &gst_qtdemux_subsrc_template);
617   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
618       "Codec/Demuxer",
619       "Demultiplex a QuickTime file into audio and video streams",
620       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
621
622   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
623
624 }
625
626 static void
627 gst_qtdemux_init (GstQTDemux * qtdemux)
628 {
629   qtdemux->sinkpad =
630       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
631   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
632   gst_pad_set_activatemode_function (qtdemux->sinkpad,
633       qtdemux_sink_activate_mode);
634   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
635   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
636   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
637
638   qtdemux->state = QTDEMUX_STATE_INITIAL;
639   qtdemux->pullbased = FALSE;
640   qtdemux->posted_redirect = FALSE;
641   qtdemux->neededbytes = 16;
642   qtdemux->todrop = 0;
643   qtdemux->adapter = gst_adapter_new ();
644   qtdemux->offset = 0;
645   qtdemux->first_mdat = -1;
646   qtdemux->got_moov = FALSE;
647   qtdemux->mdatoffset = -1;
648   qtdemux->mdatbuffer = NULL;
649   qtdemux->restoredata_buffer = NULL;
650   qtdemux->restoredata_offset = -1;
651   qtdemux->fragment_start = -1;
652   qtdemux->fragment_start_offset = -1;
653   qtdemux->media_caps = NULL;
654   qtdemux->exposed = FALSE;
655   qtdemux->mss_mode = FALSE;
656   qtdemux->pending_newsegment = NULL;
657   qtdemux->upstream_format_is_time = FALSE;
658   qtdemux->have_group_id = FALSE;
659   qtdemux->group_id = G_MAXUINT;
660   qtdemux->cenc_aux_info_offset = 0;
661   qtdemux->cenc_aux_info_sizes = NULL;
662   qtdemux->cenc_aux_sample_count = 0;
663   qtdemux->protection_system_ids = NULL;
664   g_queue_init (&qtdemux->protection_event_queue);
665   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
666   qtdemux->tag_list = gst_tag_list_new_empty ();
667   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
668   qtdemux->flowcombiner = gst_flow_combiner_new ();
669
670   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
671 }
672
673 static void
674 gst_qtdemux_dispose (GObject * object)
675 {
676   GstQTDemux *qtdemux = GST_QTDEMUX (object);
677
678   if (qtdemux->adapter) {
679     g_object_unref (G_OBJECT (qtdemux->adapter));
680     qtdemux->adapter = NULL;
681   }
682   gst_tag_list_unref (qtdemux->tag_list);
683   gst_flow_combiner_free (qtdemux->flowcombiner);
684   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
685       NULL);
686   g_queue_clear (&qtdemux->protection_event_queue);
687
688   g_free (qtdemux->cenc_aux_info_sizes);
689   qtdemux->cenc_aux_info_sizes = NULL;
690
691   G_OBJECT_CLASS (parent_class)->dispose (object);
692 }
693
694 static void
695 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
696 {
697   if (qtdemux->posted_redirect) {
698     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
699         (_("This file contains no playable streams.")),
700         ("no known streams found, a redirect message has been posted"));
701   } else {
702     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
703         (_("This file contains no playable streams.")),
704         ("no known streams found"));
705   }
706 }
707
708 static GstBuffer *
709 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
710 {
711   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
712       mem, size, 0, size, mem, free_func);
713 }
714
715 static GstFlowReturn
716 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
717     GstBuffer ** buf)
718 {
719   GstFlowReturn flow;
720   GstMapInfo map;
721   gsize bsize;
722
723   if (G_UNLIKELY (size == 0)) {
724     GstFlowReturn ret;
725     GstBuffer *tmp = NULL;
726
727     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
728     if (ret != GST_FLOW_OK)
729       return ret;
730
731     gst_buffer_map (tmp, &map, GST_MAP_READ);
732     size = QT_UINT32 (map.data);
733     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
734
735     gst_buffer_unmap (tmp, &map);
736     gst_buffer_unref (tmp);
737   }
738
739   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
740   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
741     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
742       /* we're pulling header but already got most interesting bits,
743        * so never mind the rest (e.g. tags) (that much) */
744       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
745           size);
746       return GST_FLOW_EOS;
747     } else {
748       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
749           (_("This file is invalid and cannot be played.")),
750           ("atom has bogus size %" G_GUINT64_FORMAT, size));
751       return GST_FLOW_ERROR;
752     }
753   }
754
755   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
756
757   if (G_UNLIKELY (flow != GST_FLOW_OK))
758     return flow;
759
760   bsize = gst_buffer_get_size (*buf);
761   /* Catch short reads - we don't want any partial atoms */
762   if (G_UNLIKELY (bsize < size)) {
763     GST_WARNING_OBJECT (qtdemux,
764         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
765     gst_buffer_unref (*buf);
766     *buf = NULL;
767     return GST_FLOW_EOS;
768   }
769
770   return flow;
771 }
772
773 #if 1
774 static gboolean
775 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
776     GstFormat src_format, gint64 src_value, GstFormat dest_format,
777     gint64 * dest_value)
778 {
779   gboolean res = TRUE;
780   QtDemuxStream *stream = gst_pad_get_element_private (pad);
781   gint32 index;
782
783   if (stream->subtype != FOURCC_vide) {
784     res = FALSE;
785     goto done;
786   }
787
788   switch (src_format) {
789     case GST_FORMAT_TIME:
790       switch (dest_format) {
791         case GST_FORMAT_BYTES:{
792           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
793           if (-1 == index) {
794             res = FALSE;
795             goto done;
796           }
797
798           *dest_value = stream->samples[index].offset;
799
800           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
801               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
802               GST_TIME_ARGS (src_value), *dest_value);
803           break;
804         }
805         default:
806           res = FALSE;
807           break;
808       }
809       break;
810     case GST_FORMAT_BYTES:
811       switch (dest_format) {
812         case GST_FORMAT_TIME:{
813           index =
814               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
815               stream, src_value);
816
817           if (-1 == index) {
818             res = FALSE;
819             goto done;
820           }
821
822           *dest_value =
823               QTSTREAMTIME_TO_GSTTIME (stream,
824               stream->samples[index].timestamp);
825           GST_DEBUG_OBJECT (qtdemux,
826               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
827               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
828           break;
829         }
830         default:
831           res = FALSE;
832           break;
833       }
834       break;
835     default:
836       res = FALSE;
837       break;
838   }
839
840 done:
841   return res;
842 }
843 #endif
844
845 static gboolean
846 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
847 {
848   gboolean res = FALSE;
849
850   *duration = GST_CLOCK_TIME_NONE;
851
852   if (qtdemux->duration != 0 &&
853       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
854     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
855     res = TRUE;
856   } else {
857     *duration = GST_CLOCK_TIME_NONE;
858   }
859
860   return res;
861 }
862
863 static gboolean
864 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
865     GstQuery * query)
866 {
867   gboolean res = FALSE;
868   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
869
870   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
871
872   switch (GST_QUERY_TYPE (query)) {
873     case GST_QUERY_POSITION:{
874       GstFormat fmt;
875
876       gst_query_parse_position (query, &fmt, NULL);
877       if (fmt == GST_FORMAT_TIME
878           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
879         gst_query_set_position (query, GST_FORMAT_TIME,
880             qtdemux->segment.position);
881         res = TRUE;
882       }
883     }
884       break;
885     case GST_QUERY_DURATION:{
886       GstFormat fmt;
887
888       gst_query_parse_duration (query, &fmt, NULL);
889       if (fmt == GST_FORMAT_TIME) {
890         /* First try to query upstream */
891         res = gst_pad_query_default (pad, parent, query);
892         if (!res) {
893           GstClockTime duration;
894           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
895             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
896             res = TRUE;
897           }
898         }
899       }
900       break;
901     }
902     case GST_QUERY_CONVERT:{
903       GstFormat src_fmt, dest_fmt;
904       gint64 src_value, dest_value = 0;
905
906       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
907
908       res = gst_qtdemux_src_convert (qtdemux, pad,
909           src_fmt, src_value, dest_fmt, &dest_value);
910       if (res)
911         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
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 = GST_SEQNUM_INVALID;
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 != GST_SEQNUM_INVALID)
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 != GST_SEQNUM_INVALID)
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 != GST_SEQNUM_INVALID)
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 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1828  *
1829  * If @fw is false, the coding order is explored backwards.
1830  *
1831  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1832  * sample is found for that track.
1833  *
1834  * The stream and sample index of the sample with the minimum offset in the direction explored
1835  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1836  *
1837  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1838  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1839  * @_stream and @_index. */
1840 static void
1841 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1842     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1843 {
1844   gint i, n, index;
1845   gint64 time, min_time;
1846   QtDemuxStream *stream;
1847
1848   min_time = -1;
1849   stream = NULL;
1850   index = -1;
1851
1852   for (n = 0; n < qtdemux->n_streams; ++n) {
1853     QtDemuxStream *str;
1854     gint inc;
1855     gboolean set_sample;
1856
1857     str = qtdemux->streams[n];
1858     set_sample = !set;
1859
1860     if (fw) {
1861       i = 0;
1862       inc = 1;
1863     } else {
1864       i = str->n_samples - 1;
1865       inc = -1;
1866     }
1867
1868     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1869       if (str->samples[i].size == 0)
1870         continue;
1871
1872       if (fw && (str->samples[i].offset < byte_pos))
1873         continue;
1874
1875       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1876         continue;
1877
1878       /* move stream to first available sample */
1879       if (set) {
1880         gst_qtdemux_move_stream (qtdemux, str, i);
1881         set_sample = TRUE;
1882       }
1883
1884       /* avoid index from sparse streams since they might be far away */
1885       if (!CUR_STREAM (str)->sparse) {
1886         /* determine min/max time */
1887         time = QTSAMPLE_PTS (str, &str->samples[i]);
1888         if (min_time == -1 || (!fw && time > min_time) ||
1889             (fw && time < min_time)) {
1890           min_time = time;
1891         }
1892
1893         /* determine stream with leading sample, to get its position */
1894         if (!stream ||
1895             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1896             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1897           stream = str;
1898           index = i;
1899         }
1900       }
1901       break;
1902     }
1903
1904     /* no sample for this stream, mark eos */
1905     if (!set_sample)
1906       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1907   }
1908
1909   if (_time)
1910     *_time = min_time;
1911   if (_stream)
1912     *_stream = stream;
1913   if (_index)
1914     *_index = index;
1915 }
1916
1917 static QtDemuxStream *
1918 _create_stream (void)
1919 {
1920   QtDemuxStream *stream;
1921
1922   stream = g_new0 (QtDemuxStream, 1);
1923   /* new streams always need a discont */
1924   stream->discont = TRUE;
1925   /* we enable clipping for raw audio/video streams */
1926   stream->need_clip = FALSE;
1927   stream->need_process = FALSE;
1928   stream->segment_index = -1;
1929   stream->time_position = 0;
1930   stream->sample_index = -1;
1931   stream->offset_in_sample = 0;
1932   stream->new_stream = TRUE;
1933   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1934   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1935   stream->protected = FALSE;
1936   stream->protection_scheme_type = 0;
1937   stream->protection_scheme_version = 0;
1938   stream->protection_scheme_info = NULL;
1939   stream->n_samples_moof = 0;
1940   stream->duration_moof = 0;
1941   stream->duration_last_moof = 0;
1942   stream->alignment = 1;
1943   stream->stream_tags = gst_tag_list_new_empty ();
1944   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1945   g_queue_init (&stream->protection_scheme_event_queue);
1946   return stream;
1947 }
1948
1949 static gboolean
1950 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1951 {
1952   GstStructure *structure;
1953   const gchar *variant;
1954   const GstCaps *mediacaps = NULL;
1955
1956   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1957
1958   structure = gst_caps_get_structure (caps, 0);
1959   variant = gst_structure_get_string (structure, "variant");
1960
1961   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1962     QtDemuxStream *stream;
1963     const GValue *value;
1964
1965     demux->fragmented = TRUE;
1966     demux->mss_mode = TRUE;
1967
1968     if (demux->n_streams > 1) {
1969       /* can't do this, we can only renegotiate for another mss format */
1970       return FALSE;
1971     }
1972
1973     value = gst_structure_get_value (structure, "media-caps");
1974     /* create stream */
1975     if (value) {
1976       const GValue *timescale_v;
1977
1978       /* TODO update when stream changes during playback */
1979
1980       if (demux->n_streams == 0) {
1981         stream = _create_stream ();
1982         demux->streams[demux->n_streams] = stream;
1983         demux->n_streams = 1;
1984         /* mss has no stsd/stsd entry, use id 0 as default */
1985         stream->stsd_entries_length = 1;
1986         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1987         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1988       } else {
1989         stream = demux->streams[0];
1990       }
1991
1992       timescale_v = gst_structure_get_value (structure, "timescale");
1993       if (timescale_v) {
1994         stream->timescale = g_value_get_uint64 (timescale_v);
1995       } else {
1996         /* default mss timescale */
1997         stream->timescale = 10000000;
1998       }
1999       demux->timescale = stream->timescale;
2000
2001       mediacaps = gst_value_get_caps (value);
2002       if (!CUR_STREAM (stream)->caps
2003           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2004         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2005             mediacaps);
2006         stream->new_caps = TRUE;
2007       }
2008       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2009       structure = gst_caps_get_structure (mediacaps, 0);
2010       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2011         stream->subtype = FOURCC_vide;
2012
2013         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2014         gst_structure_get_int (structure, "height",
2015             &CUR_STREAM (stream)->height);
2016         gst_structure_get_fraction (structure, "framerate",
2017             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2018       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2019         gint rate = 0;
2020         stream->subtype = FOURCC_soun;
2021         gst_structure_get_int (structure, "channels",
2022             &CUR_STREAM (stream)->n_channels);
2023         gst_structure_get_int (structure, "rate", &rate);
2024         CUR_STREAM (stream)->rate = rate;
2025       }
2026     }
2027     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2028   } else {
2029     demux->mss_mode = FALSE;
2030   }
2031
2032   return TRUE;
2033 }
2034
2035 static void
2036 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2037 {
2038   gint n;
2039
2040   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2041   gst_pad_stop_task (qtdemux->sinkpad);
2042
2043   if (hard || qtdemux->upstream_format_is_time) {
2044     qtdemux->state = QTDEMUX_STATE_INITIAL;
2045     qtdemux->neededbytes = 16;
2046     qtdemux->todrop = 0;
2047     qtdemux->pullbased = FALSE;
2048     qtdemux->posted_redirect = FALSE;
2049     qtdemux->first_mdat = -1;
2050     qtdemux->header_size = 0;
2051     qtdemux->mdatoffset = -1;
2052     qtdemux->restoredata_offset = -1;
2053     if (qtdemux->mdatbuffer)
2054       gst_buffer_unref (qtdemux->mdatbuffer);
2055     if (qtdemux->restoredata_buffer)
2056       gst_buffer_unref (qtdemux->restoredata_buffer);
2057     qtdemux->mdatbuffer = NULL;
2058     qtdemux->restoredata_buffer = NULL;
2059     qtdemux->mdatleft = 0;
2060     qtdemux->mdatsize = 0;
2061     if (qtdemux->comp_brands)
2062       gst_buffer_unref (qtdemux->comp_brands);
2063     qtdemux->comp_brands = NULL;
2064     qtdemux->last_moov_offset = -1;
2065     if (qtdemux->moov_node_compressed) {
2066       g_node_destroy (qtdemux->moov_node_compressed);
2067       if (qtdemux->moov_node)
2068         g_free (qtdemux->moov_node->data);
2069     }
2070     qtdemux->moov_node_compressed = NULL;
2071     if (qtdemux->moov_node)
2072       g_node_destroy (qtdemux->moov_node);
2073     qtdemux->moov_node = NULL;
2074     if (qtdemux->tag_list)
2075       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2076     qtdemux->tag_list = gst_tag_list_new_empty ();
2077     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2078 #if 0
2079     if (qtdemux->element_index)
2080       gst_object_unref (qtdemux->element_index);
2081     qtdemux->element_index = NULL;
2082 #endif
2083     qtdemux->major_brand = 0;
2084     if (qtdemux->pending_newsegment)
2085       gst_event_unref (qtdemux->pending_newsegment);
2086     qtdemux->pending_newsegment = NULL;
2087     qtdemux->upstream_format_is_time = FALSE;
2088     qtdemux->upstream_seekable = FALSE;
2089     qtdemux->upstream_size = 0;
2090
2091     qtdemux->fragment_start = -1;
2092     qtdemux->fragment_start_offset = -1;
2093     qtdemux->duration = 0;
2094     qtdemux->moof_offset = 0;
2095     qtdemux->chapters_track_id = 0;
2096     qtdemux->have_group_id = FALSE;
2097     qtdemux->group_id = G_MAXUINT;
2098
2099     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2100         NULL);
2101     g_queue_clear (&qtdemux->protection_event_queue);
2102   }
2103   qtdemux->offset = 0;
2104   gst_adapter_clear (qtdemux->adapter);
2105   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2106   qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2107
2108   if (hard) {
2109     for (n = 0; n < qtdemux->n_streams; n++) {
2110       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2111       qtdemux->streams[n] = NULL;
2112     }
2113     qtdemux->n_streams = 0;
2114     qtdemux->n_video_streams = 0;
2115     qtdemux->n_audio_streams = 0;
2116     qtdemux->n_sub_streams = 0;
2117     qtdemux->exposed = FALSE;
2118     qtdemux->fragmented = FALSE;
2119     qtdemux->mss_mode = FALSE;
2120     gst_caps_replace (&qtdemux->media_caps, NULL);
2121     qtdemux->timescale = 0;
2122     qtdemux->got_moov = FALSE;
2123     if (qtdemux->protection_system_ids) {
2124       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2125       qtdemux->protection_system_ids = NULL;
2126     }
2127   } else if (qtdemux->mss_mode) {
2128     gst_flow_combiner_reset (qtdemux->flowcombiner);
2129     for (n = 0; n < qtdemux->n_streams; n++)
2130       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2131   } else {
2132     gst_flow_combiner_reset (qtdemux->flowcombiner);
2133     for (n = 0; n < qtdemux->n_streams; n++) {
2134       qtdemux->streams[n]->sent_eos = FALSE;
2135       qtdemux->streams[n]->time_position = 0;
2136       qtdemux->streams[n]->accumulated_base = 0;
2137     }
2138     if (!qtdemux->pending_newsegment) {
2139       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2140       if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
2141         gst_event_set_seqnum (qtdemux->pending_newsegment,
2142             qtdemux->segment_seqnum);
2143     }
2144   }
2145 }
2146
2147
2148 /* Maps the @segment to the qt edts internal segments and pushes
2149  * the correspnding segment event.
2150  *
2151  * If it ends up being at a empty segment, a gap will be pushed and the next
2152  * edts segment will be activated in sequence.
2153  *
2154  * To be used in push-mode only */
2155 static void
2156 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2157 {
2158   gint n, i;
2159
2160   for (n = 0; n < qtdemux->n_streams; n++) {
2161     QtDemuxStream *stream = qtdemux->streams[n];
2162
2163     stream->time_position = segment->start;
2164
2165     /* in push mode we should be guaranteed that we will have empty segments
2166      * at the beginning and then one segment after, other scenarios are not
2167      * supported and are discarded when parsing the edts */
2168     for (i = 0; i < stream->n_segments; i++) {
2169       if (stream->segments[i].stop_time > segment->start) {
2170         gst_qtdemux_activate_segment (qtdemux, stream, i,
2171             stream->time_position);
2172         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2173           /* push the empty segment and move to the next one */
2174           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2175               stream->time_position);
2176           continue;
2177         }
2178
2179         g_assert (i == stream->n_segments - 1);
2180       }
2181     }
2182   }
2183 }
2184
2185 static gboolean
2186 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2187     GstEvent * event)
2188 {
2189   GstQTDemux *demux = GST_QTDEMUX (parent);
2190   gboolean res = TRUE;
2191
2192   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2193
2194   switch (GST_EVENT_TYPE (event)) {
2195     case GST_EVENT_SEGMENT:
2196     {
2197       gint64 offset = 0;
2198       QtDemuxStream *stream;
2199       gint idx;
2200       GstSegment segment;
2201
2202       /* some debug output */
2203       gst_event_copy_segment (event, &segment);
2204       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2205           &segment);
2206
2207       /* erase any previously set segment */
2208       gst_event_replace (&demux->pending_newsegment, NULL);
2209
2210       if (segment.format == GST_FORMAT_TIME) {
2211         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2212         gst_event_replace (&demux->pending_newsegment, event);
2213         demux->upstream_format_is_time = TRUE;
2214       } else {
2215         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2216             "not in time format");
2217
2218         /* chain will send initial newsegment after pads have been added */
2219         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2220           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2221           goto exit;
2222         }
2223       }
2224
2225       /* check if this matches a time seek we received previously
2226        * FIXME for backwards compatibility reasons we use the
2227        * seek_offset here to compare. In the future we might want to
2228        * change this to use the seqnum as it uniquely should identify
2229        * the segment that corresponds to the seek. */
2230       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2231           ", received segment offset %" G_GINT64_FORMAT,
2232           demux->seek_offset, segment.start);
2233       if (segment.format == GST_FORMAT_BYTES
2234           && demux->seek_offset == segment.start) {
2235         GST_OBJECT_LOCK (demux);
2236         offset = segment.start;
2237
2238         segment.format = GST_FORMAT_TIME;
2239         segment.start = demux->push_seek_start;
2240         segment.stop = demux->push_seek_stop;
2241         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2242             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2243             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2244         GST_OBJECT_UNLOCK (demux);
2245       }
2246
2247       /* we only expect a BYTE segment, e.g. following a seek */
2248       if (segment.format == GST_FORMAT_BYTES) {
2249         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2250           offset = segment.start;
2251
2252           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2253               NULL, (gint64 *) & segment.start);
2254           if ((gint64) segment.start < 0)
2255             segment.start = 0;
2256         }
2257         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2258           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2259               NULL, (gint64 *) & segment.stop);
2260           /* keyframe seeking should already arrange for start >= stop,
2261            * but make sure in other rare cases */
2262           segment.stop = MAX (segment.stop, segment.start);
2263         }
2264       } else if (segment.format == GST_FORMAT_TIME) {
2265         /* push all data on the adapter before starting this
2266          * new segment */
2267         gst_qtdemux_process_adapter (demux, TRUE);
2268       } else {
2269         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2270         goto exit;
2271       }
2272
2273       /* We shouldn't modify upstream driven TIME FORMAT segment */
2274       if (!demux->upstream_format_is_time) {
2275         /* accept upstream's notion of segment and distribute along */
2276         segment.format = GST_FORMAT_TIME;
2277         segment.position = segment.time = segment.start;
2278         segment.duration = demux->segment.duration;
2279         segment.base = gst_segment_to_running_time (&demux->segment,
2280             GST_FORMAT_TIME, demux->segment.position);
2281       }
2282
2283       gst_segment_copy_into (&segment, &demux->segment);
2284       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2285
2286       /* map segment to internal qt segments and push on each stream */
2287       if (demux->n_streams) {
2288         if (demux->fragmented) {
2289           GstEvent *segment_event = gst_event_new_segment (&segment);
2290
2291           gst_event_replace (&demux->pending_newsegment, NULL);
2292           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2293           gst_qtdemux_push_event (demux, segment_event);
2294         } else {
2295           gst_event_replace (&demux->pending_newsegment, NULL);
2296           gst_qtdemux_map_and_push_segments (demux, &segment);
2297         }
2298       }
2299
2300       /* clear leftover in current segment, if any */
2301       gst_adapter_clear (demux->adapter);
2302
2303       /* set up streaming thread */
2304       demux->offset = offset;
2305       if (demux->upstream_format_is_time) {
2306         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2307             "set values to restart reading from a new atom");
2308         demux->neededbytes = 16;
2309         demux->todrop = 0;
2310       } else {
2311         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2312             NULL);
2313         if (stream) {
2314           demux->todrop = stream->samples[idx].offset - offset;
2315           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2316         } else {
2317           /* set up for EOS */
2318           demux->neededbytes = -1;
2319           demux->todrop = 0;
2320         }
2321       }
2322     exit:
2323       gst_event_unref (event);
2324       res = TRUE;
2325       goto drop;
2326     }
2327     case GST_EVENT_FLUSH_START:
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_FLUSH_STOP:
2336     {
2337       guint64 dur;
2338
2339       dur = demux->segment.duration;
2340       gst_qtdemux_reset (demux, FALSE);
2341       demux->segment.duration = dur;
2342
2343       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2344         gst_event_unref (event);
2345         goto drop;
2346       }
2347       break;
2348     }
2349     case GST_EVENT_EOS:
2350       /* If we are in push mode, and get an EOS before we've seen any streams,
2351        * then error out - we have nowhere to send the EOS */
2352       if (!demux->pullbased) {
2353         gint i;
2354         gboolean has_valid_stream = FALSE;
2355         for (i = 0; i < demux->n_streams; i++) {
2356           if (demux->streams[i]->pad != NULL) {
2357             has_valid_stream = TRUE;
2358             break;
2359           }
2360         }
2361         if (!has_valid_stream)
2362           gst_qtdemux_post_no_playable_stream_error (demux);
2363         else {
2364           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2365               (guint) gst_adapter_available (demux->adapter));
2366           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2367             res = FALSE;
2368           }
2369         }
2370       }
2371       break;
2372     case GST_EVENT_CAPS:{
2373       GstCaps *caps = NULL;
2374
2375       gst_event_parse_caps (event, &caps);
2376       gst_qtdemux_setcaps (demux, caps);
2377       res = TRUE;
2378       gst_event_unref (event);
2379       goto drop;
2380     }
2381     case GST_EVENT_PROTECTION:
2382     {
2383       const gchar *system_id = NULL;
2384
2385       gst_event_parse_protection (event, &system_id, NULL, NULL);
2386       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2387           system_id);
2388       gst_qtdemux_append_protection_system_id (demux, system_id);
2389       /* save the event for later, for source pads that have not been created */
2390       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2391       /* send it to all pads that already exist */
2392       gst_qtdemux_push_event (demux, event);
2393       res = TRUE;
2394       goto drop;
2395     }
2396     default:
2397       break;
2398   }
2399
2400   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2401
2402 drop:
2403   return res;
2404 }
2405
2406 #if 0
2407 static void
2408 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2409 {
2410   GstQTDemux *demux = GST_QTDEMUX (element);
2411
2412   GST_OBJECT_LOCK (demux);
2413   if (demux->element_index)
2414     gst_object_unref (demux->element_index);
2415   if (index) {
2416     demux->element_index = gst_object_ref (index);
2417   } else {
2418     demux->element_index = NULL;
2419   }
2420   GST_OBJECT_UNLOCK (demux);
2421   /* object lock might be taken again */
2422   if (index)
2423     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2424   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2425       demux->element_index, demux->index_id);
2426 }
2427
2428 static GstIndex *
2429 gst_qtdemux_get_index (GstElement * element)
2430 {
2431   GstIndex *result = NULL;
2432   GstQTDemux *demux = GST_QTDEMUX (element);
2433
2434   GST_OBJECT_LOCK (demux);
2435   if (demux->element_index)
2436     result = gst_object_ref (demux->element_index);
2437   GST_OBJECT_UNLOCK (demux);
2438
2439   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2440
2441   return result;
2442 }
2443 #endif
2444
2445 static void
2446 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2447 {
2448   g_free ((gpointer) stream->stco.data);
2449   stream->stco.data = NULL;
2450   g_free ((gpointer) stream->stsz.data);
2451   stream->stsz.data = NULL;
2452   g_free ((gpointer) stream->stsc.data);
2453   stream->stsc.data = NULL;
2454   g_free ((gpointer) stream->stts.data);
2455   stream->stts.data = NULL;
2456   g_free ((gpointer) stream->stss.data);
2457   stream->stss.data = NULL;
2458   g_free ((gpointer) stream->stps.data);
2459   stream->stps.data = NULL;
2460   g_free ((gpointer) stream->ctts.data);
2461   stream->ctts.data = NULL;
2462 }
2463
2464 static void
2465 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2466     QtDemuxStream * stream)
2467 {
2468   g_free (stream->segments);
2469   stream->segments = NULL;
2470   stream->segment_index = -1;
2471   stream->accumulated_base = 0;
2472 }
2473
2474 static void
2475 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2476     QtDemuxStream * stream)
2477 {
2478   g_free (stream->samples);
2479   stream->samples = NULL;
2480   gst_qtdemux_stbl_free (stream);
2481
2482   /* fragments */
2483   g_free (stream->ra_entries);
2484   stream->ra_entries = NULL;
2485   stream->n_ra_entries = 0;
2486
2487   stream->sample_index = -1;
2488   stream->stbl_index = -1;
2489   stream->n_samples = 0;
2490   stream->time_position = 0;
2491
2492   stream->n_samples_moof = 0;
2493   stream->duration_moof = 0;
2494   stream->duration_last_moof = 0;
2495 }
2496
2497 static void
2498 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2499 {
2500   gint i;
2501   if (stream->allocator)
2502     gst_object_unref (stream->allocator);
2503   while (stream->buffers) {
2504     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2505     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2506   }
2507   for (i = 0; i < stream->stsd_entries_length; i++) {
2508     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2509     if (entry->rgb8_palette) {
2510       gst_memory_unref (entry->rgb8_palette);
2511       entry->rgb8_palette = NULL;
2512     }
2513     entry->sparse = FALSE;
2514   }
2515
2516   gst_tag_list_unref (stream->stream_tags);
2517   stream->stream_tags = gst_tag_list_new_empty ();
2518   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2519   g_free (stream->redirect_uri);
2520   stream->redirect_uri = NULL;
2521   stream->sent_eos = FALSE;
2522   stream->protected = FALSE;
2523   if (stream->protection_scheme_info) {
2524     if (stream->protection_scheme_type == FOURCC_cenc) {
2525       QtDemuxCencSampleSetInfo *info =
2526           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2527       if (info->default_properties)
2528         gst_structure_free (info->default_properties);
2529       if (info->crypto_info)
2530         g_ptr_array_free (info->crypto_info, TRUE);
2531     }
2532     g_free (stream->protection_scheme_info);
2533     stream->protection_scheme_info = NULL;
2534   }
2535   stream->protection_scheme_type = 0;
2536   stream->protection_scheme_version = 0;
2537   g_queue_foreach (&stream->protection_scheme_event_queue,
2538       (GFunc) gst_event_unref, NULL);
2539   g_queue_clear (&stream->protection_scheme_event_queue);
2540   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2541   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2542 }
2543
2544 static void
2545 gst_qtdemux_stream_reset (GstQTDemux * qtdemux, QtDemuxStream * stream)
2546 {
2547   gint i;
2548   gst_qtdemux_stream_clear (qtdemux, stream);
2549   for (i = 0; i < stream->stsd_entries_length; i++) {
2550     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2551     if (entry->caps) {
2552       gst_caps_unref (entry->caps);
2553       entry->caps = NULL;
2554     }
2555   }
2556   g_free (stream->stsd_entries);
2557   stream->stsd_entries = NULL;
2558   stream->stsd_entries_length = 0;
2559 }
2560
2561
2562 static void
2563 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2564 {
2565   gst_qtdemux_stream_reset (qtdemux, stream);
2566   gst_tag_list_unref (stream->stream_tags);
2567   if (stream->pad) {
2568     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2569     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2570   }
2571   g_free (stream);
2572 }
2573
2574 static void
2575 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2576 {
2577   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2578
2579   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2580   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2581   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2582   qtdemux->n_streams--;
2583 }
2584
2585 static GstStateChangeReturn
2586 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2587 {
2588   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2589   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2590
2591   switch (transition) {
2592     case GST_STATE_CHANGE_PAUSED_TO_READY:
2593       break;
2594     default:
2595       break;
2596   }
2597
2598   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2599
2600   switch (transition) {
2601     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2602       gst_qtdemux_reset (qtdemux, TRUE);
2603       break;
2604     }
2605     default:
2606       break;
2607   }
2608
2609   return result;
2610 }
2611
2612 static void
2613 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2614 {
2615   /* counts as header data */
2616   qtdemux->header_size += length;
2617
2618   /* only consider at least a sufficiently complete ftyp atom */
2619   if (length >= 20) {
2620     GstBuffer *buf;
2621
2622     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2623     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2624         GST_FOURCC_ARGS (qtdemux->major_brand));
2625     if (qtdemux->comp_brands)
2626       gst_buffer_unref (qtdemux->comp_brands);
2627     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2628     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2629   }
2630 }
2631
2632 static void
2633 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2634     GstTagList * xmptaglist)
2635 {
2636   /* Strip out bogus fields */
2637   if (xmptaglist) {
2638     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2639       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2640       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2641     } else {
2642       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2643     }
2644
2645     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2646
2647     /* prioritize native tags using _KEEP mode */
2648     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2649     gst_tag_list_unref (xmptaglist);
2650   }
2651 }
2652
2653 static void
2654 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2655     guint offset)
2656 {
2657   GstByteReader br;
2658   guint8 version;
2659   guint32 flags = 0;
2660   guint i;
2661   guint8 iv_size = 8;
2662   QtDemuxStream *stream;
2663   GstStructure *structure;
2664   QtDemuxCencSampleSetInfo *ss_info = NULL;
2665   const gchar *system_id;
2666   gboolean uses_sub_sample_encryption = FALSE;
2667
2668   if (qtdemux->n_streams == 0)
2669     return;
2670
2671   stream = qtdemux->streams[0];
2672
2673   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2674   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2675     GST_WARNING_OBJECT (qtdemux,
2676         "Attempting PIFF box parsing on an unencrypted stream.");
2677     return;
2678   }
2679
2680   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2681       G_TYPE_STRING, &system_id, NULL);
2682   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2683
2684   stream->protected = TRUE;
2685   stream->protection_scheme_type = FOURCC_cenc;
2686
2687   if (!stream->protection_scheme_info)
2688     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2689
2690   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2691
2692   if (ss_info->default_properties)
2693     gst_structure_free (ss_info->default_properties);
2694
2695   ss_info->default_properties =
2696       gst_structure_new ("application/x-cenc",
2697       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2698
2699   if (ss_info->crypto_info) {
2700     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2701     g_ptr_array_free (ss_info->crypto_info, TRUE);
2702     ss_info->crypto_info = NULL;
2703   }
2704
2705   /* skip UUID */
2706   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2707
2708   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2709     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2710     return;
2711   }
2712
2713   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2714     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2715     return;
2716   }
2717
2718   if ((flags & 0x000001)) {
2719     guint32 algorithm_id = 0;
2720     const guint8 *kid;
2721     GstBuffer *kid_buf;
2722     gboolean is_encrypted = TRUE;
2723
2724     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2725       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2726       return;
2727     }
2728
2729     algorithm_id >>= 8;
2730     if (algorithm_id == 0) {
2731       is_encrypted = FALSE;
2732     } else if (algorithm_id == 1) {
2733       /* FIXME: maybe store this in properties? */
2734       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2735     } else if (algorithm_id == 2) {
2736       /* FIXME: maybe store this in properties? */
2737       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2738     }
2739
2740     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2741       return;
2742
2743     if (!gst_byte_reader_get_data (&br, 16, &kid))
2744       return;
2745
2746     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2747     gst_buffer_fill (kid_buf, 0, kid, 16);
2748     if (ss_info->default_properties)
2749       gst_structure_free (ss_info->default_properties);
2750     ss_info->default_properties =
2751         gst_structure_new ("application/x-cenc",
2752         "iv_size", G_TYPE_UINT, iv_size,
2753         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2754         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2755     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2756         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2757     gst_buffer_unref (kid_buf);
2758   } else if ((flags & 0x000002)) {
2759     uses_sub_sample_encryption = TRUE;
2760   }
2761
2762   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2763     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2764     return;
2765   }
2766
2767   ss_info->crypto_info =
2768       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2769       (GDestroyNotify) qtdemux_gst_structure_free);
2770
2771   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2772     GstStructure *properties;
2773     guint8 *data;
2774     GstBuffer *buf;
2775
2776     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2777     if (properties == NULL) {
2778       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2779       return;
2780     }
2781
2782     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2783       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2784       gst_structure_free (properties);
2785       return;
2786     }
2787     buf = gst_buffer_new_wrapped (data, iv_size);
2788     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2789     gst_buffer_unref (buf);
2790
2791     if (uses_sub_sample_encryption) {
2792       guint16 n_subsamples;
2793
2794       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2795           || n_subsamples == 0) {
2796         GST_ERROR_OBJECT (qtdemux,
2797             "failed to get subsample count for sample %u", i);
2798         gst_structure_free (properties);
2799         return;
2800       }
2801       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2802       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2803         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2804             i);
2805         gst_structure_free (properties);
2806         return;
2807       }
2808       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2809       gst_structure_set (properties,
2810           "subsample_count", G_TYPE_UINT, n_subsamples,
2811           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2812       gst_buffer_unref (buf);
2813     } else {
2814       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2815     }
2816
2817     g_ptr_array_add (ss_info->crypto_info, properties);
2818   }
2819 }
2820
2821 static void
2822 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2823 {
2824   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2825     0x97, 0xA9, 0x42, 0xE8,
2826     0x9C, 0x71, 0x99, 0x94,
2827     0x91, 0xE3, 0xAF, 0xAC
2828   };
2829   static const guint8 playready_uuid[] = {
2830     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2831     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2832   };
2833
2834   static const guint8 piff_sample_encryption_uuid[] = {
2835     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2836     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2837   };
2838
2839   guint offset;
2840
2841   /* counts as header data */
2842   qtdemux->header_size += length;
2843
2844   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2845
2846   if (length <= offset + 16) {
2847     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2848     return;
2849   }
2850
2851   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2852     GstBuffer *buf;
2853     GstTagList *taglist;
2854
2855     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2856         length - offset - 16, NULL);
2857     taglist = gst_tag_list_from_xmp_buffer (buf);
2858     gst_buffer_unref (buf);
2859
2860     /* make sure we have a usable taglist */
2861     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2862
2863     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2864
2865   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2866     int len;
2867     const gunichar2 *s_utf16;
2868     char *contents;
2869
2870     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2871     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2872     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2873     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2874
2875     g_free (contents);
2876
2877     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2878         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2879         (NULL));
2880   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2881     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2882   } else {
2883     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2884         GST_READ_UINT32_LE (buffer + offset),
2885         GST_READ_UINT32_LE (buffer + offset + 4),
2886         GST_READ_UINT32_LE (buffer + offset + 8),
2887         GST_READ_UINT32_LE (buffer + offset + 12));
2888   }
2889 }
2890
2891 static void
2892 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2893 {
2894   GstSidxParser sidx_parser;
2895   GstIsoffParserResult res;
2896   guint consumed;
2897
2898   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2899
2900   res =
2901       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2902       &consumed);
2903   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2904   if (res == GST_ISOFF_QT_PARSER_DONE) {
2905     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2906   }
2907   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2908 }
2909
2910 /* caller verifies at least 8 bytes in buf */
2911 static void
2912 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2913     guint64 * plength, guint32 * pfourcc)
2914 {
2915   guint64 length;
2916   guint32 fourcc;
2917
2918   length = QT_UINT32 (data);
2919   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2920   fourcc = QT_FOURCC (data + 4);
2921   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2922
2923   if (length == 0) {
2924     length = G_MAXUINT64;
2925   } else if (length == 1 && size >= 16) {
2926     /* this means we have an extended size, which is the 64 bit value of
2927      * the next 8 bytes */
2928     length = QT_UINT64 (data + 8);
2929     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2930   }
2931
2932   if (plength)
2933     *plength = length;
2934   if (pfourcc)
2935     *pfourcc = fourcc;
2936 }
2937
2938 static gboolean
2939 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2940 {
2941   guint32 version = 0;
2942   GstClockTime duration = 0;
2943
2944   if (!gst_byte_reader_get_uint32_be (br, &version))
2945     goto failed;
2946
2947   version >>= 24;
2948   if (version == 1) {
2949     if (!gst_byte_reader_get_uint64_be (br, &duration))
2950       goto failed;
2951   } else {
2952     guint32 dur = 0;
2953
2954     if (!gst_byte_reader_get_uint32_be (br, &dur))
2955       goto failed;
2956     duration = dur;
2957   }
2958
2959   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2960   qtdemux->duration = duration;
2961
2962   return TRUE;
2963
2964 failed:
2965   {
2966     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2967     return FALSE;
2968   }
2969 }
2970
2971 static gboolean
2972 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2973     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2974 {
2975   if (!stream->parsed_trex && qtdemux->moov_node) {
2976     GNode *mvex, *trex;
2977     GstByteReader trex_data;
2978
2979     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2980     if (mvex) {
2981       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2982           &trex_data);
2983       while (trex) {
2984         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
2985
2986         /* skip version/flags */
2987         if (!gst_byte_reader_skip (&trex_data, 4))
2988           goto next;
2989         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2990           goto next;
2991         if (id != stream->track_id)
2992           goto next;
2993         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
2994           goto next;
2995         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2996           goto next;
2997         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2998           goto next;
2999         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3000           goto next;
3001
3002         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3003             "duration %d,  size %d, flags 0x%x", stream->track_id,
3004             dur, size, flags);
3005
3006         stream->parsed_trex = TRUE;
3007         stream->def_sample_description_index = sdi;
3008         stream->def_sample_duration = dur;
3009         stream->def_sample_size = size;
3010         stream->def_sample_flags = flags;
3011
3012       next:
3013         /* iterate all siblings */
3014         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3015             &trex_data);
3016       }
3017     }
3018   }
3019
3020   *ds_duration = stream->def_sample_duration;
3021   *ds_size = stream->def_sample_size;
3022   *ds_flags = stream->def_sample_flags;
3023
3024   /* even then, above values are better than random ... */
3025   if (G_UNLIKELY (!stream->parsed_trex)) {
3026     GST_WARNING_OBJECT (qtdemux,
3027         "failed to find fragment defaults for stream %d", stream->track_id);
3028     return FALSE;
3029   }
3030
3031   return TRUE;
3032 }
3033
3034 /* This method should be called whenever a more accurate duration might
3035  * have been found. It will update all relevant variables if/where needed
3036  */
3037 static void
3038 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3039 {
3040   guint i;
3041   guint64 movdur;
3042   GstClockTime prevdur;
3043
3044   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3045
3046   if (movdur > qtdemux->duration) {
3047     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3048     GST_DEBUG_OBJECT (qtdemux,
3049         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3050         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3051     qtdemux->duration = movdur;
3052     GST_DEBUG_OBJECT (qtdemux,
3053         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3054         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3055         GST_TIME_ARGS (qtdemux->segment.stop));
3056     if (qtdemux->segment.duration == prevdur) {
3057       /* If the current segment has duration/stop identical to previous duration
3058        * update them also (because they were set at that point in time with
3059        * the wrong duration */
3060       /* We convert the value *from* the timescale version to avoid rounding errors */
3061       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3062       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3063       qtdemux->segment.duration = fixeddur;
3064       qtdemux->segment.stop = fixeddur;
3065     }
3066   }
3067   for (i = 0; i < qtdemux->n_streams; i++) {
3068     QtDemuxStream *stream = qtdemux->streams[i];
3069     if (stream) {
3070       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3071       if (movdur > stream->duration) {
3072         GST_DEBUG_OBJECT (qtdemux,
3073             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3074             GST_TIME_ARGS (duration));
3075         stream->duration = movdur;
3076         /* internal duration tracking state has been updated above, so */
3077         /* preserve an open-ended dummy segment rather than repeatedly updating
3078          * it and spamming downstream accordingly with segment events */
3079         if (stream->dummy_segment &&
3080             GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3081           /* Update all dummy values to new duration */
3082           stream->segments[0].stop_time = duration;
3083           stream->segments[0].duration = duration;
3084           stream->segments[0].media_stop = duration;
3085
3086           /* let downstream know we possibly have a new stop time */
3087           if (stream->segment_index != -1) {
3088             GstClockTime pos;
3089
3090             if (qtdemux->segment.rate >= 0) {
3091               pos = stream->segment.start;
3092             } else {
3093               pos = stream->segment.stop;
3094             }
3095
3096             gst_qtdemux_stream_update_segment (qtdemux, stream,
3097                 stream->segment_index, pos, NULL, NULL);
3098           }
3099         }
3100       }
3101     }
3102   }
3103 }
3104
3105 static gboolean
3106 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3107     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3108     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3109     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3110     gboolean has_tfdt)
3111 {
3112   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3113   guint64 timestamp;
3114   gint32 data_offset = 0;
3115   guint32 flags = 0, first_flags = 0, samples_count = 0;
3116   gint i;
3117   guint8 *data;
3118   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3119   QtDemuxSample *sample;
3120   gboolean ismv = FALSE;
3121   gint64 initial_offset;
3122
3123   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3124       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3125       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3126       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3127
3128   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3129     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3130     return TRUE;
3131   }
3132
3133   /* presence of stss or not can't really tell us much,
3134    * and flags and so on tend to be marginally reliable in these files */
3135   if (stream->subtype == FOURCC_soun) {
3136     GST_DEBUG_OBJECT (qtdemux,
3137         "sound track in fragmented file; marking all keyframes");
3138     stream->all_keyframe = TRUE;
3139   }
3140
3141   if (!gst_byte_reader_skip (trun, 1) ||
3142       !gst_byte_reader_get_uint24_be (trun, &flags))
3143     goto fail;
3144
3145   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3146     goto fail;
3147
3148   if (flags & TR_DATA_OFFSET) {
3149     /* note this is really signed */
3150     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3151       goto fail;
3152     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3153     /* default base offset = first byte of moof */
3154     if (*base_offset == -1) {
3155       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3156       *base_offset = moof_offset;
3157     }
3158     *running_offset = *base_offset + data_offset;
3159   } else {
3160     /* if no offset at all, that would mean data starts at moof start,
3161      * which is a bit wrong and is ismv crappy way, so compensate
3162      * assuming data is in mdat following moof */
3163     if (*base_offset == -1) {
3164       *base_offset = moof_offset + moof_length + 8;
3165       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3166       ismv = TRUE;
3167     }
3168     if (*running_offset == -1)
3169       *running_offset = *base_offset;
3170   }
3171
3172   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3173       *running_offset);
3174   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3175       data_offset, flags, samples_count);
3176
3177   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3178     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3179       GST_DEBUG_OBJECT (qtdemux,
3180           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3181       flags ^= TR_FIRST_SAMPLE_FLAGS;
3182     } else {
3183       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3184         goto fail;
3185       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3186     }
3187   }
3188
3189   /* FIXME ? spec says other bits should also be checked to determine
3190    * entry size (and prefix size for that matter) */
3191   entry_size = 0;
3192   dur_offset = size_offset = 0;
3193   if (flags & TR_SAMPLE_DURATION) {
3194     GST_LOG_OBJECT (qtdemux, "entry duration present");
3195     dur_offset = entry_size;
3196     entry_size += 4;
3197   }
3198   if (flags & TR_SAMPLE_SIZE) {
3199     GST_LOG_OBJECT (qtdemux, "entry size present");
3200     size_offset = entry_size;
3201     entry_size += 4;
3202   }
3203   if (flags & TR_SAMPLE_FLAGS) {
3204     GST_LOG_OBJECT (qtdemux, "entry flags present");
3205     flags_offset = entry_size;
3206     entry_size += 4;
3207   }
3208   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3209     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3210     ct_offset = entry_size;
3211     entry_size += 4;
3212   }
3213
3214   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3215     goto fail;
3216   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3217
3218   if (stream->n_samples + samples_count >=
3219       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3220     goto index_too_big;
3221
3222   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3223       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3224       (stream->n_samples + samples_count) *
3225       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3226
3227   /* create a new array of samples if it's the first sample parsed */
3228   if (stream->n_samples == 0) {
3229     g_assert (stream->samples == NULL);
3230     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3231     /* or try to reallocate it with space enough to insert the new samples */
3232   } else
3233     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3234         stream->n_samples + samples_count);
3235   if (stream->samples == NULL)
3236     goto out_of_memory;
3237
3238   if (qtdemux->fragment_start != -1) {
3239     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3240     qtdemux->fragment_start = -1;
3241   } else {
3242     if (stream->n_samples == 0) {
3243       if (decode_ts > 0) {
3244         timestamp = decode_ts;
3245       } else if (stream->pending_seek != NULL) {
3246         /* if we don't have a timestamp from a tfdt box, we'll use the one
3247          * from the mfra seek table */
3248         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3249             GST_TIME_ARGS (stream->pending_seek->ts));
3250
3251         /* FIXME: this is not fully correct, the timestamp refers to the random
3252          * access sample refered to in the tfra entry, which may not necessarily
3253          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3254         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3255       } else {
3256         timestamp = 0;
3257       }
3258
3259       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3260       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3261           GST_TIME_ARGS (gst_ts));
3262     } else {
3263       /* subsequent fragments extend stream */
3264       timestamp =
3265           stream->samples[stream->n_samples - 1].timestamp +
3266           stream->samples[stream->n_samples - 1].duration;
3267
3268       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3269        * difference (1 sec.) between decode_ts and timestamp, prefer the
3270        * former */
3271       if (has_tfdt && !qtdemux->upstream_format_is_time
3272           && ABSDIFF (decode_ts, timestamp) >
3273           MAX (stream->duration_last_moof / 2,
3274               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3275         GST_INFO_OBJECT (qtdemux,
3276             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3277             ") are significantly different (more than %" GST_TIME_FORMAT
3278             "), using decode_ts",
3279             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3280             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3281             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3282                     MAX (stream->duration_last_moof / 2,
3283                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3284         timestamp = decode_ts;
3285       }
3286
3287       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3288       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3289           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3290     }
3291   }
3292
3293   initial_offset = *running_offset;
3294
3295   sample = stream->samples + stream->n_samples;
3296   for (i = 0; i < samples_count; i++) {
3297     guint32 dur, size, sflags, ct;
3298
3299     /* first read sample data */
3300     if (flags & TR_SAMPLE_DURATION) {
3301       dur = QT_UINT32 (data + dur_offset);
3302     } else {
3303       dur = d_sample_duration;
3304     }
3305     if (flags & TR_SAMPLE_SIZE) {
3306       size = QT_UINT32 (data + size_offset);
3307     } else {
3308       size = d_sample_size;
3309     }
3310     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3311       if (i == 0) {
3312         sflags = first_flags;
3313       } else {
3314         sflags = d_sample_flags;
3315       }
3316     } else if (flags & TR_SAMPLE_FLAGS) {
3317       sflags = QT_UINT32 (data + flags_offset);
3318     } else {
3319       sflags = d_sample_flags;
3320     }
3321     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3322       ct = QT_UINT32 (data + ct_offset);
3323     } else {
3324       ct = 0;
3325     }
3326     data += entry_size;
3327
3328     /* fill the sample information */
3329     sample->offset = *running_offset;
3330     sample->pts_offset = ct;
3331     sample->size = size;
3332     sample->timestamp = timestamp;
3333     sample->duration = dur;
3334     /* sample-is-difference-sample */
3335     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3336      * now idea how it relates to bitfield other than massive LE/BE confusion */
3337     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3338     *running_offset += size;
3339     timestamp += dur;
3340     stream->duration_moof += dur;
3341     sample++;
3342   }
3343
3344   /* Update total duration if needed */
3345   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3346
3347   /* Pre-emptively figure out size of mdat based on trun information.
3348    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3349    * size, else we will still be able to use this when dealing with gap'ed
3350    * input */
3351   qtdemux->mdatleft = *running_offset - initial_offset;
3352   qtdemux->mdatoffset = initial_offset;
3353   qtdemux->mdatsize = qtdemux->mdatleft;
3354
3355   stream->n_samples += samples_count;
3356   stream->n_samples_moof += samples_count;
3357
3358   if (stream->pending_seek != NULL)
3359     stream->pending_seek = NULL;
3360
3361   return TRUE;
3362
3363 fail:
3364   {
3365     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3366     return FALSE;
3367   }
3368 out_of_memory:
3369   {
3370     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3371         stream->n_samples);
3372     return FALSE;
3373   }
3374 index_too_big:
3375   {
3376     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3377         "be larger than %uMB (broken file?)", stream->n_samples,
3378         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3379     return FALSE;
3380   }
3381 }
3382
3383 /* find stream with @id */
3384 static inline QtDemuxStream *
3385 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3386 {
3387   QtDemuxStream *stream;
3388   gint i;
3389
3390   /* check */
3391   if (G_UNLIKELY (!id)) {
3392     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3393     return NULL;
3394   }
3395
3396   /* try to get it fast and simple */
3397   if (G_LIKELY (id <= qtdemux->n_streams)) {
3398     stream = qtdemux->streams[id - 1];
3399     if (G_LIKELY (stream->track_id == id))
3400       return stream;
3401   }
3402
3403   /* linear search otherwise */
3404   for (i = 0; i < qtdemux->n_streams; i++) {
3405     stream = qtdemux->streams[i];
3406     if (stream->track_id == id)
3407       return stream;
3408   }
3409   if (qtdemux->mss_mode) {
3410     /* mss should have only 1 stream anyway */
3411     return qtdemux->streams[0];
3412   }
3413
3414   return NULL;
3415 }
3416
3417 static gboolean
3418 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3419     guint32 * fragment_number)
3420 {
3421   if (!gst_byte_reader_skip (mfhd, 4))
3422     goto fail;
3423   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3424     goto fail;
3425   return TRUE;
3426 fail:
3427   {
3428     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3429     return FALSE;
3430   }
3431 }
3432
3433 static gboolean
3434 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3435     QtDemuxStream ** stream, guint32 * default_sample_duration,
3436     guint32 * default_sample_size, guint32 * default_sample_flags,
3437     gint64 * base_offset)
3438 {
3439   guint32 flags = 0;
3440   guint32 track_id = 0;
3441
3442   if (!gst_byte_reader_skip (tfhd, 1) ||
3443       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3444     goto invalid_track;
3445
3446   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3447     goto invalid_track;
3448
3449   *stream = qtdemux_find_stream (qtdemux, track_id);
3450   if (G_UNLIKELY (!*stream))
3451     goto unknown_stream;
3452
3453   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3454     *base_offset = qtdemux->moof_offset;
3455
3456   if (flags & TF_BASE_DATA_OFFSET)
3457     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3458       goto invalid_track;
3459
3460   /* obtain stream defaults */
3461   qtdemux_parse_trex (qtdemux, *stream,
3462       default_sample_duration, default_sample_size, default_sample_flags);
3463
3464   (*stream)->stsd_sample_description_id =
3465       (*stream)->def_sample_description_index - 1;
3466
3467   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3468     guint32 sample_description_index;
3469     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3470       goto invalid_track;
3471     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3472   }
3473
3474   if (qtdemux->mss_mode) {
3475     /* mss has no stsd entry */
3476     (*stream)->stsd_sample_description_id = 0;
3477   }
3478
3479   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3480     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3481       goto invalid_track;
3482
3483   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3484     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3485       goto invalid_track;
3486
3487   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3488     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3489       goto invalid_track;
3490
3491   return TRUE;
3492
3493 invalid_track:
3494   {
3495     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3496     return FALSE;
3497   }
3498 unknown_stream:
3499   {
3500     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3501     return TRUE;
3502   }
3503 }
3504
3505 static gboolean
3506 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3507     guint64 * decode_time)
3508 {
3509   guint32 version = 0;
3510
3511   if (!gst_byte_reader_get_uint32_be (br, &version))
3512     return FALSE;
3513
3514   version >>= 24;
3515   if (version == 1) {
3516     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3517       goto failed;
3518   } else {
3519     guint32 dec_time = 0;
3520     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3521       goto failed;
3522     *decode_time = dec_time;
3523   }
3524
3525   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3526       *decode_time);
3527
3528   return TRUE;
3529
3530 failed:
3531   {
3532     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3533     return FALSE;
3534   }
3535 }
3536
3537 /* Returns a pointer to a GstStructure containing the properties of
3538  * the stream sample identified by @sample_index. The caller must unref
3539  * the returned object after use. Returns NULL if unsuccessful. */
3540 static GstStructure *
3541 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3542     QtDemuxStream * stream, guint sample_index)
3543 {
3544   QtDemuxCencSampleSetInfo *info = NULL;
3545
3546   g_return_val_if_fail (stream != NULL, NULL);
3547   g_return_val_if_fail (stream->protected, NULL);
3548   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3549
3550   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3551
3552   /* Currently, cenc properties for groups of samples are not supported, so
3553    * simply return a copy of the default sample properties */
3554   return gst_structure_copy (info->default_properties);
3555 }
3556
3557 /* Parses the sizes of sample auxiliary information contained within a stream,
3558  * as given in a saiz box. Returns array of sample_count guint8 size values,
3559  * or NULL on failure */
3560 static guint8 *
3561 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3562     GstByteReader * br, guint32 * sample_count)
3563 {
3564   guint32 flags = 0;
3565   guint8 *info_sizes;
3566   guint8 default_info_size;
3567
3568   g_return_val_if_fail (qtdemux != NULL, NULL);
3569   g_return_val_if_fail (stream != NULL, NULL);
3570   g_return_val_if_fail (br != NULL, NULL);
3571   g_return_val_if_fail (sample_count != NULL, NULL);
3572
3573   if (!gst_byte_reader_get_uint32_be (br, &flags))
3574     return NULL;
3575
3576   if (flags & 0x1) {
3577     /* aux_info_type and aux_info_type_parameter are ignored */
3578     if (!gst_byte_reader_skip (br, 8))
3579       return NULL;
3580   }
3581
3582   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3583     return NULL;
3584   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3585
3586   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3587     return NULL;
3588   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3589
3590
3591   if (default_info_size == 0) {
3592     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3593       return NULL;
3594     }
3595   } else {
3596     info_sizes = g_new (guint8, *sample_count);
3597     memset (info_sizes, default_info_size, *sample_count);
3598   }
3599
3600   return info_sizes;
3601 }
3602
3603 /* Parses the offset of sample auxiliary information contained within a stream,
3604  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3605 static gboolean
3606 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3607     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3608     guint64 * offset)
3609 {
3610   guint8 version = 0;
3611   guint32 flags = 0;
3612   guint32 aux_info_type = 0;
3613   guint32 aux_info_type_parameter = 0;
3614   guint32 entry_count;
3615   guint32 off_32;
3616   guint64 off_64;
3617   const guint8 *aux_info_type_data = NULL;
3618
3619   g_return_val_if_fail (qtdemux != NULL, FALSE);
3620   g_return_val_if_fail (stream != NULL, FALSE);
3621   g_return_val_if_fail (br != NULL, FALSE);
3622   g_return_val_if_fail (offset != NULL, FALSE);
3623
3624   if (!gst_byte_reader_get_uint8 (br, &version))
3625     return FALSE;
3626
3627   if (!gst_byte_reader_get_uint24_be (br, &flags))
3628     return FALSE;
3629
3630   if (flags & 0x1) {
3631
3632     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3633       return FALSE;
3634     aux_info_type = QT_FOURCC (aux_info_type_data);
3635
3636     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3637       return FALSE;
3638   } else if (stream->protected) {
3639     aux_info_type = stream->protection_scheme_type;
3640   } else {
3641     aux_info_type = CUR_STREAM (stream)->fourcc;
3642   }
3643
3644   if (info_type)
3645     *info_type = aux_info_type;
3646   if (info_type_parameter)
3647     *info_type_parameter = aux_info_type_parameter;
3648
3649   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3650       "aux_info_type_parameter:  %#06x",
3651       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3652
3653   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3654     return FALSE;
3655
3656   if (entry_count != 1) {
3657     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3658     return FALSE;
3659   }
3660
3661   if (version == 0) {
3662     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3663       return FALSE;
3664     *offset = (guint64) off_32;
3665   } else {
3666     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3667       return FALSE;
3668     *offset = off_64;
3669   }
3670
3671   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3672   return TRUE;
3673 }
3674
3675 static void
3676 qtdemux_gst_structure_free (GstStructure * gststructure)
3677 {
3678   if (gststructure) {
3679     gst_structure_free (gststructure);
3680   }
3681 }
3682
3683 /* Parses auxiliary information relating to samples protected using Common
3684  * Encryption (cenc); the format of this information is defined in
3685  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3686 static gboolean
3687 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3688     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3689 {
3690   QtDemuxCencSampleSetInfo *ss_info = NULL;
3691   guint8 size;
3692   gint i;
3693   GPtrArray *old_crypto_info = NULL;
3694   guint old_entries = 0;
3695
3696   g_return_val_if_fail (qtdemux != NULL, FALSE);
3697   g_return_val_if_fail (stream != NULL, FALSE);
3698   g_return_val_if_fail (br != NULL, FALSE);
3699   g_return_val_if_fail (stream->protected, FALSE);
3700   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3701
3702   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3703
3704   if (ss_info->crypto_info) {
3705     old_crypto_info = ss_info->crypto_info;
3706     /* Count number of non-null entries remaining at the tail end */
3707     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3708       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3709         break;
3710       old_entries++;
3711     }
3712   }
3713
3714   ss_info->crypto_info =
3715       g_ptr_array_new_full (sample_count + old_entries,
3716       (GDestroyNotify) qtdemux_gst_structure_free);
3717
3718   /* We preserve old entries because we parse the next moof in advance
3719    * of consuming all samples from the previous moof, and otherwise
3720    * we'd discard the corresponding crypto info for the samples
3721    * from the previous fragment. */
3722   if (old_entries) {
3723     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3724         old_entries);
3725     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3726       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3727               i));
3728       g_ptr_array_index (old_crypto_info, i) = NULL;
3729     }
3730   }
3731
3732   if (old_crypto_info) {
3733     /* Everything now belongs to the new array */
3734     g_ptr_array_free (old_crypto_info, TRUE);
3735   }
3736
3737   for (i = 0; i < sample_count; ++i) {
3738     GstStructure *properties;
3739     guint16 n_subsamples = 0;
3740     guint8 *data;
3741     guint iv_size;
3742     GstBuffer *buf;
3743
3744     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3745     if (properties == NULL) {
3746       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3747       return FALSE;
3748     }
3749     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3750       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3751       gst_structure_free (properties);
3752       return FALSE;
3753     }
3754     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3755       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3756       gst_structure_free (properties);
3757       return FALSE;
3758     }
3759     buf = gst_buffer_new_wrapped (data, iv_size);
3760     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3761     gst_buffer_unref (buf);
3762     size = info_sizes[i];
3763     if (size > iv_size) {
3764       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3765           || !(n_subsamples > 0)) {
3766         gst_structure_free (properties);
3767         GST_ERROR_OBJECT (qtdemux,
3768             "failed to get subsample count for sample %u", i);
3769         return FALSE;
3770       }
3771       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3772       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3773         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3774             i);
3775         gst_structure_free (properties);
3776         return FALSE;
3777       }
3778       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3779       if (!buf) {
3780         gst_structure_free (properties);
3781         return FALSE;
3782       }
3783       gst_structure_set (properties,
3784           "subsample_count", G_TYPE_UINT, n_subsamples,
3785           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3786       gst_buffer_unref (buf);
3787     } else {
3788       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3789     }
3790     g_ptr_array_add (ss_info->crypto_info, properties);
3791   }
3792   return TRUE;
3793 }
3794
3795 /* Converts a UUID in raw byte form to a string representation, as defined in
3796  * RFC 4122. The caller takes ownership of the returned string and is
3797  * responsible for freeing it after use. */
3798 static gchar *
3799 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3800 {
3801   const guint8 *uuid = (const guint8 *) uuid_bytes;
3802
3803   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3804       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3805       uuid[0], uuid[1], uuid[2], uuid[3],
3806       uuid[4], uuid[5], uuid[6], uuid[7],
3807       uuid[8], uuid[9], uuid[10], uuid[11],
3808       uuid[12], uuid[13], uuid[14], uuid[15]);
3809 }
3810
3811 /* Parses a Protection System Specific Header box (pssh), as defined in the
3812  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3813  * information needed by a specific content protection system in order to
3814  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3815  * otherwise. */
3816 static gboolean
3817 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3818 {
3819   gchar *sysid_string;
3820   guint32 pssh_size = QT_UINT32 (node->data);
3821   GstBuffer *pssh = NULL;
3822   GstEvent *event = NULL;
3823   guint32 parent_box_type;
3824   gint i;
3825
3826   if (G_UNLIKELY (pssh_size < 32U)) {
3827     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3828     return FALSE;
3829   }
3830
3831   sysid_string =
3832       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3833
3834   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3835
3836   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3837   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3838       gst_buffer_get_size (pssh));
3839
3840   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3841
3842   /* Push an event containing the pssh box onto the queues of all streams. */
3843   event = gst_event_new_protection (sysid_string, pssh,
3844       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3845   for (i = 0; i < qtdemux->n_streams; ++i) {
3846     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3847         gst_event_ref (event));
3848   }
3849   g_free (sysid_string);
3850   gst_event_unref (event);
3851   gst_buffer_unref (pssh);
3852   return TRUE;
3853 }
3854
3855 static gboolean
3856 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3857     guint64 moof_offset, QtDemuxStream * stream)
3858 {
3859   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3860   GNode *uuid_node;
3861   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3862   GNode *saiz_node, *saio_node, *pssh_node;
3863   GstByteReader saiz_data, saio_data;
3864   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3865   gint64 base_offset, running_offset;
3866   guint32 frag_num;
3867
3868   /* NOTE @stream ignored */
3869
3870   moof_node = g_node_new ((guint8 *) buffer);
3871   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3872   qtdemux_node_dump (qtdemux, moof_node);
3873
3874   /* Get fragment number from mfhd and check it's valid */
3875   mfhd_node =
3876       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3877   if (mfhd_node == NULL)
3878     goto missing_mfhd;
3879   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3880     goto fail;
3881   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3882
3883   /* unknown base_offset to start with */
3884   base_offset = running_offset = -1;
3885   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3886   while (traf_node) {
3887     guint64 decode_time = 0;
3888
3889     /* Fragment Header node */
3890     tfhd_node =
3891         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3892         &tfhd_data);
3893     if (!tfhd_node)
3894       goto missing_tfhd;
3895     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3896             &ds_size, &ds_flags, &base_offset))
3897       goto missing_tfhd;
3898
3899     /* The following code assumes at most a single set of sample auxiliary
3900      * data in the fragment (consisting of a saiz box and a corresponding saio
3901      * box); in theory, however, there could be multiple sets of sample
3902      * auxiliary data in a fragment. */
3903     saiz_node =
3904         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3905         &saiz_data);
3906     if (saiz_node) {
3907       guint32 info_type = 0;
3908       guint64 offset = 0;
3909       guint32 info_type_parameter = 0;
3910
3911       g_free (qtdemux->cenc_aux_info_sizes);
3912
3913       qtdemux->cenc_aux_info_sizes =
3914           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3915           &qtdemux->cenc_aux_sample_count);
3916       if (qtdemux->cenc_aux_info_sizes == NULL) {
3917         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3918         goto fail;
3919       }
3920       saio_node =
3921           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3922           &saio_data);
3923       if (!saio_node) {
3924         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3925         g_free (qtdemux->cenc_aux_info_sizes);
3926         qtdemux->cenc_aux_info_sizes = NULL;
3927         goto fail;
3928       }
3929
3930       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3931                   &info_type, &info_type_parameter, &offset))) {
3932         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3933         g_free (qtdemux->cenc_aux_info_sizes);
3934         qtdemux->cenc_aux_info_sizes = NULL;
3935         goto fail;
3936       }
3937       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3938         offset += (guint64) (base_offset - qtdemux->moof_offset);
3939       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3940         GstByteReader br;
3941         if (offset > length) {
3942           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3943           qtdemux->cenc_aux_info_offset = offset;
3944         } else {
3945           gst_byte_reader_init (&br, buffer + offset, length - offset);
3946           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3947                   qtdemux->cenc_aux_info_sizes,
3948                   qtdemux->cenc_aux_sample_count)) {
3949             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3950             g_free (qtdemux->cenc_aux_info_sizes);
3951             qtdemux->cenc_aux_info_sizes = NULL;
3952             goto fail;
3953           }
3954         }
3955       }
3956     }
3957
3958     tfdt_node =
3959         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3960         &tfdt_data);
3961     if (tfdt_node) {
3962       /* We'll use decode_time to interpolate timestamps
3963        * in case the input timestamps are missing */
3964       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3965
3966       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3967           " (%" GST_TIME_FORMAT ")", decode_time,
3968           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
3969                   decode_time) : GST_CLOCK_TIME_NONE));
3970
3971       /* Discard the fragment buffer timestamp info to avoid using it.
3972        * Rely on tfdt instead as it is more accurate than the timestamp
3973        * that is fetched from a manifest/playlist and is usually
3974        * less accurate. */
3975       qtdemux->fragment_start = -1;
3976     }
3977
3978     if (G_UNLIKELY (!stream)) {
3979       /* we lost track of offset, we'll need to regain it,
3980        * but can delay complaining until later or avoid doing so altogether */
3981       base_offset = -2;
3982       goto next;
3983     }
3984     if (G_UNLIKELY (base_offset < -1))
3985       goto lost_offset;
3986
3987     if (qtdemux->upstream_format_is_time)
3988       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3989
3990     /* initialise moof sample data */
3991     stream->n_samples_moof = 0;
3992     stream->duration_last_moof = stream->duration_moof;
3993     stream->duration_moof = 0;
3994
3995     /* Track Run node */
3996     trun_node =
3997         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3998         &trun_data);
3999     while (trun_node) {
4000       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4001           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4002           &running_offset, decode_time, (tfdt_node != NULL));
4003       /* iterate all siblings */
4004       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4005           &trun_data);
4006     }
4007
4008     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4009     if (uuid_node) {
4010       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4011       guint32 box_length = QT_UINT32 (uuid_buffer);
4012
4013       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4014     }
4015
4016     /* if no new base_offset provided for next traf,
4017      * base is end of current traf */
4018     base_offset = running_offset;
4019     running_offset = -1;
4020
4021     if (stream->n_samples_moof && stream->duration_moof)
4022       stream->new_caps = TRUE;
4023
4024   next:
4025     /* iterate all siblings */
4026     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4027   }
4028
4029   /* parse any protection system info */
4030   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4031   while (pssh_node) {
4032     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4033     qtdemux_parse_pssh (qtdemux, pssh_node);
4034     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4035   }
4036
4037   g_node_destroy (moof_node);
4038   return TRUE;
4039
4040 missing_tfhd:
4041   {
4042     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4043     goto fail;
4044   }
4045 missing_mfhd:
4046   {
4047     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4048     goto fail;
4049   }
4050 lost_offset:
4051   {
4052     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4053     goto fail;
4054   }
4055 fail:
4056   {
4057     g_node_destroy (moof_node);
4058     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4059         (_("This file is corrupt and cannot be played.")), (NULL));
4060     return FALSE;
4061   }
4062 }
4063
4064 #if 0
4065 /* might be used if some day we actually use mfra & co
4066  * for random access to fragments,
4067  * but that will require quite some modifications and much less relying
4068  * on a sample array */
4069 #endif
4070
4071 static gboolean
4072 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4073 {
4074   QtDemuxStream *stream;
4075   guint32 ver_flags, track_id, len, num_entries, i;
4076   guint value_size, traf_size, trun_size, sample_size;
4077   guint64 time = 0, moof_offset = 0;
4078 #if 0
4079   GstBuffer *buf = NULL;
4080   GstFlowReturn ret;
4081 #endif
4082   GstByteReader tfra;
4083
4084   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4085
4086   if (!gst_byte_reader_skip (&tfra, 8))
4087     return FALSE;
4088
4089   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4090     return FALSE;
4091
4092   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4093       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4094       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4095     return FALSE;
4096
4097   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4098
4099   stream = qtdemux_find_stream (qtdemux, track_id);
4100   if (stream == NULL)
4101     goto unknown_trackid;
4102
4103   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4104   sample_size = (len & 3) + 1;
4105   trun_size = ((len & 12) >> 2) + 1;
4106   traf_size = ((len & 48) >> 4) + 1;
4107
4108   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4109       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4110
4111   if (num_entries == 0)
4112     goto no_samples;
4113
4114   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4115           value_size + value_size + traf_size + trun_size + sample_size))
4116     goto corrupt_file;
4117
4118   g_free (stream->ra_entries);
4119   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4120   stream->n_ra_entries = num_entries;
4121
4122   for (i = 0; i < num_entries; i++) {
4123     qt_atom_parser_get_offset (&tfra, value_size, &time);
4124     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4125     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4126     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4127     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4128
4129     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4130
4131     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4132         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4133
4134     stream->ra_entries[i].ts = time;
4135     stream->ra_entries[i].moof_offset = moof_offset;
4136
4137     /* don't want to go through the entire file and read all moofs at startup */
4138 #if 0
4139     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4140     if (ret != GST_FLOW_OK)
4141       goto corrupt_file;
4142     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4143         moof_offset, stream);
4144     gst_buffer_unref (buf);
4145 #endif
4146   }
4147
4148   check_update_duration (qtdemux, time);
4149
4150   return TRUE;
4151
4152 /* ERRORS */
4153 unknown_trackid:
4154   {
4155     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4156     return FALSE;
4157   }
4158 corrupt_file:
4159   {
4160     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4161     return FALSE;
4162   }
4163 no_samples:
4164   {
4165     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4166     return FALSE;
4167   }
4168 }
4169
4170 static gboolean
4171 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4172 {
4173   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4174   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4175   GstBuffer *mfro = NULL, *mfra = NULL;
4176   GstFlowReturn flow;
4177   gboolean ret = FALSE;
4178   GNode *mfra_node, *tfra_node;
4179   guint64 mfra_offset = 0;
4180   guint32 fourcc, mfra_size;
4181   gint64 len;
4182
4183   /* query upstream size in bytes */
4184   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4185     goto size_query_failed;
4186
4187   /* mfro box should be at the very end of the file */
4188   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4189   if (flow != GST_FLOW_OK)
4190     goto exit;
4191
4192   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4193
4194   fourcc = QT_FOURCC (mfro_map.data + 4);
4195   if (fourcc != FOURCC_mfro)
4196     goto exit;
4197
4198   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4199   if (mfro_map.size < 16)
4200     goto invalid_mfro_size;
4201
4202   mfra_size = QT_UINT32 (mfro_map.data + 12);
4203   if (mfra_size >= len)
4204     goto invalid_mfra_size;
4205
4206   mfra_offset = len - mfra_size;
4207
4208   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4209       mfra_offset, mfra_size);
4210
4211   /* now get and parse mfra box */
4212   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4213   if (flow != GST_FLOW_OK)
4214     goto broken_file;
4215
4216   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4217
4218   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4219   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4220
4221   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4222
4223   while (tfra_node) {
4224     qtdemux_parse_tfra (qtdemux, tfra_node);
4225     /* iterate all siblings */
4226     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4227   }
4228   g_node_destroy (mfra_node);
4229
4230   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4231   ret = TRUE;
4232
4233 exit:
4234
4235   if (mfro) {
4236     if (mfro_map.memory != NULL)
4237       gst_buffer_unmap (mfro, &mfro_map);
4238     gst_buffer_unref (mfro);
4239   }
4240   if (mfra) {
4241     if (mfra_map.memory != NULL)
4242       gst_buffer_unmap (mfra, &mfra_map);
4243     gst_buffer_unref (mfra);
4244   }
4245   return ret;
4246
4247 /* ERRORS */
4248 size_query_failed:
4249   {
4250     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4251     goto exit;
4252   }
4253 invalid_mfro_size:
4254   {
4255     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4256     goto exit;
4257   }
4258 invalid_mfra_size:
4259   {
4260     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4261     goto exit;
4262   }
4263 broken_file:
4264   {
4265     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4266     goto exit;
4267   }
4268 }
4269
4270 static guint64
4271 add_offset (guint64 offset, guint64 advance)
4272 {
4273   /* Avoid 64-bit overflow by clamping */
4274   if (offset > G_MAXUINT64 - advance)
4275     return G_MAXUINT64;
4276   return offset + advance;
4277 }
4278
4279 static GstFlowReturn
4280 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4281 {
4282   guint64 length = 0;
4283   guint32 fourcc = 0;
4284   GstBuffer *buf = NULL;
4285   GstFlowReturn ret = GST_FLOW_OK;
4286   guint64 cur_offset = qtdemux->offset;
4287   GstMapInfo map;
4288
4289   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4290   if (G_UNLIKELY (ret != GST_FLOW_OK))
4291     goto beach;
4292   gst_buffer_map (buf, &map, GST_MAP_READ);
4293   if (G_LIKELY (map.size >= 8))
4294     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4295   gst_buffer_unmap (buf, &map);
4296   gst_buffer_unref (buf);
4297
4298   /* maybe we already got most we needed, so only consider this eof */
4299   if (G_UNLIKELY (length == 0)) {
4300     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4301         (_("Invalid atom size.")),
4302         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4303             GST_FOURCC_ARGS (fourcc)));
4304     ret = GST_FLOW_EOS;
4305     goto beach;
4306   }
4307
4308   switch (fourcc) {
4309     case FOURCC_moof:
4310       /* record for later parsing when needed */
4311       if (!qtdemux->moof_offset) {
4312         qtdemux->moof_offset = qtdemux->offset;
4313       }
4314       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4315         /* FIXME */
4316       } else {
4317         qtdemux->offset += length;      /* skip moof and keep going */
4318       }
4319       if (qtdemux->got_moov) {
4320         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4321         ret = GST_FLOW_EOS;
4322         goto beach;
4323       }
4324       break;
4325     case FOURCC_mdat:
4326     case FOURCC_free:
4327     case FOURCC_skip:
4328     case FOURCC_wide:
4329     case FOURCC_PICT:
4330     case FOURCC_pnot:
4331     {
4332       GST_LOG_OBJECT (qtdemux,
4333           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4334           GST_FOURCC_ARGS (fourcc), cur_offset);
4335       qtdemux->offset = add_offset (qtdemux->offset, length);
4336       break;
4337     }
4338     case FOURCC_moov:
4339     {
4340       GstBuffer *moov = NULL;
4341
4342       if (qtdemux->got_moov) {
4343         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4344         qtdemux->offset = add_offset (qtdemux->offset, length);
4345         goto beach;
4346       }
4347
4348       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4349       if (ret != GST_FLOW_OK)
4350         goto beach;
4351       gst_buffer_map (moov, &map, GST_MAP_READ);
4352
4353       if (length != map.size) {
4354         /* Some files have a 'moov' atom at the end of the file which contains
4355          * a terminal 'free' atom where the body of the atom is missing.
4356          * Check for, and permit, this special case.
4357          */
4358         if (map.size >= 8) {
4359           guint8 *final_data = map.data + (map.size - 8);
4360           guint32 final_length = QT_UINT32 (final_data);
4361           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4362
4363           if (final_fourcc == FOURCC_free
4364               && map.size + final_length - 8 == length) {
4365             /* Ok, we've found that special case. Allocate a new buffer with
4366              * that free atom actually present. */
4367             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4368             gst_buffer_fill (newmoov, 0, map.data, map.size);
4369             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4370             gst_buffer_unmap (moov, &map);
4371             gst_buffer_unref (moov);
4372             moov = newmoov;
4373             gst_buffer_map (moov, &map, GST_MAP_READ);
4374           }
4375         }
4376       }
4377
4378       if (length != map.size) {
4379         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4380             (_("This file is incomplete and cannot be played.")),
4381             ("We got less than expected (received %" G_GSIZE_FORMAT
4382                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4383                 (guint) length, cur_offset));
4384         gst_buffer_unmap (moov, &map);
4385         gst_buffer_unref (moov);
4386         ret = GST_FLOW_ERROR;
4387         goto beach;
4388       }
4389       qtdemux->offset += length;
4390
4391       qtdemux_parse_moov (qtdemux, map.data, length);
4392       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4393
4394       qtdemux_parse_tree (qtdemux);
4395       if (qtdemux->moov_node_compressed) {
4396         g_node_destroy (qtdemux->moov_node_compressed);
4397         g_free (qtdemux->moov_node->data);
4398       }
4399       qtdemux->moov_node_compressed = NULL;
4400       g_node_destroy (qtdemux->moov_node);
4401       qtdemux->moov_node = NULL;
4402       gst_buffer_unmap (moov, &map);
4403       gst_buffer_unref (moov);
4404       qtdemux->got_moov = TRUE;
4405
4406       break;
4407     }
4408     case FOURCC_ftyp:
4409     {
4410       GstBuffer *ftyp = NULL;
4411
4412       /* extract major brand; might come in handy for ISO vs QT issues */
4413       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4414       if (ret != GST_FLOW_OK)
4415         goto beach;
4416       qtdemux->offset += length;
4417       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4418       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4419       gst_buffer_unmap (ftyp, &map);
4420       gst_buffer_unref (ftyp);
4421       break;
4422     }
4423     case FOURCC_uuid:
4424     {
4425       GstBuffer *uuid = NULL;
4426
4427       /* uuid are extension atoms */
4428       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4429       if (ret != GST_FLOW_OK)
4430         goto beach;
4431       qtdemux->offset += length;
4432       gst_buffer_map (uuid, &map, GST_MAP_READ);
4433       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4434       gst_buffer_unmap (uuid, &map);
4435       gst_buffer_unref (uuid);
4436       break;
4437     }
4438     case FOURCC_sidx:
4439     {
4440       GstBuffer *sidx = NULL;
4441       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4442       if (ret != GST_FLOW_OK)
4443         goto beach;
4444       qtdemux->offset += length;
4445       gst_buffer_map (sidx, &map, GST_MAP_READ);
4446       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4447       gst_buffer_unmap (sidx, &map);
4448       gst_buffer_unref (sidx);
4449       break;
4450     }
4451     default:
4452     {
4453       GstBuffer *unknown = NULL;
4454
4455       GST_LOG_OBJECT (qtdemux,
4456           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4457           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4458           cur_offset);
4459       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4460       if (ret != GST_FLOW_OK)
4461         goto beach;
4462       gst_buffer_map (unknown, &map, GST_MAP_READ);
4463       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4464       gst_buffer_unmap (unknown, &map);
4465       gst_buffer_unref (unknown);
4466       qtdemux->offset += length;
4467       break;
4468     }
4469   }
4470
4471 beach:
4472   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4473     /* digested all data, show what we have */
4474     qtdemux_prepare_streams (qtdemux);
4475     ret = qtdemux_expose_streams (qtdemux);
4476
4477     qtdemux->state = QTDEMUX_STATE_MOVIE;
4478     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4479         qtdemux->state);
4480     return ret;
4481   }
4482   return ret;
4483 }
4484
4485 /* Seeks to the previous keyframe of the indexed stream and
4486  * aligns other streams with respect to the keyframe timestamp
4487  * of indexed stream. Only called in case of Reverse Playback
4488  */
4489 static GstFlowReturn
4490 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4491 {
4492   guint8 n = 0;
4493   guint32 seg_idx = 0, k_index = 0;
4494   guint32 ref_seg_idx, ref_k_index;
4495   GstClockTime k_pos = 0, last_stop = 0;
4496   QtDemuxSegment *seg = NULL;
4497   QtDemuxStream *ref_str = NULL;
4498   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4499   guint64 target_ts;
4500
4501   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4502    * and finally align all the other streams on that timestamp with their
4503    * respective keyframes */
4504   for (n = 0; n < qtdemux->n_streams; n++) {
4505     QtDemuxStream *str = qtdemux->streams[n];
4506
4507     /* No candidate yet, take the first stream */
4508     if (!ref_str) {
4509       ref_str = str;
4510       continue;
4511     }
4512
4513     /* So that stream has a segment, we prefer video streams */
4514     if (str->subtype == FOURCC_vide) {
4515       ref_str = str;
4516       break;
4517     }
4518   }
4519
4520   if (G_UNLIKELY (!ref_str)) {
4521     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4522     goto eos;
4523   }
4524
4525   if (G_UNLIKELY (!ref_str->from_sample)) {
4526     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4527     goto eos;
4528   }
4529
4530   /* So that stream has been playing from from_sample to to_sample. We will
4531    * get the timestamp of the previous sample and search for a keyframe before
4532    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4533   if (ref_str->subtype == FOURCC_vide) {
4534     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4535         ref_str->from_sample - 1, FALSE);
4536   } else {
4537     if (ref_str->from_sample >= 10)
4538       k_index = ref_str->from_sample - 10;
4539     else
4540       k_index = 0;
4541   }
4542
4543   target_ts =
4544       ref_str->samples[k_index].timestamp +
4545       ref_str->samples[k_index].pts_offset;
4546
4547   /* get current segment for that stream */
4548   seg = &ref_str->segments[ref_str->segment_index];
4549   /* Use segment start in original timescale for comparisons */
4550   seg_media_start_mov = seg->trak_media_start;
4551
4552   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4553       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4554       k_index, target_ts, seg_media_start_mov,
4555       GST_TIME_ARGS (seg->media_start));
4556
4557   /* Crawl back through segments to find the one containing this I frame */
4558   while (target_ts < seg_media_start_mov) {
4559     GST_DEBUG_OBJECT (qtdemux,
4560         "keyframe position (sample %u) is out of segment %u " " target %"
4561         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4562         ref_str->segment_index, target_ts, seg_media_start_mov);
4563
4564     if (G_UNLIKELY (!ref_str->segment_index)) {
4565       /* Reached first segment, let's consider it's EOS */
4566       goto eos;
4567     }
4568     ref_str->segment_index--;
4569     seg = &ref_str->segments[ref_str->segment_index];
4570     /* Use segment start in original timescale for comparisons */
4571     seg_media_start_mov = seg->trak_media_start;
4572   }
4573   /* Calculate time position of the keyframe and where we should stop */
4574   k_pos =
4575       QTSTREAMTIME_TO_GSTTIME (ref_str,
4576       target_ts - seg->trak_media_start) + seg->time;
4577   last_stop =
4578       QTSTREAMTIME_TO_GSTTIME (ref_str,
4579       ref_str->samples[ref_str->from_sample].timestamp -
4580       seg->trak_media_start) + seg->time;
4581
4582   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4583       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4584       k_index, GST_TIME_ARGS (k_pos));
4585
4586   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4587   qtdemux->segment.position = last_stop;
4588   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4589       GST_TIME_ARGS (last_stop));
4590
4591   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4592     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4593     goto eos;
4594   }
4595
4596   ref_seg_idx = ref_str->segment_index;
4597   ref_k_index = k_index;
4598
4599   /* Align them all on this */
4600   for (n = 0; n < qtdemux->n_streams; n++) {
4601     guint32 index = 0;
4602     GstClockTime seg_time = 0;
4603     QtDemuxStream *str = qtdemux->streams[n];
4604
4605     /* aligning reference stream again might lead to backing up to yet another
4606      * keyframe (due to timestamp rounding issues),
4607      * potentially putting more load on downstream; so let's try to avoid */
4608     if (str == ref_str) {
4609       seg_idx = ref_seg_idx;
4610       seg = &str->segments[seg_idx];
4611       k_index = ref_k_index;
4612       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4613           "sample at index %d", n, ref_str->segment_index, k_index);
4614     } else {
4615       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4616       GST_DEBUG_OBJECT (qtdemux,
4617           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4618           seg_idx, GST_TIME_ARGS (k_pos));
4619
4620       /* get segment and time in the segment */
4621       seg = &str->segments[seg_idx];
4622       seg_time = k_pos - seg->time;
4623
4624       /* get the media time in the segment.
4625        * No adjustment for empty "filler" segments */
4626       if (seg->media_start != GST_CLOCK_TIME_NONE)
4627         seg_time += seg->media_start;
4628
4629       /* get the index of the sample with media time */
4630       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4631       GST_DEBUG_OBJECT (qtdemux,
4632           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4633           GST_TIME_ARGS (seg_time), index);
4634
4635       /* find previous keyframe */
4636       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4637     }
4638
4639     /* Remember until where we want to go */
4640     str->to_sample = str->from_sample - 1;
4641     /* Define our time position */
4642     target_ts =
4643         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4644     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4645     if (seg->media_start != GST_CLOCK_TIME_NONE)
4646       str->time_position -= seg->media_start;
4647
4648     /* Now seek back in time */
4649     gst_qtdemux_move_stream (qtdemux, str, k_index);
4650     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4651         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4652         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4653   }
4654
4655   return GST_FLOW_OK;
4656
4657 eos:
4658   return GST_FLOW_EOS;
4659 }
4660
4661 /*
4662  * Gets the current qt segment start, stop and position for the
4663  * given time offset. This is used in update_segment()
4664  */
4665 static void
4666 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4667     QtDemuxStream * stream, GstClockTime offset,
4668     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4669 {
4670   GstClockTime seg_time;
4671   GstClockTime start, stop, time;
4672   QtDemuxSegment *segment;
4673
4674   segment = &stream->segments[stream->segment_index];
4675
4676   /* get time in this segment */
4677   seg_time = (offset - segment->time) * segment->rate;
4678
4679   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4680       GST_TIME_ARGS (seg_time));
4681
4682   if (G_UNLIKELY (seg_time > segment->duration)) {
4683     GST_LOG_OBJECT (stream->pad,
4684         "seg_time > segment->duration %" GST_TIME_FORMAT,
4685         GST_TIME_ARGS (segment->duration));
4686     seg_time = segment->duration;
4687   }
4688
4689   /* qtdemux->segment.stop is in outside-time-realm, whereas
4690    * segment->media_stop is in track-time-realm.
4691    *
4692    * In order to compare the two, we need to bring segment.stop
4693    * into the track-time-realm
4694    *
4695    * FIXME - does this comment still hold? Don't see any conversion here */
4696
4697   stop = qtdemux->segment.stop;
4698   if (stop == GST_CLOCK_TIME_NONE)
4699     stop = qtdemux->segment.duration;
4700   if (stop == GST_CLOCK_TIME_NONE)
4701     stop = segment->media_stop;
4702   else
4703     stop =
4704         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4705
4706   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4707     start = segment->time + seg_time;
4708     time = offset;
4709     stop = start - seg_time + segment->duration;
4710   } else if (qtdemux->segment.rate >= 0) {
4711     start = MIN (segment->media_start + seg_time, stop);
4712     time = offset;
4713   } else {
4714     if (segment->media_start >= qtdemux->segment.start) {
4715       time = segment->time;
4716     } else {
4717       time = segment->time + (qtdemux->segment.start - segment->media_start);
4718     }
4719
4720     start = MAX (segment->media_start, qtdemux->segment.start);
4721     stop = MIN (segment->media_start + seg_time, stop);
4722   }
4723
4724   *_start = start;
4725   *_stop = stop;
4726   *_time = time;
4727 }
4728
4729 /*
4730  * Updates the qt segment used for the stream and pushes a new segment event
4731  * downstream on this stream's pad.
4732  */
4733 static gboolean
4734 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4735     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4736     GstClockTime * _stop)
4737 {
4738   QtDemuxSegment *segment;
4739   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4740   gdouble rate;
4741   GstEvent *event;
4742
4743   /* update the current segment */
4744   stream->segment_index = seg_idx;
4745
4746   /* get the segment */
4747   segment = &stream->segments[seg_idx];
4748
4749   if (G_UNLIKELY (offset < segment->time)) {
4750     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4751         GST_TIME_ARGS (segment->time));
4752     return FALSE;
4753   }
4754
4755   /* segment lies beyond total indicated duration */
4756   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4757           segment->time > qtdemux->segment.duration)) {
4758     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4759         " < segment->time %" GST_TIME_FORMAT,
4760         GST_TIME_ARGS (qtdemux->segment.duration),
4761         GST_TIME_ARGS (segment->time));
4762     return FALSE;
4763   }
4764
4765   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4766       &start, &stop, &time);
4767
4768   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4769       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4770       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4771
4772   /* combine global rate with that of the segment */
4773   rate = segment->rate * qtdemux->segment.rate;
4774
4775   /* Copy flags from main segment */
4776   stream->segment.flags = qtdemux->segment.flags;
4777
4778   /* update the segment values used for clipping */
4779   stream->segment.offset = qtdemux->segment.offset;
4780   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4781   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4782   stream->segment.rate = rate;
4783   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4784       stream->cslg_shift);
4785   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4786       stream->cslg_shift);
4787   stream->segment.time = time;
4788   stream->segment.position = stream->segment.start;
4789
4790   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4791       &stream->segment);
4792
4793   /* now prepare and send the segment */
4794   if (stream->pad) {
4795     event = gst_event_new_segment (&stream->segment);
4796     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4797       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4798     }
4799     gst_pad_push_event (stream->pad, event);
4800     /* assume we can send more data now */
4801     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4802     /* clear to send tags on this pad now */
4803     gst_qtdemux_push_tags (qtdemux, stream);
4804   }
4805
4806   if (_start)
4807     *_start = start;
4808   if (_stop)
4809     *_stop = stop;
4810
4811   return TRUE;
4812 }
4813
4814 /* activate the given segment number @seg_idx of @stream at time @offset.
4815  * @offset is an absolute global position over all the segments.
4816  *
4817  * This will push out a NEWSEGMENT event with the right values and
4818  * position the stream index to the first decodable sample before
4819  * @offset.
4820  */
4821 static gboolean
4822 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4823     guint32 seg_idx, GstClockTime offset)
4824 {
4825   QtDemuxSegment *segment;
4826   guint32 index, kf_index;
4827   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4828
4829   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4830       seg_idx, GST_TIME_ARGS (offset));
4831
4832   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4833           &start, &stop))
4834     return FALSE;
4835
4836   segment = &stream->segments[stream->segment_index];
4837
4838   /* in the fragmented case, we pick a fragment that starts before our
4839    * desired position and rely on downstream to wait for a keyframe
4840    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4841    * tfra entries tells us which trun/sample the key unit is in, but we don't
4842    * make use of this additional information at the moment) */
4843   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4844     stream->to_sample = G_MAXUINT32;
4845     return TRUE;
4846   } else {
4847     /* well, it will be taken care of below */
4848     qtdemux->fragmented_seek_pending = FALSE;
4849     /* FIXME ideally the do_fragmented_seek can be done right here,
4850      * rather than at loop level
4851      * (which might even allow handling edit lists in a fragmented file) */
4852   }
4853
4854   /* We don't need to look for a sample in push-based */
4855   if (!qtdemux->pullbased)
4856     return TRUE;
4857
4858   /* and move to the keyframe before the indicated media time of the
4859    * segment */
4860   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4861     if (qtdemux->segment.rate >= 0) {
4862       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4863       stream->to_sample = G_MAXUINT32;
4864       GST_DEBUG_OBJECT (stream->pad,
4865           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4866           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4867           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4868     } else {
4869       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4870       stream->to_sample = index;
4871       GST_DEBUG_OBJECT (stream->pad,
4872           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4873           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4874           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4875     }
4876   } else {
4877     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4878         "this is an empty segment");
4879     return TRUE;
4880   }
4881
4882   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4883    * encountered an error and printed a message so we return appropriately */
4884   if (index == -1)
4885     return FALSE;
4886
4887   /* we're at the right spot */
4888   if (index == stream->sample_index) {
4889     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4890     return TRUE;
4891   }
4892
4893   /* find keyframe of the target index */
4894   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4895
4896 /* *INDENT-OFF* */
4897 /* indent does stupid stuff with stream->samples[].timestamp */
4898
4899   /* if we move forwards, we don't have to go back to the previous
4900    * keyframe since we already sent that. We can also just jump to
4901    * the keyframe right before the target index if there is one. */
4902   if (index > stream->sample_index) {
4903     /* moving forwards check if we move past a keyframe */
4904     if (kf_index > stream->sample_index) {
4905       GST_DEBUG_OBJECT (stream->pad,
4906            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4907            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4908            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4909       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4910     } else {
4911       GST_DEBUG_OBJECT (stream->pad,
4912           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4913           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4914           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4915     }
4916   } else {
4917     GST_DEBUG_OBJECT (stream->pad,
4918         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4919         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4920         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4921     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4922   }
4923
4924 /* *INDENT-ON* */
4925
4926   return TRUE;
4927 }
4928
4929 /* prepare to get the current sample of @stream, getting essential values.
4930  *
4931  * This function will also prepare and send the segment when needed.
4932  *
4933  * Return FALSE if the stream is EOS.
4934  *
4935  * PULL-BASED
4936  */
4937 static gboolean
4938 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4939     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4940     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4941     gboolean * keyframe)
4942 {
4943   QtDemuxSample *sample;
4944   GstClockTime time_position;
4945   guint32 seg_idx;
4946
4947   g_return_val_if_fail (stream != NULL, FALSE);
4948
4949   time_position = stream->time_position;
4950   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4951     goto eos;
4952
4953   seg_idx = stream->segment_index;
4954   if (G_UNLIKELY (seg_idx == -1)) {
4955     /* find segment corresponding to time_position if we are looking
4956      * for a segment. */
4957     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4958   }
4959
4960   /* different segment, activate it, sample_index will be set. */
4961   if (G_UNLIKELY (stream->segment_index != seg_idx))
4962     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4963
4964   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4965                   segment_index]))) {
4966     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4967
4968     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4969         " prepare empty sample");
4970
4971     *empty = TRUE;
4972     *pts = *dts = time_position;
4973     *duration = seg->duration - (time_position - seg->time);
4974
4975     return TRUE;
4976   }
4977
4978   *empty = FALSE;
4979
4980   if (stream->sample_index == -1)
4981     stream->sample_index = 0;
4982
4983   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4984       stream->sample_index, stream->n_samples);
4985
4986   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4987     if (!qtdemux->fragmented)
4988       goto eos;
4989
4990     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4991     do {
4992       GstFlowReturn flow;
4993
4994       GST_OBJECT_LOCK (qtdemux);
4995       flow = qtdemux_add_fragmented_samples (qtdemux);
4996       GST_OBJECT_UNLOCK (qtdemux);
4997
4998       if (flow != GST_FLOW_OK)
4999         goto eos;
5000     }
5001     while (stream->sample_index >= stream->n_samples);
5002   }
5003
5004   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5005     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5006         stream->sample_index);
5007     return FALSE;
5008   }
5009
5010   /* now get the info for the sample we're at */
5011   sample = &stream->samples[stream->sample_index];
5012
5013   *dts = QTSAMPLE_DTS (stream, sample);
5014   *pts = QTSAMPLE_PTS (stream, sample);
5015   *offset = sample->offset;
5016   *size = sample->size;
5017   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5018   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5019
5020   return TRUE;
5021
5022   /* special cases */
5023 eos:
5024   {
5025     stream->time_position = GST_CLOCK_TIME_NONE;
5026     return FALSE;
5027   }
5028 }
5029
5030 /* move to the next sample in @stream.
5031  *
5032  * Moves to the next segment when needed.
5033  */
5034 static void
5035 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5036 {
5037   QtDemuxSample *sample;
5038   QtDemuxSegment *segment;
5039
5040   /* get current segment */
5041   segment = &stream->segments[stream->segment_index];
5042
5043   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5044     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5045     goto next_segment;
5046   }
5047
5048   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5049     /* Mark the stream as EOS */
5050     GST_DEBUG_OBJECT (qtdemux,
5051         "reached max allowed sample %u, mark EOS", stream->to_sample);
5052     stream->time_position = GST_CLOCK_TIME_NONE;
5053     return;
5054   }
5055
5056   /* move to next sample */
5057   stream->sample_index++;
5058   stream->offset_in_sample = 0;
5059
5060   /* reached the last sample, we need the next segment */
5061   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5062     goto next_segment;
5063
5064   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5065     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5066         stream->sample_index);
5067     return;
5068   }
5069
5070   /* get next sample */
5071   sample = &stream->samples[stream->sample_index];
5072
5073   /* see if we are past the segment */
5074   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5075     goto next_segment;
5076
5077   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5078     /* inside the segment, update time_position, looks very familiar to
5079      * GStreamer segments, doesn't it? */
5080     stream->time_position =
5081         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5082   } else {
5083     /* not yet in segment, time does not yet increment. This means
5084      * that we are still prerolling keyframes to the decoder so it can
5085      * decode the first sample of the segment. */
5086     stream->time_position = segment->time;
5087   }
5088   return;
5089
5090   /* move to the next segment */
5091 next_segment:
5092   {
5093     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5094
5095     if (stream->segment_index == stream->n_segments - 1) {
5096       /* are we at the end of the last segment, we're EOS */
5097       stream->time_position = GST_CLOCK_TIME_NONE;
5098     } else {
5099       /* else we're only at the end of the current segment */
5100       stream->time_position = segment->stop_time;
5101     }
5102     /* make sure we select a new segment */
5103
5104     /* accumulate previous segments */
5105     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5106       stream->accumulated_base +=
5107           (stream->segment.stop -
5108           stream->segment.start) / ABS (stream->segment.rate);
5109
5110     stream->segment_index = -1;
5111   }
5112 }
5113
5114 static void
5115 gst_qtdemux_sync_streams (GstQTDemux * demux)
5116 {
5117   gint i;
5118
5119   if (demux->n_streams <= 1)
5120     return;
5121
5122   for (i = 0; i < demux->n_streams; i++) {
5123     QtDemuxStream *stream;
5124     GstClockTime end_time;
5125
5126     stream = demux->streams[i];
5127
5128     if (!stream->pad)
5129       continue;
5130
5131     /* TODO advance time on subtitle streams here, if any some day */
5132
5133     /* some clips/trailers may have unbalanced streams at the end,
5134      * so send EOS on shorter stream to prevent stalling others */
5135
5136     /* do not mess with EOS if SEGMENT seeking */
5137     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5138       continue;
5139
5140     if (demux->pullbased) {
5141       /* loop mode is sample time based */
5142       if (!STREAM_IS_EOS (stream))
5143         continue;
5144     } else {
5145       /* push mode is byte position based */
5146       if (stream->n_samples &&
5147           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5148         continue;
5149     }
5150
5151     if (stream->sent_eos)
5152       continue;
5153
5154     /* only act if some gap */
5155     end_time = stream->segments[stream->n_segments - 1].stop_time;
5156     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5157         ", stream end: %" GST_TIME_FORMAT,
5158         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5159     if (GST_CLOCK_TIME_IS_VALID (end_time)
5160         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5161       GstEvent *event;
5162
5163       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5164           GST_PAD_NAME (stream->pad));
5165       stream->sent_eos = TRUE;
5166       event = gst_event_new_eos ();
5167       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5168         gst_event_set_seqnum (event, demux->segment_seqnum);
5169       gst_pad_push_event (stream->pad, event);
5170     }
5171   }
5172 }
5173
5174 /* EOS and NOT_LINKED need to be combined. This means that we return:
5175  *
5176  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5177  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5178  */
5179 static GstFlowReturn
5180 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5181     GstFlowReturn ret)
5182 {
5183   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5184
5185   if (stream->pad)
5186     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5187         ret);
5188   else
5189     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5190
5191   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5192   return ret;
5193 }
5194
5195 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5196  * completely clipped
5197  *
5198  * Should be used only with raw buffers */
5199 static GstBuffer *
5200 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5201     GstBuffer * buf)
5202 {
5203   guint64 start, stop, cstart, cstop, diff;
5204   GstClockTime pts, duration;
5205   gsize size, osize;
5206   gint num_rate, denom_rate;
5207   gint frame_size;
5208   gboolean clip_data;
5209   guint offset;
5210
5211   osize = size = gst_buffer_get_size (buf);
5212   offset = 0;
5213
5214   /* depending on the type, setup the clip parameters */
5215   if (stream->subtype == FOURCC_soun) {
5216     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5217     num_rate = GST_SECOND;
5218     denom_rate = (gint) CUR_STREAM (stream)->rate;
5219     clip_data = TRUE;
5220   } else if (stream->subtype == FOURCC_vide) {
5221     frame_size = size;
5222     num_rate = CUR_STREAM (stream)->fps_n;
5223     denom_rate = CUR_STREAM (stream)->fps_d;
5224     clip_data = FALSE;
5225   } else
5226     goto wrong_type;
5227
5228   if (frame_size <= 0)
5229     goto bad_frame_size;
5230
5231   /* we can only clip if we have a valid pts */
5232   pts = GST_BUFFER_PTS (buf);
5233   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5234     goto no_pts;
5235
5236   duration = GST_BUFFER_DURATION (buf);
5237
5238   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5239     duration =
5240         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5241   }
5242
5243   start = pts;
5244   stop = start + duration;
5245
5246   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5247               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5248     goto clipped;
5249
5250   /* see if some clipping happened */
5251   diff = cstart - start;
5252   if (diff > 0) {
5253     pts += diff;
5254     duration -= diff;
5255
5256     if (clip_data) {
5257       /* bring clipped time to samples and to bytes */
5258       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5259       diff *= frame_size;
5260
5261       GST_DEBUG_OBJECT (qtdemux,
5262           "clipping start to %" GST_TIME_FORMAT " %"
5263           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5264
5265       offset = diff;
5266       size -= diff;
5267     }
5268   }
5269   diff = stop - cstop;
5270   if (diff > 0) {
5271     duration -= diff;
5272
5273     if (clip_data) {
5274       /* bring clipped time to samples and then to bytes */
5275       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5276       diff *= frame_size;
5277       GST_DEBUG_OBJECT (qtdemux,
5278           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5279           " bytes", GST_TIME_ARGS (cstop), diff);
5280       size -= diff;
5281     }
5282   }
5283
5284   if (offset != 0 || size != osize)
5285     gst_buffer_resize (buf, offset, size);
5286
5287   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5288   GST_BUFFER_PTS (buf) = pts;
5289   GST_BUFFER_DURATION (buf) = duration;
5290
5291   return buf;
5292
5293   /* dropped buffer */
5294 wrong_type:
5295   {
5296     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5297     return buf;
5298   }
5299 bad_frame_size:
5300   {
5301     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5302     return buf;
5303   }
5304 no_pts:
5305   {
5306     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5307     return buf;
5308   }
5309 clipped:
5310   {
5311     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5312     gst_buffer_unref (buf);
5313     return NULL;
5314   }
5315 }
5316
5317 static GstBuffer *
5318 gst_qtdemux_align_buffer (GstQTDemux * demux,
5319     GstBuffer * buffer, gsize alignment)
5320 {
5321   GstMapInfo map;
5322
5323   gst_buffer_map (buffer, &map, GST_MAP_READ);
5324
5325   if (map.size < sizeof (guintptr)) {
5326     gst_buffer_unmap (buffer, &map);
5327     return buffer;
5328   }
5329
5330   if (((guintptr) map.data) & (alignment - 1)) {
5331     GstBuffer *new_buffer;
5332     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5333
5334     new_buffer = gst_buffer_new_allocate (NULL,
5335         gst_buffer_get_size (buffer), &params);
5336
5337     /* Copy data "by hand", so ensure alignment is kept: */
5338     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5339
5340     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5341     GST_DEBUG_OBJECT (demux,
5342         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5343         alignment);
5344
5345     gst_buffer_unmap (buffer, &map);
5346     gst_buffer_unref (buffer);
5347
5348     return new_buffer;
5349   }
5350
5351   gst_buffer_unmap (buffer, &map);
5352   return buffer;
5353 }
5354
5355 /* the input buffer metadata must be writable,
5356  * but time/duration etc not yet set and need not be preserved */
5357 static GstBuffer *
5358 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5359     GstBuffer * buf)
5360 {
5361   GstMapInfo map;
5362   guint nsize = 0;
5363   gchar *str;
5364
5365   /* not many cases for now */
5366   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5367     /* send a one time dvd clut event */
5368     if (stream->pending_event && stream->pad)
5369       gst_pad_push_event (stream->pad, stream->pending_event);
5370     stream->pending_event = NULL;
5371   }
5372
5373   if (G_UNLIKELY (stream->subtype != FOURCC_text
5374           && stream->subtype != FOURCC_sbtl &&
5375           stream->subtype != FOURCC_subp)) {
5376     return buf;
5377   }
5378
5379   gst_buffer_map (buf, &map, GST_MAP_READ);
5380
5381   /* empty buffer is sent to terminate previous subtitle */
5382   if (map.size <= 2) {
5383     gst_buffer_unmap (buf, &map);
5384     gst_buffer_unref (buf);
5385     return NULL;
5386   }
5387   if (stream->subtype == FOURCC_subp) {
5388     /* That's all the processing needed for subpictures */
5389     gst_buffer_unmap (buf, &map);
5390     return buf;
5391   }
5392
5393   nsize = GST_READ_UINT16_BE (map.data);
5394   nsize = MIN (nsize, map.size - 2);
5395
5396   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5397       nsize, map.size);
5398
5399   /* takes care of UTF-8 validation or UTF-16 recognition,
5400    * no other encoding expected */
5401   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5402   gst_buffer_unmap (buf, &map);
5403   if (str) {
5404     gst_buffer_unref (buf);
5405     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5406   } else {
5407     /* this should not really happen unless the subtitle is corrupted */
5408     gst_buffer_unref (buf);
5409     buf = NULL;
5410   }
5411
5412   /* FIXME ? convert optional subsequent style info to markup */
5413
5414   return buf;
5415 }
5416
5417 /* Sets a buffer's attributes properly and pushes it downstream.
5418  * Also checks for additional actions and custom processing that may
5419  * need to be done first.
5420  */
5421 static GstFlowReturn
5422 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5423     QtDemuxStream * stream, GstBuffer * buf,
5424     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5425     gboolean keyframe, GstClockTime position, guint64 byte_position)
5426 {
5427   GstFlowReturn ret = GST_FLOW_OK;
5428
5429   /* offset the timestamps according to the edit list */
5430
5431   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5432     gchar *url;
5433     GstMapInfo map;
5434
5435     gst_buffer_map (buf, &map, GST_MAP_READ);
5436     url = g_strndup ((gchar *) map.data, map.size);
5437     gst_buffer_unmap (buf, &map);
5438     if (url != NULL && strlen (url) != 0) {
5439       /* we have RTSP redirect now */
5440       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5441           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5442               gst_structure_new ("redirect",
5443                   "new-location", G_TYPE_STRING, url, NULL)));
5444       qtdemux->posted_redirect = TRUE;
5445     } else {
5446       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5447           "posting");
5448     }
5449     g_free (url);
5450   }
5451
5452   /* position reporting */
5453   if (qtdemux->segment.rate >= 0) {
5454     qtdemux->segment.position = position;
5455     gst_qtdemux_sync_streams (qtdemux);
5456   }
5457
5458   if (G_UNLIKELY (!stream->pad)) {
5459     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5460     gst_buffer_unref (buf);
5461     goto exit;
5462   }
5463
5464   /* send out pending buffers */
5465   while (stream->buffers) {
5466     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5467
5468     if (G_UNLIKELY (stream->discont)) {
5469       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5470       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5471       stream->discont = FALSE;
5472     } else {
5473       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5474     }
5475
5476     if (stream->alignment > 1)
5477       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5478     gst_pad_push (stream->pad, buffer);
5479
5480     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5481   }
5482
5483   /* we're going to modify the metadata */
5484   buf = gst_buffer_make_writable (buf);
5485
5486   if (G_UNLIKELY (stream->need_process))
5487     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5488
5489   if (!buf) {
5490     goto exit;
5491   }
5492
5493   GST_BUFFER_DTS (buf) = dts;
5494   GST_BUFFER_PTS (buf) = pts;
5495   GST_BUFFER_DURATION (buf) = duration;
5496   GST_BUFFER_OFFSET (buf) = -1;
5497   GST_BUFFER_OFFSET_END (buf) = -1;
5498
5499   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5500     gst_buffer_append_memory (buf,
5501         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5502
5503   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5504     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5505   }
5506 #if 0
5507   if (G_UNLIKELY (qtdemux->element_index)) {
5508     GstClockTime stream_time;
5509
5510     stream_time =
5511         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5512         timestamp);
5513     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5514       GST_LOG_OBJECT (qtdemux,
5515           "adding association %" GST_TIME_FORMAT "-> %"
5516           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5517       gst_index_add_association (qtdemux->element_index,
5518           qtdemux->index_id,
5519           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5520           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5521           GST_FORMAT_BYTES, byte_position, NULL);
5522     }
5523   }
5524 #endif
5525
5526   if (stream->need_clip)
5527     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5528
5529   if (G_UNLIKELY (buf == NULL))
5530     goto exit;
5531
5532   if (G_UNLIKELY (stream->discont)) {
5533     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5534     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5535     stream->discont = FALSE;
5536   } else {
5537     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5538   }
5539
5540   if (!keyframe) {
5541     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5542     stream->on_keyframe = FALSE;
5543   } else {
5544     stream->on_keyframe = TRUE;
5545   }
5546
5547
5548   GST_LOG_OBJECT (qtdemux,
5549       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5550       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5551       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5552       GST_PAD_NAME (stream->pad));
5553
5554   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5555     GstStructure *crypto_info;
5556     QtDemuxCencSampleSetInfo *info =
5557         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5558     gint index;
5559     GstEvent *event;
5560
5561     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5562       gst_pad_push_event (stream->pad, event);
5563     }
5564
5565     if (info->crypto_info == NULL) {
5566       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5567       gst_buffer_unref (buf);
5568       goto exit;
5569     }
5570
5571     /* The end of the crypto_info array matches our n_samples position,
5572      * so count backward from there */
5573     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5574     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5575       /* steal structure from array */
5576       crypto_info = g_ptr_array_index (info->crypto_info, index);
5577       g_ptr_array_index (info->crypto_info, index) = NULL;
5578       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5579           info->crypto_info->len);
5580       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5581         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5582     } else {
5583       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5584           index, stream->sample_index);
5585     }
5586   }
5587
5588   if (stream->alignment > 1)
5589     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5590
5591   ret = gst_pad_push (stream->pad, buf);
5592
5593   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5594     /* mark position in stream, we'll need this to know when to send GAP event */
5595     stream->segment.position = pts + duration;
5596   }
5597
5598 exit:
5599   return ret;
5600 }
5601
5602 static const QtDemuxRandomAccessEntry *
5603 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5604     GstClockTime pos, gboolean after)
5605 {
5606   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5607   guint n_entries = stream->n_ra_entries;
5608   guint i;
5609
5610   /* we assume the table is sorted */
5611   for (i = 0; i < n_entries; ++i) {
5612     if (entries[i].ts > pos)
5613       break;
5614   }
5615
5616   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5617    * probably okay to assume that the index lists the very first fragment */
5618   if (i == 0)
5619     return &entries[0];
5620
5621   if (after)
5622     return &entries[i];
5623   else
5624     return &entries[i - 1];
5625 }
5626
5627 static gboolean
5628 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5629 {
5630   const QtDemuxRandomAccessEntry *best_entry = NULL;
5631   guint i;
5632
5633   GST_OBJECT_LOCK (qtdemux);
5634
5635   g_assert (qtdemux->n_streams > 0);
5636
5637   /* first see if we can determine where to go to using mfra,
5638    * before we start clearing things */
5639   for (i = 0; i < qtdemux->n_streams; i++) {
5640     const QtDemuxRandomAccessEntry *entry;
5641     QtDemuxStream *stream;
5642     gboolean is_audio_or_video;
5643
5644     stream = qtdemux->streams[i];
5645
5646     if (stream->ra_entries == NULL)
5647       continue;
5648
5649     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5650       is_audio_or_video = TRUE;
5651     else
5652       is_audio_or_video = FALSE;
5653
5654     entry =
5655         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5656         stream->time_position, !is_audio_or_video);
5657
5658     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5659         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5660
5661     stream->pending_seek = entry;
5662
5663     /* decide position to jump to just based on audio/video tracks, not subs */
5664     if (!is_audio_or_video)
5665       continue;
5666
5667     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5668       best_entry = entry;
5669   }
5670
5671   /* no luck, will handle seek otherwise */
5672   if (best_entry == NULL) {
5673     GST_OBJECT_UNLOCK (qtdemux);
5674     return FALSE;
5675   }
5676
5677   /* ok, now we can prepare for processing as of located moof */
5678   for (i = 0; i < qtdemux->n_streams; i++) {
5679     QtDemuxStream *stream;
5680
5681     stream = qtdemux->streams[i];
5682
5683     g_free (stream->samples);
5684     stream->samples = NULL;
5685     stream->n_samples = 0;
5686     stream->stbl_index = -1;    /* no samples have yet been parsed */
5687     stream->sample_index = -1;
5688
5689     if (stream->protection_scheme_info) {
5690       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5691       if (stream->protection_scheme_type == FOURCC_cenc) {
5692         QtDemuxCencSampleSetInfo *info =
5693             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5694         if (info->crypto_info) {
5695           g_ptr_array_free (info->crypto_info, TRUE);
5696           info->crypto_info = NULL;
5697         }
5698       }
5699     }
5700   }
5701
5702   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5703       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5704       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5705       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5706
5707   qtdemux->moof_offset = best_entry->moof_offset;
5708
5709   qtdemux_add_fragmented_samples (qtdemux);
5710
5711   GST_OBJECT_UNLOCK (qtdemux);
5712   return TRUE;
5713 }
5714
5715 static GstFlowReturn
5716 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5717 {
5718   GstFlowReturn ret = GST_FLOW_OK;
5719   GstBuffer *buf = NULL;
5720   QtDemuxStream *stream;
5721   GstClockTime min_time;
5722   guint64 offset = 0;
5723   GstClockTime dts = GST_CLOCK_TIME_NONE;
5724   GstClockTime pts = GST_CLOCK_TIME_NONE;
5725   GstClockTime duration = 0;
5726   gboolean keyframe = FALSE;
5727   guint sample_size = 0;
5728   gboolean empty = 0;
5729   guint size;
5730   gint index;
5731   gint i;
5732
5733   gst_qtdemux_push_pending_newsegment (qtdemux);
5734
5735   if (qtdemux->fragmented_seek_pending) {
5736     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5737     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
5738       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5739       qtdemux->fragmented_seek_pending = FALSE;
5740     } else {
5741       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
5742     }
5743   }
5744
5745   /* Figure out the next stream sample to output, min_time is expressed in
5746    * global time and runs over the edit list segments. */
5747   min_time = G_MAXUINT64;
5748   index = -1;
5749   for (i = 0; i < qtdemux->n_streams; i++) {
5750     GstClockTime position;
5751
5752     stream = qtdemux->streams[i];
5753     position = stream->time_position;
5754
5755     /* position of -1 is EOS */
5756     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5757       min_time = position;
5758       index = i;
5759     }
5760   }
5761   /* all are EOS */
5762   if (G_UNLIKELY (index == -1)) {
5763     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5764     goto eos;
5765   }
5766
5767   /* check for segment end */
5768   if (G_UNLIKELY (qtdemux->segment.stop != -1
5769           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5770               || (qtdemux->segment.rate < 0
5771                   && qtdemux->segment.start > min_time))
5772           && qtdemux->streams[index]->on_keyframe)) {
5773     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5774     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5775     goto eos_stream;
5776   }
5777
5778   /* gap events for subtitle streams */
5779   for (i = 0; i < qtdemux->n_streams; i++) {
5780     stream = qtdemux->streams[i];
5781     if (stream->pad && (stream->subtype == FOURCC_subp
5782             || stream->subtype == FOURCC_text
5783             || stream->subtype == FOURCC_sbtl)) {
5784       /* send one second gap events until the stream catches up */
5785       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5786       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5787           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5788           stream->segment.position + GST_SECOND < min_time) {
5789         GstEvent *gap =
5790             gst_event_new_gap (stream->segment.position, GST_SECOND);
5791         gst_pad_push_event (stream->pad, gap);
5792         stream->segment.position += GST_SECOND;
5793       }
5794     }
5795   }
5796
5797   stream = qtdemux->streams[index];
5798   /* fetch info for the current sample of this stream */
5799   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5800               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5801     goto eos_stream;
5802
5803   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5804   if (stream->new_caps) {
5805     gst_qtdemux_configure_stream (qtdemux, stream);
5806     qtdemux_do_allocation (qtdemux, stream);
5807   }
5808
5809   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5810   if (G_UNLIKELY (qtdemux->
5811           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5812     if (stream->subtype == FOURCC_vide && !keyframe) {
5813       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5814       goto next;
5815     }
5816   }
5817
5818   GST_DEBUG_OBJECT (qtdemux,
5819       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5820       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5821       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5822       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5823
5824   if (G_UNLIKELY (empty)) {
5825     /* empty segment, push a gap if there's a second or more
5826      * difference and move to the next one */
5827     if ((pts + duration - stream->segment.position) >= GST_SECOND)
5828       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5829     stream->segment.position = pts + duration;
5830     goto next;
5831   }
5832
5833   /* hmm, empty sample, skip and move to next sample */
5834   if (G_UNLIKELY (sample_size <= 0))
5835     goto next;
5836
5837   /* last pushed sample was out of boundary, goto next sample */
5838   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5839     goto next;
5840
5841   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5842     size = sample_size;
5843   } else {
5844     GST_DEBUG_OBJECT (qtdemux,
5845         "size %d larger than stream max_buffer_size %d, trimming",
5846         sample_size, stream->max_buffer_size);
5847     size =
5848         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5849   }
5850
5851   if (qtdemux->cenc_aux_info_offset > 0) {
5852     GstMapInfo map;
5853     GstByteReader br;
5854     GstBuffer *aux_info = NULL;
5855
5856     /* pull the data stored before the sample */
5857     ret =
5858         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5859         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5860     if (G_UNLIKELY (ret != GST_FLOW_OK))
5861       goto beach;
5862     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5863     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5864     gst_byte_reader_init (&br, map.data + 8, map.size);
5865     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5866             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5867       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5868       gst_buffer_unmap (aux_info, &map);
5869       gst_buffer_unref (aux_info);
5870       ret = GST_FLOW_ERROR;
5871       goto beach;
5872     }
5873     gst_buffer_unmap (aux_info, &map);
5874     gst_buffer_unref (aux_info);
5875   }
5876
5877   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5878       offset);
5879
5880   if (stream->use_allocator) {
5881     /* if we have a per-stream allocator, use it */
5882     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5883   }
5884
5885   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5886       size, &buf);
5887   if (G_UNLIKELY (ret != GST_FLOW_OK))
5888     goto beach;
5889
5890   if (size != sample_size) {
5891     pts += gst_util_uint64_scale_int (GST_SECOND,
5892         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5893         stream->timescale);
5894     dts +=
5895         gst_util_uint64_scale_int (GST_SECOND,
5896         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5897         stream->timescale);
5898     duration =
5899         gst_util_uint64_scale_int (GST_SECOND,
5900         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5901   }
5902
5903   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5904       dts, pts, duration, keyframe, min_time, offset);
5905
5906   if (size != sample_size) {
5907     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5908     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5909
5910     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5911         sample->timestamp +
5912         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5913     if (time_position >= segment->media_start) {
5914       /* inside the segment, update time_position, looks very familiar to
5915        * GStreamer segments, doesn't it? */
5916       stream->time_position = (time_position - segment->media_start) +
5917           segment->time;
5918     } else {
5919       /* not yet in segment, time does not yet increment. This means
5920        * that we are still prerolling keyframes to the decoder so it can
5921        * decode the first sample of the segment. */
5922       stream->time_position = segment->time;
5923     }
5924   }
5925
5926   /* combine flows */
5927   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5928   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5929    * we have no more data for the pad to push */
5930   if (ret == GST_FLOW_EOS)
5931     ret = GST_FLOW_OK;
5932
5933   stream->offset_in_sample += size;
5934   if (stream->offset_in_sample >= sample_size) {
5935     gst_qtdemux_advance_sample (qtdemux, stream);
5936   }
5937   goto beach;
5938
5939 next:
5940   gst_qtdemux_advance_sample (qtdemux, stream);
5941
5942 beach:
5943   return ret;
5944
5945   /* special cases */
5946 eos:
5947   {
5948     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5949     ret = GST_FLOW_EOS;
5950     goto beach;
5951   }
5952 eos_stream:
5953   {
5954     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5955     /* EOS will be raised if all are EOS */
5956     ret = GST_FLOW_OK;
5957     goto beach;
5958   }
5959 }
5960
5961 static void
5962 gst_qtdemux_loop (GstPad * pad)
5963 {
5964   GstQTDemux *qtdemux;
5965   guint64 cur_offset;
5966   GstFlowReturn ret;
5967
5968   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5969
5970   cur_offset = qtdemux->offset;
5971   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5972       cur_offset, qt_demux_state_string (qtdemux->state));
5973
5974   switch (qtdemux->state) {
5975     case QTDEMUX_STATE_INITIAL:
5976     case QTDEMUX_STATE_HEADER:
5977       ret = gst_qtdemux_loop_state_header (qtdemux);
5978       break;
5979     case QTDEMUX_STATE_MOVIE:
5980       ret = gst_qtdemux_loop_state_movie (qtdemux);
5981       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5982         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5983       }
5984       break;
5985     default:
5986       /* ouch */
5987       goto invalid_state;
5988   }
5989
5990   /* if something went wrong, pause */
5991   if (ret != GST_FLOW_OK)
5992     goto pause;
5993
5994 done:
5995   gst_object_unref (qtdemux);
5996   return;
5997
5998   /* ERRORS */
5999 invalid_state:
6000   {
6001     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6002         (NULL), ("streaming stopped, invalid state"));
6003     gst_pad_pause_task (pad);
6004     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6005     goto done;
6006   }
6007 pause:
6008   {
6009     const gchar *reason = gst_flow_get_name (ret);
6010
6011     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6012
6013     gst_pad_pause_task (pad);
6014
6015     /* fatal errors need special actions */
6016     /* check EOS */
6017     if (ret == GST_FLOW_EOS) {
6018       if (qtdemux->n_streams == 0) {
6019         /* we have no streams, post an error */
6020         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6021       }
6022       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6023         gint64 stop;
6024
6025         if ((stop = qtdemux->segment.stop) == -1)
6026           stop = qtdemux->segment.duration;
6027
6028         if (qtdemux->segment.rate >= 0) {
6029           GstMessage *message;
6030           GstEvent *event;
6031
6032           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6033           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6034               GST_FORMAT_TIME, stop);
6035           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6036           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6037             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6038             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6039           }
6040           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6041           gst_qtdemux_push_event (qtdemux, event);
6042         } else {
6043           GstMessage *message;
6044           GstEvent *event;
6045
6046           /*  For Reverse Playback */
6047           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6048           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6049               GST_FORMAT_TIME, qtdemux->segment.start);
6050           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6051               qtdemux->segment.start);
6052           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6053             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6054             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6055           }
6056           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6057           gst_qtdemux_push_event (qtdemux, event);
6058         }
6059       } else {
6060         GstEvent *event;
6061
6062         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6063         event = gst_event_new_eos ();
6064         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6065           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6066         gst_qtdemux_push_event (qtdemux, event);
6067       }
6068     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6069       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6070       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6071     }
6072     goto done;
6073   }
6074 }
6075
6076 /*
6077  * has_next_entry
6078  *
6079  * Returns if there are samples to be played.
6080  */
6081 static gboolean
6082 has_next_entry (GstQTDemux * demux)
6083 {
6084   QtDemuxStream *stream;
6085   int i;
6086
6087   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6088
6089   for (i = 0; i < demux->n_streams; i++) {
6090     stream = demux->streams[i];
6091
6092     if (stream->sample_index == -1) {
6093       stream->sample_index = 0;
6094       stream->offset_in_sample = 0;
6095     }
6096
6097     if (stream->sample_index >= stream->n_samples) {
6098       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6099       continue;
6100     }
6101     GST_DEBUG_OBJECT (demux, "Found a sample");
6102     return TRUE;
6103   }
6104
6105   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6106   return FALSE;
6107 }
6108
6109 /*
6110  * next_entry_size
6111  *
6112  * Returns the size of the first entry at the current offset.
6113  * If -1, there are none (which means EOS or empty file).
6114  */
6115 static guint64
6116 next_entry_size (GstQTDemux * demux)
6117 {
6118   QtDemuxStream *stream;
6119   int i;
6120   int smallidx = -1;
6121   guint64 smalloffs = (guint64) - 1;
6122   QtDemuxSample *sample;
6123
6124   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6125       demux->offset);
6126
6127   for (i = 0; i < demux->n_streams; i++) {
6128     stream = demux->streams[i];
6129
6130     if (stream->sample_index == -1) {
6131       stream->sample_index = 0;
6132       stream->offset_in_sample = 0;
6133     }
6134
6135     if (stream->sample_index >= stream->n_samples) {
6136       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6137       continue;
6138     }
6139
6140     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6141       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6142           stream->sample_index);
6143       return -1;
6144     }
6145
6146     sample = &stream->samples[stream->sample_index];
6147
6148     GST_LOG_OBJECT (demux,
6149         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6150         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6151         sample->offset, sample->size);
6152
6153     if (((smalloffs == -1)
6154             || (sample->offset < smalloffs)) && (sample->size)) {
6155       smallidx = i;
6156       smalloffs = sample->offset;
6157     }
6158   }
6159
6160   GST_LOG_OBJECT (demux,
6161       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6162       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6163
6164   if (smallidx == -1)
6165     return -1;
6166
6167   stream = demux->streams[smallidx];
6168   sample = &stream->samples[stream->sample_index];
6169
6170   if (sample->offset >= demux->offset) {
6171     demux->todrop = sample->offset - demux->offset;
6172     return sample->size + demux->todrop;
6173   }
6174
6175   GST_DEBUG_OBJECT (demux,
6176       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6177   return -1;
6178 }
6179
6180 static void
6181 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6182 {
6183   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6184
6185   gst_element_post_message (GST_ELEMENT_CAST (demux),
6186       gst_message_new_element (GST_OBJECT_CAST (demux),
6187           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6188 }
6189
6190 static gboolean
6191 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6192 {
6193   GstEvent *event;
6194   gboolean res = 0;
6195
6196   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6197
6198   event =
6199       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6200       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6201       GST_SEEK_TYPE_NONE, -1);
6202
6203   /* store seqnum to drop flush events, they don't need to reach downstream */
6204   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6205   res = gst_pad_push_event (demux->sinkpad, event);
6206   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6207
6208   return res;
6209 }
6210
6211 /* check for seekable upstream, above and beyond a mere query */
6212 static void
6213 gst_qtdemux_check_seekability (GstQTDemux * demux)
6214 {
6215   GstQuery *query;
6216   gboolean seekable = FALSE;
6217   gint64 start = -1, stop = -1;
6218
6219   if (demux->upstream_size)
6220     return;
6221
6222   if (demux->upstream_format_is_time)
6223     return;
6224
6225   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6226   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6227     GST_DEBUG_OBJECT (demux, "seeking query failed");
6228     goto done;
6229   }
6230
6231   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6232
6233   /* try harder to query upstream size if we didn't get it the first time */
6234   if (seekable && stop == -1) {
6235     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6236     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6237   }
6238
6239   /* if upstream doesn't know the size, it's likely that it's not seekable in
6240    * practice even if it technically may be seekable */
6241   if (seekable && (start != 0 || stop <= start)) {
6242     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6243     seekable = FALSE;
6244   }
6245
6246 done:
6247   gst_query_unref (query);
6248
6249   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6250       G_GUINT64_FORMAT ")", seekable, start, stop);
6251   demux->upstream_seekable = seekable;
6252   demux->upstream_size = seekable ? stop : -1;
6253 }
6254
6255 static void
6256 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6257 {
6258   g_return_if_fail (bytes <= demux->todrop);
6259
6260   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6261   gst_adapter_flush (demux->adapter, bytes);
6262   demux->neededbytes -= bytes;
6263   demux->offset += bytes;
6264   demux->todrop -= bytes;
6265 }
6266
6267 static void
6268 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6269 {
6270   if (G_UNLIKELY (demux->pending_newsegment)) {
6271     gint i;
6272
6273     gst_qtdemux_push_pending_newsegment (demux);
6274     /* clear to send tags on all streams */
6275     for (i = 0; i < demux->n_streams; i++) {
6276       QtDemuxStream *stream;
6277       stream = demux->streams[i];
6278       gst_qtdemux_push_tags (demux, stream);
6279       if (CUR_STREAM (stream)->sparse) {
6280         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6281         gst_pad_push_event (stream->pad,
6282             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6283       }
6284     }
6285   }
6286 }
6287
6288 static void
6289 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6290     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6291 {
6292   GstClockTime ts, dur;
6293   GstEvent *gap;
6294
6295   ts = pos;
6296   dur =
6297       stream->segments[segment_index].duration - (pos -
6298       stream->segments[segment_index].time);
6299   gap = gst_event_new_gap (ts, dur);
6300   stream->time_position += dur;
6301
6302   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6303       "segment: %" GST_PTR_FORMAT, gap);
6304   gst_pad_push_event (stream->pad, gap);
6305 }
6306
6307 static void
6308 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6309     QtDemuxStream * stream)
6310 {
6311   gint i;
6312
6313   /* Push any initial gap segments before proceeding to the
6314    * 'real' data */
6315   for (i = 0; i < stream->n_segments; i++) {
6316     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6317
6318     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6319       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6320           stream->time_position);
6321     } else {
6322       /* Only support empty segment at the beginning followed by
6323        * one non-empty segment, this was checked when parsing the
6324        * edts atom, arriving here is unexpected */
6325       g_assert (i + 1 == stream->n_segments);
6326       break;
6327     }
6328   }
6329 }
6330
6331 static GstFlowReturn
6332 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6333 {
6334   GstQTDemux *demux;
6335
6336   demux = GST_QTDEMUX (parent);
6337
6338   GST_DEBUG_OBJECT (demux,
6339       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6340       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6341       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6342       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6343       gst_buffer_get_size (inbuf), demux->offset);
6344
6345   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6346     gboolean is_gap_input = FALSE;
6347     gint i;
6348
6349     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6350
6351     for (i = 0; i < demux->n_streams; i++) {
6352       demux->streams[i]->discont = TRUE;
6353     }
6354
6355     /* Check if we can land back on our feet in the case where upstream is
6356      * handling the seeking/pushing of samples with gaps in between (like
6357      * in the case of trick-mode DASH for example) */
6358     if (demux->upstream_format_is_time
6359         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6360       gint i;
6361       for (i = 0; i < demux->n_streams; i++) {
6362         guint32 res;
6363         GST_LOG_OBJECT (demux,
6364             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6365             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6366         res =
6367             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6368             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6369         if (res != -1) {
6370           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6371           GST_LOG_OBJECT (demux,
6372               "Checking if sample %d from stream %d is valid (offset:%"
6373               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6374               sample->offset, sample->size);
6375           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6376             GST_LOG_OBJECT (demux,
6377                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6378                 res);
6379             is_gap_input = TRUE;
6380             /* We can go back to standard playback mode */
6381             demux->state = QTDEMUX_STATE_MOVIE;
6382             /* Remember which sample this stream is at */
6383             demux->streams[i]->sample_index = res;
6384             /* Finally update all push-based values to the expected values */
6385             demux->neededbytes = demux->streams[i]->samples[res].size;
6386             demux->offset = GST_BUFFER_OFFSET (inbuf);
6387             demux->mdatleft =
6388                 demux->mdatsize - demux->offset + demux->mdatoffset;
6389             demux->todrop = 0;
6390           }
6391         }
6392       }
6393       if (!is_gap_input) {
6394         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6395         /* Reset state if it's a real discont */
6396         demux->neededbytes = 16;
6397         demux->state = QTDEMUX_STATE_INITIAL;
6398         demux->offset = GST_BUFFER_OFFSET (inbuf);
6399         gst_adapter_clear (demux->adapter);
6400       }
6401     }
6402     /* Reverse fragmented playback, need to flush all we have before
6403      * consuming a new fragment.
6404      * The samples array have the timestamps calculated by accumulating the
6405      * durations but this won't work for reverse playback of fragments as
6406      * the timestamps of a subsequent fragment should be smaller than the
6407      * previously received one. */
6408     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6409       gst_qtdemux_process_adapter (demux, TRUE);
6410       for (i = 0; i < demux->n_streams; i++)
6411         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6412     }
6413   }
6414
6415   gst_adapter_push (demux->adapter, inbuf);
6416
6417   GST_DEBUG_OBJECT (demux,
6418       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6419       demux->neededbytes, gst_adapter_available (demux->adapter));
6420
6421   return gst_qtdemux_process_adapter (demux, FALSE);
6422 }
6423
6424 static GstFlowReturn
6425 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6426 {
6427   GstFlowReturn ret = GST_FLOW_OK;
6428
6429   /* we never really mean to buffer that much */
6430   if (demux->neededbytes == -1) {
6431     goto eos;
6432   }
6433
6434   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6435       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6436
6437 #ifndef GST_DISABLE_GST_DEBUG
6438     {
6439       guint64 discont_offset, distance_from_discont;
6440
6441       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6442       distance_from_discont =
6443           gst_adapter_distance_from_discont (demux->adapter);
6444
6445       GST_DEBUG_OBJECT (demux,
6446           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6447           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6448           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6449           demux->offset, discont_offset, distance_from_discont);
6450     }
6451 #endif
6452
6453     switch (demux->state) {
6454       case QTDEMUX_STATE_INITIAL:{
6455         const guint8 *data;
6456         guint32 fourcc;
6457         guint64 size;
6458
6459         gst_qtdemux_check_seekability (demux);
6460
6461         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6462
6463         /* get fourcc/length, set neededbytes */
6464         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6465             &size, &fourcc);
6466         gst_adapter_unmap (demux->adapter);
6467         data = NULL;
6468         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6469             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6470         if (size == 0) {
6471           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6472               (_("This file is invalid and cannot be played.")),
6473               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6474                   GST_FOURCC_ARGS (fourcc)));
6475           ret = GST_FLOW_ERROR;
6476           break;
6477         }
6478         if (fourcc == FOURCC_mdat) {
6479           gint next_entry = next_entry_size (demux);
6480           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6481             /* we have the headers, start playback */
6482             demux->state = QTDEMUX_STATE_MOVIE;
6483             demux->neededbytes = next_entry;
6484             demux->mdatleft = size;
6485             demux->mdatsize = demux->mdatleft;
6486           } else {
6487             /* no headers yet, try to get them */
6488             guint bs;
6489             gboolean res;
6490             guint64 old, target;
6491
6492           buffer_data:
6493             old = demux->offset;
6494             target = old + size;
6495
6496             /* try to jump over the atom with a seek */
6497             /* only bother if it seems worth doing so,
6498              * and avoids possible upstream/server problems */
6499             if (demux->upstream_seekable &&
6500                 demux->upstream_size > 4 * (1 << 20)) {
6501               res = qtdemux_seek_offset (demux, target);
6502             } else {
6503               GST_DEBUG_OBJECT (demux, "skipping seek");
6504               res = FALSE;
6505             }
6506
6507             if (res) {
6508               GST_DEBUG_OBJECT (demux, "seek success");
6509               /* remember the offset fo the first mdat so we can seek back to it
6510                * after we have the headers */
6511               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6512                 demux->first_mdat = old;
6513                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6514                     demux->first_mdat);
6515               }
6516               /* seek worked, continue reading */
6517               demux->offset = target;
6518               demux->neededbytes = 16;
6519               demux->state = QTDEMUX_STATE_INITIAL;
6520             } else {
6521               /* seek failed, need to buffer */
6522               demux->offset = old;
6523               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6524               /* there may be multiple mdat (or alike) buffers */
6525               /* sanity check */
6526               if (demux->mdatbuffer)
6527                 bs = gst_buffer_get_size (demux->mdatbuffer);
6528               else
6529                 bs = 0;
6530               if (size + bs > 10 * (1 << 20))
6531                 goto no_moov;
6532               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6533               demux->neededbytes = size;
6534               if (!demux->mdatbuffer)
6535                 demux->mdatoffset = demux->offset;
6536             }
6537           }
6538         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6539           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6540               (_("This file is invalid and cannot be played.")),
6541               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6542                   GST_FOURCC_ARGS (fourcc), size));
6543           ret = GST_FLOW_ERROR;
6544           break;
6545         } else {
6546           /* this means we already started buffering and still no moov header,
6547            * let's continue buffering everything till we get moov */
6548           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6549                   || fourcc == FOURCC_moof))
6550             goto buffer_data;
6551           demux->neededbytes = size;
6552           demux->state = QTDEMUX_STATE_HEADER;
6553         }
6554         break;
6555       }
6556       case QTDEMUX_STATE_HEADER:{
6557         const guint8 *data;
6558         guint32 fourcc;
6559
6560         GST_DEBUG_OBJECT (demux, "In header");
6561
6562         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6563
6564         /* parse the header */
6565         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6566             &fourcc);
6567         if (fourcc == FOURCC_moov) {
6568           gint n;
6569
6570           /* in usual fragmented setup we could try to scan for more
6571            * and end up at the the moov (after mdat) again */
6572           if (demux->got_moov && demux->n_streams > 0 &&
6573               (!demux->fragmented
6574                   || demux->last_moov_offset == demux->offset)) {
6575             GST_DEBUG_OBJECT (demux,
6576                 "Skipping moov atom as we have (this) one already");
6577           } else {
6578             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6579
6580             if (demux->got_moov && demux->fragmented) {
6581               GST_DEBUG_OBJECT (demux,
6582                   "Got a second moov, clean up data from old one");
6583               if (demux->moov_node_compressed) {
6584                 g_node_destroy (demux->moov_node_compressed);
6585                 if (demux->moov_node)
6586                   g_free (demux->moov_node->data);
6587               }
6588               demux->moov_node_compressed = NULL;
6589               if (demux->moov_node)
6590                 g_node_destroy (demux->moov_node);
6591               demux->moov_node = NULL;
6592             } else {
6593               /* prepare newsegment to send when streaming actually starts */
6594               if (!demux->pending_newsegment) {
6595                 demux->pending_newsegment =
6596                     gst_event_new_segment (&demux->segment);
6597                 if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6598                   gst_event_set_seqnum (demux->pending_newsegment,
6599                       demux->segment_seqnum);
6600               }
6601             }
6602
6603             demux->last_moov_offset = demux->offset;
6604
6605             qtdemux_parse_moov (demux, data, demux->neededbytes);
6606             qtdemux_node_dump (demux, demux->moov_node);
6607             qtdemux_parse_tree (demux);
6608             qtdemux_prepare_streams (demux);
6609             if (!demux->got_moov)
6610               qtdemux_expose_streams (demux);
6611             else {
6612
6613               for (n = 0; n < demux->n_streams; n++) {
6614                 QtDemuxStream *stream = demux->streams[n];
6615
6616                 gst_qtdemux_configure_stream (demux, stream);
6617               }
6618             }
6619
6620             demux->got_moov = TRUE;
6621             gst_qtdemux_check_send_pending_segment (demux);
6622
6623             /* fragmented streams headers shouldn't contain edts atoms */
6624             if (!demux->fragmented) {
6625               for (n = 0; n < demux->n_streams; n++) {
6626                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6627                     demux->streams[n]);
6628               }
6629             }
6630
6631             if (demux->moov_node_compressed) {
6632               g_node_destroy (demux->moov_node_compressed);
6633               g_free (demux->moov_node->data);
6634             }
6635             demux->moov_node_compressed = NULL;
6636             g_node_destroy (demux->moov_node);
6637             demux->moov_node = NULL;
6638             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6639           }
6640         } else if (fourcc == FOURCC_moof) {
6641           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6642             guint64 dist = 0;
6643             GstClockTime prev_pts;
6644             guint64 prev_offset;
6645             guint64 adapter_discont_offset, adapter_discont_dist;
6646
6647             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6648
6649             /*
6650              * The timestamp of the moof buffer is relevant as some scenarios
6651              * won't have the initial timestamp in the atoms. Whenever a new
6652              * buffer has started, we get that buffer's PTS and use it as a base
6653              * timestamp for the trun entries.
6654              *
6655              * To keep track of the current buffer timestamp and starting point
6656              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6657              * from the beggining of the buffer, with the distance and demux->offset
6658              * we know if it is still the same buffer or not.
6659              */
6660             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6661             prev_offset = demux->offset - dist;
6662             if (demux->fragment_start_offset == -1
6663                 || prev_offset > demux->fragment_start_offset) {
6664               demux->fragment_start_offset = prev_offset;
6665               demux->fragment_start = prev_pts;
6666               GST_DEBUG_OBJECT (demux,
6667                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6668                   GST_TIME_FORMAT, demux->fragment_start_offset,
6669                   GST_TIME_ARGS (demux->fragment_start));
6670             }
6671
6672             /* We can't use prev_offset() here because this would require
6673              * upstream to set consistent and correct offsets on all buffers
6674              * since the discont. Nothing ever did that in the past and we
6675              * would break backwards compatibility here then.
6676              * Instead take the offset we had at the last discont and count
6677              * the bytes from there. This works with old code as there would
6678              * be no discont between moov and moof, and also works with
6679              * adaptivedemux which correctly sets offset and will set the
6680              * DISCONT flag accordingly when needed.
6681              *
6682              * We also only do this for upstream TIME segments as otherwise
6683              * there are potential backwards compatibility problems with
6684              * seeking in PUSH mode and upstream providing inconsistent
6685              * timestamps. */
6686             adapter_discont_offset =
6687                 gst_adapter_offset_at_discont (demux->adapter);
6688             adapter_discont_dist =
6689                 gst_adapter_distance_from_discont (demux->adapter);
6690
6691             GST_DEBUG_OBJECT (demux,
6692                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6693                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6694                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6695
6696             if (demux->upstream_format_is_time) {
6697               demux->moof_offset = adapter_discont_offset;
6698               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6699                 demux->moof_offset += adapter_discont_dist;
6700               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6701                 demux->moof_offset = demux->offset;
6702             } else {
6703               demux->moof_offset = demux->offset;
6704             }
6705
6706             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6707                     demux->moof_offset, NULL)) {
6708               gst_adapter_unmap (demux->adapter);
6709               ret = GST_FLOW_ERROR;
6710               goto done;
6711             }
6712             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6713             if (demux->mss_mode && !demux->exposed) {
6714               if (!demux->pending_newsegment) {
6715                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6716                 demux->pending_newsegment =
6717                     gst_event_new_segment (&demux->segment);
6718                 if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6719                   gst_event_set_seqnum (demux->pending_newsegment,
6720                       demux->segment_seqnum);
6721               }
6722               qtdemux_expose_streams (demux);
6723             }
6724           } else {
6725             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6726           }
6727         } else if (fourcc == FOURCC_ftyp) {
6728           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6729           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6730         } else if (fourcc == FOURCC_uuid) {
6731           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6732           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6733         } else if (fourcc == FOURCC_sidx) {
6734           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6735           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6736         } else {
6737           switch (fourcc) {
6738             case FOURCC_styp:
6739               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6740                * FALLTHROUGH */
6741             case FOURCC_skip:
6742             case FOURCC_free:
6743               /* [free] and [skip] are padding atoms */
6744               GST_DEBUG_OBJECT (demux,
6745                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6746                   GST_FOURCC_ARGS (fourcc));
6747               break;
6748             default:
6749               GST_WARNING_OBJECT (demux,
6750                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6751                   GST_FOURCC_ARGS (fourcc));
6752               /* Let's jump that one and go back to initial state */
6753               break;
6754           }
6755         }
6756         gst_adapter_unmap (demux->adapter);
6757         data = NULL;
6758
6759         if (demux->mdatbuffer && demux->n_streams) {
6760           gsize remaining_data_size = 0;
6761
6762           /* the mdat was before the header */
6763           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6764               demux->n_streams, demux->mdatbuffer);
6765           /* restore our adapter/offset view of things with upstream;
6766            * put preceding buffered data ahead of current moov data.
6767            * This should also handle evil mdat, moov, mdat cases and alike */
6768           gst_adapter_flush (demux->adapter, demux->neededbytes);
6769
6770           /* Store any remaining data after the mdat for later usage */
6771           remaining_data_size = gst_adapter_available (demux->adapter);
6772           if (remaining_data_size > 0) {
6773             g_assert (demux->restoredata_buffer == NULL);
6774             demux->restoredata_buffer =
6775                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6776             demux->restoredata_offset = demux->offset + demux->neededbytes;
6777             GST_DEBUG_OBJECT (demux,
6778                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6779                 G_GUINT64_FORMAT, remaining_data_size,
6780                 demux->restoredata_offset);
6781           }
6782
6783           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6784           demux->mdatbuffer = NULL;
6785           demux->offset = demux->mdatoffset;
6786           demux->neededbytes = next_entry_size (demux);
6787           demux->state = QTDEMUX_STATE_MOVIE;
6788           demux->mdatleft = gst_adapter_available (demux->adapter);
6789           demux->mdatsize = demux->mdatleft;
6790         } else {
6791           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6792           gst_adapter_flush (demux->adapter, demux->neededbytes);
6793
6794           /* only go back to the mdat if there are samples to play */
6795           if (demux->got_moov && demux->first_mdat != -1
6796               && has_next_entry (demux)) {
6797             gboolean res;
6798
6799             /* we need to seek back */
6800             res = qtdemux_seek_offset (demux, demux->first_mdat);
6801             if (res) {
6802               demux->offset = demux->first_mdat;
6803             } else {
6804               GST_DEBUG_OBJECT (demux, "Seek back failed");
6805             }
6806           } else {
6807             demux->offset += demux->neededbytes;
6808           }
6809           demux->neededbytes = 16;
6810           demux->state = QTDEMUX_STATE_INITIAL;
6811         }
6812
6813         break;
6814       }
6815       case QTDEMUX_STATE_BUFFER_MDAT:{
6816         GstBuffer *buf;
6817         guint8 fourcc[4];
6818
6819         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6820             demux->offset);
6821         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6822         gst_buffer_extract (buf, 0, fourcc, 4);
6823         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6824             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6825         if (demux->mdatbuffer)
6826           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6827         else
6828           demux->mdatbuffer = buf;
6829         demux->offset += demux->neededbytes;
6830         demux->neededbytes = 16;
6831         demux->state = QTDEMUX_STATE_INITIAL;
6832         gst_qtdemux_post_progress (demux, 1, 1);
6833
6834         break;
6835       }
6836       case QTDEMUX_STATE_MOVIE:{
6837         QtDemuxStream *stream = NULL;
6838         QtDemuxSample *sample;
6839         int i = -1;
6840         GstClockTime dts, pts, duration;
6841         gboolean keyframe;
6842
6843         GST_DEBUG_OBJECT (demux,
6844             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6845
6846         if (demux->fragmented) {
6847           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6848               demux->mdatleft);
6849           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6850             /* if needed data starts within this atom,
6851              * then it should not exceed this atom */
6852             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6853               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6854                   (_("This file is invalid and cannot be played.")),
6855                   ("sample data crosses atom boundary"));
6856               ret = GST_FLOW_ERROR;
6857               break;
6858             }
6859             demux->mdatleft -= demux->neededbytes;
6860           } else {
6861             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6862             /* so we are dropping more than left in this atom */
6863             gst_qtdemux_drop_data (demux, demux->mdatleft);
6864             demux->mdatleft = 0;
6865
6866             /* need to resume atom parsing so we do not miss any other pieces */
6867             demux->state = QTDEMUX_STATE_INITIAL;
6868             demux->neededbytes = 16;
6869
6870             /* check if there was any stored post mdat data from previous buffers */
6871             if (demux->restoredata_buffer) {
6872               g_assert (gst_adapter_available (demux->adapter) == 0);
6873
6874               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6875               demux->restoredata_buffer = NULL;
6876               demux->offset = demux->restoredata_offset;
6877             }
6878
6879             break;
6880           }
6881         }
6882
6883         if (demux->todrop) {
6884           if (demux->cenc_aux_info_offset > 0) {
6885             GstByteReader br;
6886             const guint8 *data;
6887
6888             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6889             data = gst_adapter_map (demux->adapter, demux->todrop);
6890             gst_byte_reader_init (&br, data + 8, demux->todrop);
6891             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6892                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6893               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6894               ret = GST_FLOW_ERROR;
6895               gst_adapter_unmap (demux->adapter);
6896               g_free (demux->cenc_aux_info_sizes);
6897               demux->cenc_aux_info_sizes = NULL;
6898               goto done;
6899             }
6900             demux->cenc_aux_info_offset = 0;
6901             g_free (demux->cenc_aux_info_sizes);
6902             demux->cenc_aux_info_sizes = NULL;
6903             gst_adapter_unmap (demux->adapter);
6904           }
6905           gst_qtdemux_drop_data (demux, demux->todrop);
6906         }
6907
6908         /* first buffer? */
6909         /* initial newsegment sent here after having added pads,
6910          * possible others in sink_event */
6911         gst_qtdemux_check_send_pending_segment (demux);
6912
6913         /* Figure out which stream this packet belongs to */
6914         for (i = 0; i < demux->n_streams; i++) {
6915           stream = demux->streams[i];
6916           if (stream->sample_index >= stream->n_samples)
6917             continue;
6918           GST_LOG_OBJECT (demux,
6919               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6920               " / size:%d)", i, stream->sample_index,
6921               stream->samples[stream->sample_index].offset,
6922               stream->samples[stream->sample_index].size);
6923
6924           if (stream->samples[stream->sample_index].offset == demux->offset)
6925             break;
6926         }
6927
6928         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6929           goto unknown_stream;
6930
6931         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6932
6933         if (stream->new_caps) {
6934           gst_qtdemux_configure_stream (demux, stream);
6935         }
6936
6937         /* Put data in a buffer, set timestamps, caps, ... */
6938         sample = &stream->samples[stream->sample_index];
6939
6940         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6941           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6942               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6943
6944           dts = QTSAMPLE_DTS (stream, sample);
6945           pts = QTSAMPLE_PTS (stream, sample);
6946           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6947           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6948
6949           /* check for segment end */
6950           if (G_UNLIKELY (demux->segment.stop != -1
6951                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6952             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6953             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6954
6955             /* skip this data, stream is EOS */
6956             gst_adapter_flush (demux->adapter, demux->neededbytes);
6957             demux->offset += demux->neededbytes;
6958
6959             /* check if all streams are eos */
6960             ret = GST_FLOW_EOS;
6961             for (i = 0; i < demux->n_streams; i++) {
6962               if (!STREAM_IS_EOS (demux->streams[i])) {
6963                 ret = GST_FLOW_OK;
6964                 break;
6965               }
6966             }
6967           } else {
6968             GstBuffer *outbuf;
6969
6970             outbuf =
6971                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6972
6973             /* FIXME: should either be an assert or a plain check */
6974             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6975
6976             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6977                 dts, pts, duration, keyframe, dts, demux->offset);
6978           }
6979
6980           /* combine flows */
6981           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6982         } else {
6983           /* skip this data, stream is EOS */
6984           gst_adapter_flush (demux->adapter, demux->neededbytes);
6985         }
6986
6987         stream->sample_index++;
6988         stream->offset_in_sample = 0;
6989
6990         /* update current offset and figure out size of next buffer */
6991         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6992             demux->offset, demux->neededbytes);
6993         demux->offset += demux->neededbytes;
6994         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6995             demux->offset);
6996
6997
6998         if (ret == GST_FLOW_EOS) {
6999           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7000           demux->neededbytes = -1;
7001           goto eos;
7002         }
7003
7004         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7005           if (demux->fragmented) {
7006             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7007             /* there may be more to follow, only finish this atom */
7008             demux->todrop = demux->mdatleft;
7009             demux->neededbytes = demux->todrop;
7010             break;
7011           }
7012           goto eos;
7013         }
7014         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7015           goto non_ok_unlinked_flow;
7016         }
7017         break;
7018       }
7019       default:
7020         goto invalid_state;
7021     }
7022   }
7023
7024   /* when buffering movie data, at least show user something is happening */
7025   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7026       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7027     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7028         demux->neededbytes);
7029   }
7030 done:
7031
7032   return ret;
7033
7034   /* ERRORS */
7035 non_ok_unlinked_flow:
7036   {
7037     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7038         gst_flow_get_name (ret));
7039     return ret;
7040   }
7041 unknown_stream:
7042   {
7043     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7044     ret = GST_FLOW_ERROR;
7045     goto done;
7046   }
7047 eos:
7048   {
7049     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7050     ret = GST_FLOW_EOS;
7051     goto done;
7052   }
7053 invalid_state:
7054   {
7055     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7056         (NULL), ("qtdemuxer invalid state %d", demux->state));
7057     ret = GST_FLOW_ERROR;
7058     goto done;
7059   }
7060 no_moov:
7061   {
7062     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7063         (NULL), ("no 'moov' atom within the first 10 MB"));
7064     ret = GST_FLOW_ERROR;
7065     goto done;
7066   }
7067 }
7068
7069 static gboolean
7070 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7071 {
7072   GstQuery *query;
7073   gboolean pull_mode;
7074
7075   query = gst_query_new_scheduling ();
7076
7077   if (!gst_pad_peer_query (sinkpad, query)) {
7078     gst_query_unref (query);
7079     goto activate_push;
7080   }
7081
7082   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7083       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7084   gst_query_unref (query);
7085
7086   if (!pull_mode)
7087     goto activate_push;
7088
7089   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7090   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7091
7092 activate_push:
7093   {
7094     GST_DEBUG_OBJECT (sinkpad, "activating push");
7095     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7096   }
7097 }
7098
7099 static gboolean
7100 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7101     GstPadMode mode, gboolean active)
7102 {
7103   gboolean res;
7104   GstQTDemux *demux = GST_QTDEMUX (parent);
7105
7106   switch (mode) {
7107     case GST_PAD_MODE_PUSH:
7108       demux->pullbased = FALSE;
7109       res = TRUE;
7110       break;
7111     case GST_PAD_MODE_PULL:
7112       if (active) {
7113         demux->pullbased = TRUE;
7114         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7115             sinkpad, NULL);
7116       } else {
7117         res = gst_pad_stop_task (sinkpad);
7118       }
7119       break;
7120     default:
7121       res = FALSE;
7122       break;
7123   }
7124   return res;
7125 }
7126
7127 #ifdef HAVE_ZLIB
7128 static void *
7129 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7130 {
7131   guint8 *buffer;
7132   z_stream z;
7133   int ret;
7134
7135   memset (&z, 0, sizeof (z));
7136   z.zalloc = NULL;
7137   z.zfree = NULL;
7138   z.opaque = NULL;
7139
7140   if ((ret = inflateInit (&z)) != Z_OK) {
7141     GST_ERROR ("inflateInit() returned %d", ret);
7142     return NULL;
7143   }
7144
7145   z.next_in = z_buffer;
7146   z.avail_in = z_length;
7147
7148   buffer = (guint8 *) g_malloc (*length);
7149   z.avail_out = *length;
7150   z.next_out = (Bytef *) buffer;
7151   do {
7152     ret = inflate (&z, Z_NO_FLUSH);
7153     if (ret == Z_STREAM_END) {
7154       break;
7155     } else if (ret != Z_OK) {
7156       GST_WARNING ("inflate() returned %d", ret);
7157       break;
7158     }
7159
7160     *length += 4096;
7161     buffer = (guint8 *) g_realloc (buffer, *length);
7162     z.next_out = (Bytef *) (buffer + z.total_out);
7163     z.avail_out += 4096;
7164   } while (z.avail_in > 0);
7165
7166   if (ret != Z_STREAM_END) {
7167     g_free (buffer);
7168     buffer = NULL;
7169     *length = 0;
7170   } else {
7171     *length = z.total_out;
7172   }
7173
7174   inflateEnd (&z);
7175
7176   return buffer;
7177 }
7178 #endif /* HAVE_ZLIB */
7179
7180 static gboolean
7181 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7182 {
7183   GNode *cmov;
7184
7185   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7186
7187   /* counts as header data */
7188   qtdemux->header_size += length;
7189
7190   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7191   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7192
7193   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7194   if (cmov) {
7195     guint32 method;
7196     GNode *dcom;
7197     GNode *cmvd;
7198     guint32 dcom_len;
7199
7200     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7201     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7202     if (dcom == NULL || cmvd == NULL)
7203       goto invalid_compression;
7204
7205     dcom_len = QT_UINT32 (dcom->data);
7206     if (dcom_len < 12)
7207       goto invalid_compression;
7208
7209     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7210     switch (method) {
7211 #ifdef HAVE_ZLIB
7212       case FOURCC_zlib:{
7213         guint uncompressed_length;
7214         guint compressed_length;
7215         guint8 *buf;
7216         guint32 cmvd_len;
7217
7218         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7219         if (cmvd_len < 12)
7220           goto invalid_compression;
7221
7222         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7223         compressed_length = cmvd_len - 12;
7224         GST_LOG ("length = %u", uncompressed_length);
7225
7226         buf =
7227             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7228             compressed_length, &uncompressed_length);
7229
7230         if (buf) {
7231           qtdemux->moov_node_compressed = qtdemux->moov_node;
7232           qtdemux->moov_node = g_node_new (buf);
7233
7234           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7235               uncompressed_length);
7236         }
7237         break;
7238       }
7239 #endif /* HAVE_ZLIB */
7240       default:
7241         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7242             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7243         break;
7244     }
7245   }
7246   return TRUE;
7247
7248   /* ERRORS */
7249 invalid_compression:
7250   {
7251     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7252     return FALSE;
7253   }
7254 }
7255
7256 static gboolean
7257 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7258     const guint8 * end)
7259 {
7260   while (G_UNLIKELY (buf < end)) {
7261     GNode *child;
7262     guint32 len;
7263
7264     if (G_UNLIKELY (buf + 4 > end)) {
7265       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7266       break;
7267     }
7268     len = QT_UINT32 (buf);
7269     if (G_UNLIKELY (len == 0)) {
7270       GST_LOG_OBJECT (qtdemux, "empty container");
7271       break;
7272     }
7273     if (G_UNLIKELY (len < 8)) {
7274       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7275       break;
7276     }
7277     if (G_UNLIKELY (len > (end - buf))) {
7278       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7279           (gint) (end - buf));
7280       break;
7281     }
7282
7283     child = g_node_new ((guint8 *) buf);
7284     g_node_append (node, child);
7285     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7286     qtdemux_parse_node (qtdemux, child, buf, len);
7287
7288     buf += len;
7289   }
7290   return TRUE;
7291 }
7292
7293 static gboolean
7294 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7295     GNode * xdxt)
7296 {
7297   int len = QT_UINT32 (xdxt->data);
7298   guint8 *buf = xdxt->data;
7299   guint8 *end = buf + len;
7300   GstBuffer *buffer;
7301
7302   /* skip size and type */
7303   buf += 8;
7304   end -= 8;
7305
7306   while (buf < end) {
7307     gint size;
7308     guint32 type;
7309
7310     size = QT_UINT32 (buf);
7311     type = QT_FOURCC (buf + 4);
7312
7313     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7314
7315     if (buf + size > end || size <= 0)
7316       break;
7317
7318     buf += 8;
7319     size -= 8;
7320
7321     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7322         GST_FOURCC_ARGS (type));
7323
7324     switch (type) {
7325       case FOURCC_tCtH:
7326         buffer = gst_buffer_new_and_alloc (size);
7327         gst_buffer_fill (buffer, 0, buf, size);
7328         stream->buffers = g_slist_append (stream->buffers, buffer);
7329         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7330         break;
7331       case FOURCC_tCt_:
7332         buffer = gst_buffer_new_and_alloc (size);
7333         gst_buffer_fill (buffer, 0, buf, size);
7334         stream->buffers = g_slist_append (stream->buffers, buffer);
7335         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7336         break;
7337       case FOURCC_tCtC:
7338         buffer = gst_buffer_new_and_alloc (size);
7339         gst_buffer_fill (buffer, 0, buf, size);
7340         stream->buffers = g_slist_append (stream->buffers, buffer);
7341         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7342         break;
7343       default:
7344         GST_WARNING_OBJECT (qtdemux,
7345             "unknown theora cookie %" GST_FOURCC_FORMAT,
7346             GST_FOURCC_ARGS (type));
7347         break;
7348     }
7349     buf += size;
7350   }
7351   return TRUE;
7352 }
7353
7354 static gboolean
7355 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7356     guint length)
7357 {
7358   guint32 fourcc = 0;
7359   guint32 node_length = 0;
7360   const QtNodeType *type;
7361   const guint8 *end;
7362
7363   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7364
7365   if (G_UNLIKELY (length < 8))
7366     goto not_enough_data;
7367
7368   node_length = QT_UINT32 (buffer);
7369   fourcc = QT_FOURCC (buffer + 4);
7370
7371   /* ignore empty nodes */
7372   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7373     return TRUE;
7374
7375   type = qtdemux_type_get (fourcc);
7376
7377   end = buffer + length;
7378
7379   GST_LOG_OBJECT (qtdemux,
7380       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7381       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7382
7383   if (node_length > length)
7384     goto broken_atom_size;
7385
7386   if (type->flags & QT_FLAG_CONTAINER) {
7387     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7388   } else {
7389     switch (fourcc) {
7390       case FOURCC_stsd:
7391       {
7392         if (node_length < 20) {
7393           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7394           break;
7395         }
7396         GST_DEBUG_OBJECT (qtdemux,
7397             "parsing stsd (sample table, sample description) atom");
7398         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7399         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7400         break;
7401       }
7402       case FOURCC_mp4a:
7403       case FOURCC_alac:
7404       case FOURCC_fLaC:
7405       {
7406         guint32 version;
7407         guint32 offset;
7408         guint min_size;
7409
7410         /* also read alac (or whatever) in stead of mp4a in the following,
7411          * since a similar layout is used in other cases as well */
7412         if (fourcc == FOURCC_mp4a)
7413           min_size = 20;
7414         else if (fourcc == FOURCC_fLaC)
7415           min_size = 86;
7416         else
7417           min_size = 40;
7418
7419         /* There are two things we might encounter here: a true mp4a atom, and
7420            an mp4a entry in an stsd atom. The latter is what we're interested
7421            in, and it looks like an atom, but isn't really one. The true mp4a
7422            atom is short, so we detect it based on length here. */
7423         if (length < min_size) {
7424           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7425               GST_FOURCC_ARGS (fourcc));
7426           break;
7427         }
7428
7429         /* 'version' here is the sound sample description version. Types 0 and
7430            1 are documented in the QTFF reference, but type 2 is not: it's
7431            described in Apple header files instead (struct SoundDescriptionV2
7432            in Movies.h) */
7433         version = QT_UINT16 (buffer + 16);
7434
7435         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7436             GST_FOURCC_ARGS (fourcc), version);
7437
7438         /* parse any esds descriptors */
7439         switch (version) {
7440           case 0:
7441             offset = 0x24;
7442             break;
7443           case 1:
7444             offset = 0x34;
7445             break;
7446           case 2:
7447             offset = 0x48;
7448             break;
7449           default:
7450             GST_WARNING_OBJECT (qtdemux,
7451                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7452                 GST_FOURCC_ARGS (fourcc), version);
7453             offset = 0;
7454             break;
7455         }
7456         if (offset)
7457           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7458         break;
7459       }
7460       case FOURCC_mp4v:
7461       case FOURCC_MP4V:
7462       case FOURCC_fmp4:
7463       case FOURCC_FMP4:
7464       case FOURCC_apcs:
7465       case FOURCC_apch:
7466       case FOURCC_apcn:
7467       case FOURCC_apco:
7468       case FOURCC_ap4h:
7469       case FOURCC_xvid:
7470       case FOURCC_XVID:
7471       case FOURCC_H264:
7472       case FOURCC_avc1:
7473       case FOURCC_avc3:
7474       case FOURCC_H265:
7475       case FOURCC_hvc1:
7476       case FOURCC_hev1:
7477       case FOURCC_mjp2:
7478       case FOURCC_encv:
7479       {
7480         guint32 version;
7481         guint32 str_len;
7482
7483         /* codec_data is contained inside these atoms, which all have
7484          * the same format. */
7485         /* video sample description size is 86 bytes without extension.
7486          * node_length have to be bigger than 86 bytes because video sample
7487          * description can include extenstions such as esds, fiel, glbl, etc. */
7488         if (node_length < 86) {
7489           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7490               " sample description length too short (%u < 86)",
7491               GST_FOURCC_ARGS (fourcc), node_length);
7492           break;
7493         }
7494
7495         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7496             GST_FOURCC_ARGS (fourcc));
7497
7498         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7499          *              its data format.
7500          * revision level (2 bytes) : must be set to 0. */
7501         version = QT_UINT32 (buffer + 16);
7502         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7503
7504         /* compressor name : PASCAL string and informative purposes
7505          * first byte : the number of bytes to be displayed.
7506          *              it has to be less than 32 because it is reserved
7507          *              space of 32 bytes total including itself. */
7508         str_len = QT_UINT8 (buffer + 50);
7509         if (str_len < 32)
7510           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7511               (char *) buffer + 51);
7512         else
7513           GST_WARNING_OBJECT (qtdemux,
7514               "compressorname length too big (%u > 31)", str_len);
7515
7516         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7517             end - buffer);
7518         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7519         break;
7520       }
7521       case FOURCC_meta:
7522       {
7523         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7524         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7525         break;
7526       }
7527       case FOURCC_mp4s:
7528       {
7529         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7530         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7531         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7532         break;
7533       }
7534       case FOURCC_XiTh:
7535       {
7536         guint32 version;
7537         guint32 offset;
7538
7539         if (length < 16) {
7540           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7541               GST_FOURCC_ARGS (fourcc));
7542           break;
7543         }
7544
7545         version = QT_UINT32 (buffer + 12);
7546         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7547
7548         switch (version) {
7549           case 0x00000001:
7550             offset = 0x62;
7551             break;
7552           default:
7553             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7554             offset = 0;
7555             break;
7556         }
7557         if (offset) {
7558           if (length < offset) {
7559             GST_WARNING_OBJECT (qtdemux,
7560                 "skipping too small %" GST_FOURCC_FORMAT " box",
7561                 GST_FOURCC_ARGS (fourcc));
7562             break;
7563           }
7564           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7565         }
7566         break;
7567       }
7568       case FOURCC_in24:
7569       {
7570         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7571         break;
7572       }
7573       case FOURCC_uuid:
7574       {
7575         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7576         break;
7577       }
7578       case FOURCC_enca:
7579       {
7580         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7581         break;
7582       }
7583       default:
7584         if (!strcmp (type->name, "unknown"))
7585           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7586         break;
7587     }
7588   }
7589   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7590       GST_FOURCC_ARGS (fourcc));
7591   return TRUE;
7592
7593 /* ERRORS */
7594 not_enough_data:
7595   {
7596     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7597         (_("This file is corrupt and cannot be played.")),
7598         ("Not enough data for an atom header, got only %u bytes", length));
7599     return FALSE;
7600   }
7601 broken_atom_size:
7602   {
7603     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7604         (_("This file is corrupt and cannot be played.")),
7605         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7606             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7607             length));
7608     return FALSE;
7609   }
7610 }
7611
7612 static GNode *
7613 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7614 {
7615   GNode *child;
7616   guint8 *buffer;
7617   guint32 child_fourcc;
7618
7619   for (child = g_node_first_child (node); child;
7620       child = g_node_next_sibling (child)) {
7621     buffer = (guint8 *) child->data;
7622
7623     child_fourcc = QT_FOURCC (buffer + 4);
7624
7625     if (G_UNLIKELY (child_fourcc == fourcc)) {
7626       return child;
7627     }
7628   }
7629   return NULL;
7630 }
7631
7632 static GNode *
7633 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7634     GstByteReader * parser)
7635 {
7636   GNode *child;
7637   guint8 *buffer;
7638   guint32 child_fourcc, child_len;
7639
7640   for (child = g_node_first_child (node); child;
7641       child = g_node_next_sibling (child)) {
7642     buffer = (guint8 *) child->data;
7643
7644     child_len = QT_UINT32 (buffer);
7645     child_fourcc = QT_FOURCC (buffer + 4);
7646
7647     if (G_UNLIKELY (child_fourcc == fourcc)) {
7648       if (G_UNLIKELY (child_len < (4 + 4)))
7649         return NULL;
7650       /* FIXME: must verify if atom length < parent atom length */
7651       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7652       return child;
7653     }
7654   }
7655   return NULL;
7656 }
7657
7658 static GNode *
7659 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7660 {
7661   return g_node_nth_child (node, index);
7662 }
7663
7664 static GNode *
7665 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7666     GstByteReader * parser)
7667 {
7668   GNode *child;
7669   guint8 *buffer;
7670   guint32 child_fourcc, child_len;
7671
7672   for (child = g_node_next_sibling (node); child;
7673       child = g_node_next_sibling (child)) {
7674     buffer = (guint8 *) child->data;
7675
7676     child_fourcc = QT_FOURCC (buffer + 4);
7677
7678     if (child_fourcc == fourcc) {
7679       if (parser) {
7680         child_len = QT_UINT32 (buffer);
7681         if (G_UNLIKELY (child_len < (4 + 4)))
7682           return NULL;
7683         /* FIXME: must verify if atom length < parent atom length */
7684         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7685       }
7686       return child;
7687     }
7688   }
7689   return NULL;
7690 }
7691
7692 static GNode *
7693 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7694 {
7695   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7696 }
7697
7698 static void
7699 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7700 {
7701 /* FIXME: This can only reliably work if demuxers have a
7702  * separate streaming thread per srcpad. This should be
7703  * done in a demuxer base class, which integrates parts
7704  * of multiqueue
7705  *
7706  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7707  */
7708 #if 0
7709   GstQuery *query;
7710
7711   query = gst_query_new_allocation (stream->caps, FALSE);
7712
7713   if (!gst_pad_peer_query (stream->pad, query)) {
7714     /* not a problem, just debug a little */
7715     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7716   }
7717
7718   if (stream->allocator)
7719     gst_object_unref (stream->allocator);
7720
7721   if (gst_query_get_n_allocation_params (query) > 0) {
7722     /* try the allocator */
7723     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7724         &stream->params);
7725     stream->use_allocator = TRUE;
7726   } else {
7727     stream->allocator = NULL;
7728     gst_allocation_params_init (&stream->params);
7729     stream->use_allocator = FALSE;
7730   }
7731   gst_query_unref (query);
7732 #endif
7733 }
7734
7735 static gboolean
7736 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7737     QtDemuxStream * stream)
7738 {
7739   GstStructure *s;
7740   const gchar *selected_system;
7741
7742   g_return_val_if_fail (qtdemux != NULL, FALSE);
7743   g_return_val_if_fail (stream != NULL, FALSE);
7744   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7745       FALSE);
7746
7747   if (stream->protection_scheme_type != FOURCC_cenc) {
7748     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7749     return FALSE;
7750   }
7751   if (qtdemux->protection_system_ids == NULL) {
7752     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7753         "cenc protection system information has been found");
7754     return FALSE;
7755   }
7756   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7757   selected_system = gst_protection_select_system ((const gchar **)
7758       qtdemux->protection_system_ids->pdata);
7759   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7760       qtdemux->protection_system_ids->len - 1);
7761   if (!selected_system) {
7762     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7763         "suitable decryptor element has been found");
7764     return FALSE;
7765   }
7766
7767   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7768   if (!gst_structure_has_name (s, "application/x-cenc")) {
7769     gst_structure_set (s,
7770         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7771         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7772         NULL);
7773     gst_structure_set_name (s, "application/x-cenc");
7774   }
7775   return TRUE;
7776 }
7777
7778 static gboolean
7779 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7780 {
7781   if (stream->subtype == FOURCC_vide) {
7782     /* fps is calculated base on the duration of the average framerate since
7783      * qt does not have a fixed framerate. */
7784     gboolean fps_available = TRUE;
7785
7786     if ((stream->n_samples == 1 && stream->first_duration == 0)
7787         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
7788       /* still frame */
7789       CUR_STREAM (stream)->fps_n = 0;
7790       CUR_STREAM (stream)->fps_d = 1;
7791     } else {
7792       if (stream->duration == 0 || stream->n_samples < 2) {
7793         CUR_STREAM (stream)->fps_n = stream->timescale;
7794         CUR_STREAM (stream)->fps_d = 1;
7795         fps_available = FALSE;
7796       } else {
7797         GstClockTime avg_duration;
7798         guint64 duration;
7799         guint32 n_samples;
7800
7801         /* duration and n_samples can be updated for fragmented format
7802          * so, framerate of fragmented format is calculated using data in a moof */
7803         if (qtdemux->fragmented && stream->n_samples_moof > 0
7804             && stream->duration_moof > 0) {
7805           n_samples = stream->n_samples_moof;
7806           duration = stream->duration_moof;
7807         } else {
7808           n_samples = stream->n_samples;
7809           duration = stream->duration;
7810         }
7811
7812         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7813         /* stream->duration is guint64, timescale, n_samples are guint32 */
7814         avg_duration =
7815             gst_util_uint64_scale_round (duration -
7816             stream->first_duration, GST_SECOND,
7817             (guint64) (stream->timescale) * (n_samples - 1));
7818
7819         GST_LOG_OBJECT (qtdemux,
7820             "Calculating avg sample duration based on stream (or moof) duration %"
7821             G_GUINT64_FORMAT
7822             " minus first sample %u, leaving %d samples gives %"
7823             GST_TIME_FORMAT, duration, stream->first_duration,
7824             n_samples - 1, GST_TIME_ARGS (avg_duration));
7825
7826         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7827             &CUR_STREAM (stream)->fps_d);
7828
7829         GST_DEBUG_OBJECT (qtdemux,
7830             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7831             stream->timescale, CUR_STREAM (stream)->fps_n,
7832             CUR_STREAM (stream)->fps_d);
7833       }
7834     }
7835
7836     if (CUR_STREAM (stream)->caps) {
7837       CUR_STREAM (stream)->caps =
7838           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7839
7840       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7841           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7842           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7843
7844       /* set framerate if calculated framerate is reliable */
7845       if (fps_available) {
7846         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7847             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7848             CUR_STREAM (stream)->fps_d, NULL);
7849       }
7850
7851       /* calculate pixel-aspect-ratio using display width and height */
7852       GST_DEBUG_OBJECT (qtdemux,
7853           "video size %dx%d, target display size %dx%d",
7854           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7855           stream->display_width, stream->display_height);
7856       /* qt file might have pasp atom */
7857       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7858         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7859             CUR_STREAM (stream)->par_h);
7860         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7861             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7862             CUR_STREAM (stream)->par_h, NULL);
7863       } else if (stream->display_width > 0 && stream->display_height > 0
7864           && CUR_STREAM (stream)->width > 0
7865           && CUR_STREAM (stream)->height > 0) {
7866         gint n, d;
7867
7868         /* calculate the pixel aspect ratio using the display and pixel w/h */
7869         n = stream->display_width * CUR_STREAM (stream)->height;
7870         d = stream->display_height * CUR_STREAM (stream)->width;
7871         if (n == d)
7872           n = d = 1;
7873         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7874         CUR_STREAM (stream)->par_w = n;
7875         CUR_STREAM (stream)->par_h = d;
7876         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7877             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7878             CUR_STREAM (stream)->par_h, NULL);
7879       }
7880
7881       if (CUR_STREAM (stream)->interlace_mode > 0) {
7882         if (CUR_STREAM (stream)->interlace_mode == 1) {
7883           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7884               G_TYPE_STRING, "progressive", NULL);
7885         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7886           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7887               G_TYPE_STRING, "interleaved", NULL);
7888           if (CUR_STREAM (stream)->field_order == 9) {
7889             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7890                 G_TYPE_STRING, "top-field-first", NULL);
7891           } else if (CUR_STREAM (stream)->field_order == 14) {
7892             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7893                 G_TYPE_STRING, "bottom-field-first", NULL);
7894           }
7895         }
7896       }
7897
7898       /* Create incomplete colorimetry here if needed */
7899       if (CUR_STREAM (stream)->colorimetry.range ||
7900           CUR_STREAM (stream)->colorimetry.matrix ||
7901           CUR_STREAM (stream)->colorimetry.transfer
7902           || CUR_STREAM (stream)->colorimetry.primaries) {
7903         gchar *colorimetry =
7904             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7905         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7906             G_TYPE_STRING, colorimetry, NULL);
7907         g_free (colorimetry);
7908       }
7909
7910       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7911         guint par_w = 1, par_h = 1;
7912
7913         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7914           par_w = CUR_STREAM (stream)->par_w;
7915           par_h = CUR_STREAM (stream)->par_h;
7916         }
7917
7918         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7919                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7920                 par_h)) {
7921           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7922         }
7923
7924         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7925             "multiview-mode", G_TYPE_STRING,
7926             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7927             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7928             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7929       }
7930     }
7931   }
7932
7933   else if (stream->subtype == FOURCC_soun) {
7934     if (CUR_STREAM (stream)->caps) {
7935       CUR_STREAM (stream)->caps =
7936           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7937       if (CUR_STREAM (stream)->rate > 0)
7938         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7939             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
7940       if (CUR_STREAM (stream)->n_channels > 0)
7941         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7942             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
7943       if (CUR_STREAM (stream)->n_channels > 2) {
7944         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7945          * correctly; this is just the minimum we can do - assume
7946          * we don't actually have any channel positions. */
7947         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7948             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7949       }
7950     }
7951   }
7952
7953   if (stream->pad) {
7954     GstCaps *prev_caps = NULL;
7955
7956     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7957     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7958     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7959     gst_pad_set_active (stream->pad, TRUE);
7960
7961     gst_pad_use_fixed_caps (stream->pad);
7962
7963     if (stream->protected) {
7964       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7965         GST_ERROR_OBJECT (qtdemux,
7966             "Failed to configure protected stream caps.");
7967         return FALSE;
7968       }
7969     }
7970
7971     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7972         CUR_STREAM (stream)->caps);
7973     if (stream->new_stream) {
7974       gchar *stream_id;
7975       GstEvent *event;
7976       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7977
7978       event =
7979           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7980           0);
7981       if (event) {
7982         gst_event_parse_stream_flags (event, &stream_flags);
7983         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7984           qtdemux->have_group_id = TRUE;
7985         else
7986           qtdemux->have_group_id = FALSE;
7987         gst_event_unref (event);
7988       } else if (!qtdemux->have_group_id) {
7989         qtdemux->have_group_id = TRUE;
7990         qtdemux->group_id = gst_util_group_id_next ();
7991       }
7992
7993       stream->new_stream = FALSE;
7994       stream_id =
7995           gst_pad_create_stream_id_printf (stream->pad,
7996           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7997       event = gst_event_new_stream_start (stream_id);
7998       if (qtdemux->have_group_id)
7999         gst_event_set_group_id (event, qtdemux->group_id);
8000       if (stream->disabled)
8001         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8002       if (CUR_STREAM (stream)->sparse) {
8003         stream_flags |= GST_STREAM_FLAG_SPARSE;
8004       } else {
8005         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8006       }
8007       gst_event_set_stream_flags (event, stream_flags);
8008       gst_pad_push_event (stream->pad, event);
8009       g_free (stream_id);
8010     }
8011
8012     prev_caps = gst_pad_get_current_caps (stream->pad);
8013
8014     if (CUR_STREAM (stream)->caps) {
8015       if (!prev_caps
8016           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8017         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8018             CUR_STREAM (stream)->caps);
8019         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8020       } else {
8021         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8022       }
8023     } else {
8024       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8025     }
8026
8027     if (prev_caps)
8028       gst_caps_unref (prev_caps);
8029     stream->new_caps = FALSE;
8030   }
8031   return TRUE;
8032 }
8033
8034 static void
8035 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8036     QtDemuxStream * stream)
8037 {
8038   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8039     return;
8040
8041   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8042       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8043   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8044           stream->stsd_entries_length)) {
8045     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8046         (_("This file is invalid and cannot be played.")),
8047         ("New sample description id is out of bounds (%d >= %d)",
8048             stream->stsd_sample_description_id, stream->stsd_entries_length));
8049   } else {
8050     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8051     stream->new_caps = TRUE;
8052   }
8053 }
8054
8055 static gboolean
8056 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8057     QtDemuxStream * stream, GstTagList * list)
8058 {
8059   gboolean ret = TRUE;
8060   /* consistent default for push based mode */
8061   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8062
8063   if (stream->subtype == FOURCC_vide) {
8064     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8065
8066     stream->pad =
8067         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8068     g_free (name);
8069
8070     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8071       gst_object_unref (stream->pad);
8072       stream->pad = NULL;
8073       ret = FALSE;
8074       goto done;
8075     }
8076
8077     qtdemux->n_video_streams++;
8078   } else if (stream->subtype == FOURCC_soun) {
8079     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8080
8081     stream->pad =
8082         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8083     g_free (name);
8084     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8085       gst_object_unref (stream->pad);
8086       stream->pad = NULL;
8087       ret = FALSE;
8088       goto done;
8089     }
8090     qtdemux->n_audio_streams++;
8091   } else if (stream->subtype == FOURCC_strm) {
8092     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8093   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8094       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8095     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8096
8097     stream->pad =
8098         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8099     g_free (name);
8100     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8101       gst_object_unref (stream->pad);
8102       stream->pad = NULL;
8103       ret = FALSE;
8104       goto done;
8105     }
8106     qtdemux->n_sub_streams++;
8107   } else if (CUR_STREAM (stream)->caps) {
8108     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8109
8110     stream->pad =
8111         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8112     g_free (name);
8113     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8114       gst_object_unref (stream->pad);
8115       stream->pad = NULL;
8116       ret = FALSE;
8117       goto done;
8118     }
8119     qtdemux->n_video_streams++;
8120   } else {
8121     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8122     goto done;
8123   }
8124
8125   if (stream->pad) {
8126     GList *l;
8127
8128     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8129         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8130     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8131     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8132
8133     if (stream->stream_tags)
8134       gst_tag_list_unref (stream->stream_tags);
8135     stream->stream_tags = list;
8136     list = NULL;
8137     /* global tags go on each pad anyway */
8138     stream->send_global_tags = TRUE;
8139     /* send upstream GST_EVENT_PROTECTION events that were received before
8140        this source pad was created */
8141     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8142       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8143   }
8144 done:
8145   if (list)
8146     gst_tag_list_unref (list);
8147   return ret;
8148 }
8149
8150 /* find next atom with @fourcc starting at @offset */
8151 static GstFlowReturn
8152 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8153     guint64 * length, guint32 fourcc)
8154 {
8155   GstFlowReturn ret;
8156   guint32 lfourcc;
8157   GstBuffer *buf;
8158
8159   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8160       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8161
8162   while (TRUE) {
8163     GstMapInfo map;
8164
8165     buf = NULL;
8166     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8167     if (G_UNLIKELY (ret != GST_FLOW_OK))
8168       goto locate_failed;
8169     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8170       /* likely EOF */
8171       ret = GST_FLOW_EOS;
8172       gst_buffer_unref (buf);
8173       goto locate_failed;
8174     }
8175     gst_buffer_map (buf, &map, GST_MAP_READ);
8176     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8177     gst_buffer_unmap (buf, &map);
8178     gst_buffer_unref (buf);
8179
8180     if (G_UNLIKELY (*length == 0)) {
8181       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8182       ret = GST_FLOW_ERROR;
8183       goto locate_failed;
8184     }
8185
8186     if (lfourcc == fourcc) {
8187       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8188           *offset);
8189       break;
8190     } else {
8191       GST_LOG_OBJECT (qtdemux,
8192           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8193           GST_FOURCC_ARGS (fourcc), *offset);
8194       *offset += *length;
8195     }
8196   }
8197
8198   return GST_FLOW_OK;
8199
8200 locate_failed:
8201   {
8202     /* might simply have had last one */
8203     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8204     return ret;
8205   }
8206 }
8207
8208 /* should only do something in pull mode */
8209 /* call with OBJECT lock */
8210 static GstFlowReturn
8211 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8212 {
8213   guint64 length, offset;
8214   GstBuffer *buf = NULL;
8215   GstFlowReturn ret = GST_FLOW_OK;
8216   GstFlowReturn res = GST_FLOW_OK;
8217   GstMapInfo map;
8218
8219   offset = qtdemux->moof_offset;
8220   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8221
8222   if (!offset) {
8223     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8224     return GST_FLOW_EOS;
8225   }
8226
8227   /* best not do pull etc with lock held */
8228   GST_OBJECT_UNLOCK (qtdemux);
8229
8230   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8231   if (ret != GST_FLOW_OK)
8232     goto flow_failed;
8233
8234   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8235   if (G_UNLIKELY (ret != GST_FLOW_OK))
8236     goto flow_failed;
8237   gst_buffer_map (buf, &map, GST_MAP_READ);
8238   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8239     gst_buffer_unmap (buf, &map);
8240     gst_buffer_unref (buf);
8241     buf = NULL;
8242     goto parse_failed;
8243   }
8244
8245   gst_buffer_unmap (buf, &map);
8246   gst_buffer_unref (buf);
8247   buf = NULL;
8248
8249   offset += length;
8250   /* look for next moof */
8251   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8252   if (G_UNLIKELY (ret != GST_FLOW_OK))
8253     goto flow_failed;
8254
8255 exit:
8256   GST_OBJECT_LOCK (qtdemux);
8257
8258   qtdemux->moof_offset = offset;
8259
8260   return res;
8261
8262 parse_failed:
8263   {
8264     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8265     offset = 0;
8266     res = GST_FLOW_ERROR;
8267     goto exit;
8268   }
8269 flow_failed:
8270   {
8271     /* maybe upstream temporarily flushing */
8272     if (ret != GST_FLOW_FLUSHING) {
8273       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8274       offset = 0;
8275     } else {
8276       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8277       /* resume at current position next time */
8278     }
8279     res = ret;
8280     goto exit;
8281   }
8282 }
8283
8284 /* initialise bytereaders for stbl sub-atoms */
8285 static gboolean
8286 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8287 {
8288   stream->stbl_index = -1;      /* no samples have yet been parsed */
8289   stream->sample_index = -1;
8290
8291   /* time-to-sample atom */
8292   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8293     goto corrupt_file;
8294
8295   /* copy atom data into a new buffer for later use */
8296   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8297
8298   /* skip version + flags */
8299   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8300       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8301     goto corrupt_file;
8302   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8303
8304   /* make sure there's enough data */
8305   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8306     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8307     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8308         stream->n_sample_times);
8309     if (!stream->n_sample_times)
8310       goto corrupt_file;
8311   }
8312
8313   /* sync sample atom */
8314   stream->stps_present = FALSE;
8315   if ((stream->stss_present =
8316           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8317               &stream->stss) ? TRUE : FALSE) == TRUE) {
8318     /* copy atom data into a new buffer for later use */
8319     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8320
8321     /* skip version + flags */
8322     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8323         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8324       goto corrupt_file;
8325
8326     if (stream->n_sample_syncs) {
8327       /* make sure there's enough data */
8328       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8329         goto corrupt_file;
8330     }
8331
8332     /* partial sync sample atom */
8333     if ((stream->stps_present =
8334             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8335                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8336       /* copy atom data into a new buffer for later use */
8337       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8338
8339       /* skip version + flags */
8340       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8341           !gst_byte_reader_get_uint32_be (&stream->stps,
8342               &stream->n_sample_partial_syncs))
8343         goto corrupt_file;
8344
8345       /* if there are no entries, the stss table contains the real
8346        * sync samples */
8347       if (stream->n_sample_partial_syncs) {
8348         /* make sure there's enough data */
8349         if (!qt_atom_parser_has_chunks (&stream->stps,
8350                 stream->n_sample_partial_syncs, 4))
8351           goto corrupt_file;
8352       }
8353     }
8354   }
8355
8356   /* sample size */
8357   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8358     goto no_samples;
8359
8360   /* copy atom data into a new buffer for later use */
8361   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8362
8363   /* skip version + flags */
8364   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8365       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8366     goto corrupt_file;
8367
8368   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8369     goto corrupt_file;
8370
8371   if (!stream->n_samples)
8372     goto no_samples;
8373
8374   /* sample-to-chunk atom */
8375   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8376     goto corrupt_file;
8377
8378   /* copy atom data into a new buffer for later use */
8379   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8380
8381   /* skip version + flags */
8382   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8383       !gst_byte_reader_get_uint32_be (&stream->stsc,
8384           &stream->n_samples_per_chunk))
8385     goto corrupt_file;
8386
8387   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8388       stream->n_samples_per_chunk);
8389
8390   /* make sure there's enough data */
8391   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8392           12))
8393     goto corrupt_file;
8394
8395
8396   /* chunk offset */
8397   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8398     stream->co_size = sizeof (guint32);
8399   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8400           &stream->stco))
8401     stream->co_size = sizeof (guint64);
8402   else
8403     goto corrupt_file;
8404
8405   /* copy atom data into a new buffer for later use */
8406   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8407
8408   /* skip version + flags */
8409   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8410     goto corrupt_file;
8411
8412   /* chunks_are_samples == TRUE means treat chunks as samples */
8413   stream->chunks_are_samples = stream->sample_size
8414       && !CUR_STREAM (stream)->sampled;
8415   if (stream->chunks_are_samples) {
8416     /* treat chunks as samples */
8417     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8418       goto corrupt_file;
8419   } else {
8420     /* skip number of entries */
8421     if (!gst_byte_reader_skip (&stream->stco, 4))
8422       goto corrupt_file;
8423
8424     /* make sure there are enough data in the stsz atom */
8425     if (!stream->sample_size) {
8426       /* different sizes for each sample */
8427       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8428         goto corrupt_file;
8429     }
8430   }
8431
8432   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8433       stream->n_samples, (guint) sizeof (QtDemuxSample),
8434       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8435
8436   if (stream->n_samples >=
8437       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8438     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8439         "be larger than %uMB (broken file?)", stream->n_samples,
8440         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8441     return FALSE;
8442   }
8443
8444   g_assert (stream->samples == NULL);
8445   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8446   if (!stream->samples) {
8447     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8448         stream->n_samples);
8449     return FALSE;
8450   }
8451
8452   /* composition time-to-sample */
8453   if ((stream->ctts_present =
8454           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8455               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8456     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8457
8458     /* copy atom data into a new buffer for later use */
8459     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8460
8461     /* skip version + flags */
8462     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8463         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8464             &stream->n_composition_times))
8465       goto corrupt_file;
8466
8467     /* make sure there's enough data */
8468     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8469             4 + 4))
8470       goto corrupt_file;
8471
8472     /* This is optional, if missing we iterate the ctts */
8473     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8474       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8475           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8476         g_free ((gpointer) cslg.data);
8477         goto corrupt_file;
8478       }
8479     } else {
8480       gint32 cslg_least = 0;
8481       guint num_entries, pos;
8482       gint i;
8483
8484       pos = gst_byte_reader_get_pos (&stream->ctts);
8485       num_entries = stream->n_composition_times;
8486
8487       stream->cslg_shift = 0;
8488
8489       for (i = 0; i < num_entries; i++) {
8490         gint32 offset;
8491
8492         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8493         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8494
8495         if (offset < cslg_least)
8496           cslg_least = offset;
8497       }
8498
8499       if (cslg_least < 0)
8500         stream->cslg_shift = ABS (cslg_least);
8501       else
8502         stream->cslg_shift = 0;
8503
8504       /* reset the reader so we can generate sample table */
8505       gst_byte_reader_set_pos (&stream->ctts, pos);
8506     }
8507   } else {
8508     /* Ensure the cslg_shift value is consistent so we can use it
8509      * unconditionnally to produce TS and Segment */
8510     stream->cslg_shift = 0;
8511   }
8512
8513   return TRUE;
8514
8515 corrupt_file:
8516   {
8517     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8518         (_("This file is corrupt and cannot be played.")), (NULL));
8519     return FALSE;
8520   }
8521 no_samples:
8522   {
8523     gst_qtdemux_stbl_free (stream);
8524     if (!qtdemux->fragmented) {
8525       /* not quite good */
8526       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8527       return FALSE;
8528     } else {
8529       /* may pick up samples elsewhere */
8530       return TRUE;
8531     }
8532   }
8533 }
8534
8535 /* collect samples from the next sample to be parsed up to sample @n for @stream
8536  * by reading the info from @stbl
8537  *
8538  * This code can be executed from both the streaming thread and the seeking
8539  * thread so it takes the object lock to protect itself
8540  */
8541 static gboolean
8542 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8543 {
8544   gint i, j, k;
8545   QtDemuxSample *samples, *first, *cur, *last;
8546   guint32 n_samples_per_chunk;
8547   guint32 n_samples;
8548
8549   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8550       GST_FOURCC_FORMAT ", pad %s",
8551       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8552       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8553
8554   n_samples = stream->n_samples;
8555
8556   if (n >= n_samples)
8557     goto out_of_samples;
8558
8559   GST_OBJECT_LOCK (qtdemux);
8560   if (n <= stream->stbl_index)
8561     goto already_parsed;
8562
8563   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8564
8565   if (!stream->stsz.data) {
8566     /* so we already parsed and passed all the moov samples;
8567      * onto fragmented ones */
8568     g_assert (qtdemux->fragmented);
8569     goto done;
8570   }
8571
8572   /* pointer to the sample table */
8573   samples = stream->samples;
8574
8575   /* starts from -1, moves to the next sample index to parse */
8576   stream->stbl_index++;
8577
8578   /* keep track of the first and last sample to fill */
8579   first = &samples[stream->stbl_index];
8580   last = &samples[n];
8581
8582   if (!stream->chunks_are_samples) {
8583     /* set the sample sizes */
8584     if (stream->sample_size == 0) {
8585       /* different sizes for each sample */
8586       for (cur = first; cur <= last; cur++) {
8587         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8588         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8589             (guint) (cur - samples), cur->size);
8590       }
8591     } else {
8592       /* samples have the same size */
8593       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8594       for (cur = first; cur <= last; cur++)
8595         cur->size = stream->sample_size;
8596     }
8597   }
8598
8599   n_samples_per_chunk = stream->n_samples_per_chunk;
8600   cur = first;
8601
8602   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8603     guint32 last_chunk;
8604
8605     if (stream->stsc_chunk_index >= stream->last_chunk
8606         || stream->stsc_chunk_index < stream->first_chunk) {
8607       stream->first_chunk =
8608           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8609       stream->samples_per_chunk =
8610           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8611       /* starts from 1 */
8612       stream->stsd_sample_description_id =
8613           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8614
8615       /* chunk numbers are counted from 1 it seems */
8616       if (G_UNLIKELY (stream->first_chunk == 0))
8617         goto corrupt_file;
8618
8619       --stream->first_chunk;
8620
8621       /* the last chunk of each entry is calculated by taking the first chunk
8622        * of the next entry; except if there is no next, where we fake it with
8623        * INT_MAX */
8624       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8625         stream->last_chunk = G_MAXUINT32;
8626       } else {
8627         stream->last_chunk =
8628             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8629         if (G_UNLIKELY (stream->last_chunk == 0))
8630           goto corrupt_file;
8631
8632         --stream->last_chunk;
8633       }
8634
8635       GST_LOG_OBJECT (qtdemux,
8636           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8637           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8638           stream->samples_per_chunk, stream->stsd_sample_description_id);
8639
8640       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8641         goto corrupt_file;
8642
8643       if (stream->last_chunk != G_MAXUINT32) {
8644         if (!qt_atom_parser_peek_sub (&stream->stco,
8645                 stream->first_chunk * stream->co_size,
8646                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8647                 &stream->co_chunk))
8648           goto corrupt_file;
8649
8650       } else {
8651         stream->co_chunk = stream->stco;
8652         if (!gst_byte_reader_skip (&stream->co_chunk,
8653                 stream->first_chunk * stream->co_size))
8654           goto corrupt_file;
8655       }
8656
8657       stream->stsc_chunk_index = stream->first_chunk;
8658     }
8659
8660     last_chunk = stream->last_chunk;
8661
8662     if (stream->chunks_are_samples) {
8663       cur = &samples[stream->stsc_chunk_index];
8664
8665       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8666         if (j > n) {
8667           /* save state */
8668           stream->stsc_chunk_index = j;
8669           goto done;
8670         }
8671
8672         cur->offset =
8673             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8674             stream->co_size);
8675
8676         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8677             "%" G_GUINT64_FORMAT, j, cur->offset);
8678
8679         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8680             CUR_STREAM (stream)->bytes_per_frame > 0) {
8681           cur->size =
8682               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8683               CUR_STREAM (stream)->samples_per_frame *
8684               CUR_STREAM (stream)->bytes_per_frame;
8685         } else {
8686           cur->size = stream->samples_per_chunk;
8687         }
8688
8689         GST_DEBUG_OBJECT (qtdemux,
8690             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8691             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8692                     stream->stco_sample_index)), cur->size);
8693
8694         cur->timestamp = stream->stco_sample_index;
8695         cur->duration = stream->samples_per_chunk;
8696         cur->keyframe = TRUE;
8697         cur++;
8698
8699         stream->stco_sample_index += stream->samples_per_chunk;
8700       }
8701       stream->stsc_chunk_index = j;
8702     } else {
8703       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8704         guint32 samples_per_chunk;
8705         guint64 chunk_offset;
8706
8707         if (!stream->stsc_sample_index
8708             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8709                 &stream->chunk_offset))
8710           goto corrupt_file;
8711
8712         samples_per_chunk = stream->samples_per_chunk;
8713         chunk_offset = stream->chunk_offset;
8714
8715         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8716           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8717               G_GUINT64_FORMAT " and size %d",
8718               (guint) (cur - samples), chunk_offset, cur->size);
8719
8720           cur->offset = chunk_offset;
8721           chunk_offset += cur->size;
8722           cur++;
8723
8724           if (G_UNLIKELY (cur > last)) {
8725             /* save state */
8726             stream->stsc_sample_index = k + 1;
8727             stream->chunk_offset = chunk_offset;
8728             stream->stsc_chunk_index = j;
8729             goto done2;
8730           }
8731         }
8732         stream->stsc_sample_index = 0;
8733       }
8734       stream->stsc_chunk_index = j;
8735     }
8736     stream->stsc_index++;
8737   }
8738
8739   if (stream->chunks_are_samples)
8740     goto ctts;
8741 done2:
8742   {
8743     guint32 n_sample_times;
8744
8745     n_sample_times = stream->n_sample_times;
8746     cur = first;
8747
8748     for (i = stream->stts_index; i < n_sample_times; i++) {
8749       guint32 stts_samples;
8750       gint32 stts_duration;
8751       gint64 stts_time;
8752
8753       if (stream->stts_sample_index >= stream->stts_samples
8754           || !stream->stts_sample_index) {
8755
8756         stream->stts_samples =
8757             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8758         stream->stts_duration =
8759             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8760
8761         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8762             i, stream->stts_samples, stream->stts_duration);
8763
8764         stream->stts_sample_index = 0;
8765       }
8766
8767       stts_samples = stream->stts_samples;
8768       stts_duration = stream->stts_duration;
8769       stts_time = stream->stts_time;
8770
8771       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8772         GST_DEBUG_OBJECT (qtdemux,
8773             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8774             (guint) (cur - samples), j,
8775             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8776
8777         cur->timestamp = stts_time;
8778         cur->duration = stts_duration;
8779
8780         /* avoid 32-bit wrap-around,
8781          * but still mind possible 'negative' duration */
8782         stts_time += (gint64) stts_duration;
8783         cur++;
8784
8785         if (G_UNLIKELY (cur > last)) {
8786           /* save values */
8787           stream->stts_time = stts_time;
8788           stream->stts_sample_index = j + 1;
8789           if (stream->stts_sample_index >= stream->stts_samples)
8790             stream->stts_index++;
8791           goto done3;
8792         }
8793       }
8794       stream->stts_sample_index = 0;
8795       stream->stts_time = stts_time;
8796       stream->stts_index++;
8797     }
8798     /* fill up empty timestamps with the last timestamp, this can happen when
8799      * the last samples do not decode and so we don't have timestamps for them.
8800      * We however look at the last timestamp to estimate the track length so we
8801      * need something in here. */
8802     for (; cur < last; cur++) {
8803       GST_DEBUG_OBJECT (qtdemux,
8804           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8805           (guint) (cur - samples),
8806           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8807       cur->timestamp = stream->stts_time;
8808       cur->duration = -1;
8809     }
8810   }
8811 done3:
8812   {
8813     /* sample sync, can be NULL */
8814     if (stream->stss_present == TRUE) {
8815       guint32 n_sample_syncs;
8816
8817       n_sample_syncs = stream->n_sample_syncs;
8818
8819       if (!n_sample_syncs) {
8820         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8821         stream->all_keyframe = TRUE;
8822       } else {
8823         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8824           /* note that the first sample is index 1, not 0 */
8825           guint32 index;
8826
8827           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8828
8829           if (G_LIKELY (index > 0 && index <= n_samples)) {
8830             index -= 1;
8831             samples[index].keyframe = TRUE;
8832             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8833             /* and exit if we have enough samples */
8834             if (G_UNLIKELY (index >= n)) {
8835               i++;
8836               break;
8837             }
8838           }
8839         }
8840         /* save state */
8841         stream->stss_index = i;
8842       }
8843
8844       /* stps marks partial sync frames like open GOP I-Frames */
8845       if (stream->stps_present == TRUE) {
8846         guint32 n_sample_partial_syncs;
8847
8848         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8849
8850         /* if there are no entries, the stss table contains the real
8851          * sync samples */
8852         if (n_sample_partial_syncs) {
8853           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8854             /* note that the first sample is index 1, not 0 */
8855             guint32 index;
8856
8857             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8858
8859             if (G_LIKELY (index > 0 && index <= n_samples)) {
8860               index -= 1;
8861               samples[index].keyframe = TRUE;
8862               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8863               /* and exit if we have enough samples */
8864               if (G_UNLIKELY (index >= n)) {
8865                 i++;
8866                 break;
8867               }
8868             }
8869           }
8870           /* save state */
8871           stream->stps_index = i;
8872         }
8873       }
8874     } else {
8875       /* no stss, all samples are keyframes */
8876       stream->all_keyframe = TRUE;
8877       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8878     }
8879   }
8880
8881 ctts:
8882   /* composition time to sample */
8883   if (stream->ctts_present == TRUE) {
8884     guint32 n_composition_times;
8885     guint32 ctts_count;
8886     gint32 ctts_soffset;
8887
8888     /* Fill in the pts_offsets */
8889     cur = first;
8890     n_composition_times = stream->n_composition_times;
8891
8892     for (i = stream->ctts_index; i < n_composition_times; i++) {
8893       if (stream->ctts_sample_index >= stream->ctts_count
8894           || !stream->ctts_sample_index) {
8895         stream->ctts_count =
8896             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8897         stream->ctts_soffset =
8898             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8899         stream->ctts_sample_index = 0;
8900       }
8901
8902       ctts_count = stream->ctts_count;
8903       ctts_soffset = stream->ctts_soffset;
8904
8905       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8906         cur->pts_offset = ctts_soffset;
8907         cur++;
8908
8909         if (G_UNLIKELY (cur > last)) {
8910           /* save state */
8911           stream->ctts_sample_index = j + 1;
8912           goto done;
8913         }
8914       }
8915       stream->ctts_sample_index = 0;
8916       stream->ctts_index++;
8917     }
8918   }
8919 done:
8920   stream->stbl_index = n;
8921   /* if index has been completely parsed, free data that is no-longer needed */
8922   if (n + 1 == stream->n_samples) {
8923     gst_qtdemux_stbl_free (stream);
8924     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8925     if (qtdemux->pullbased) {
8926       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8927       while (n + 1 == stream->n_samples)
8928         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8929           break;
8930     }
8931   }
8932   GST_OBJECT_UNLOCK (qtdemux);
8933
8934   return TRUE;
8935
8936   /* SUCCESS */
8937 already_parsed:
8938   {
8939     GST_LOG_OBJECT (qtdemux,
8940         "Tried to parse up to sample %u but this sample has already been parsed",
8941         n);
8942     /* if fragmented, there may be more */
8943     if (qtdemux->fragmented && n == stream->stbl_index)
8944       goto done;
8945     GST_OBJECT_UNLOCK (qtdemux);
8946     return TRUE;
8947   }
8948   /* ERRORS */
8949 out_of_samples:
8950   {
8951     GST_LOG_OBJECT (qtdemux,
8952         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8953         stream->n_samples);
8954     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8955         (_("This file is corrupt and cannot be played.")), (NULL));
8956     return FALSE;
8957   }
8958 corrupt_file:
8959   {
8960     GST_OBJECT_UNLOCK (qtdemux);
8961     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8962         (_("This file is corrupt and cannot be played.")), (NULL));
8963     return FALSE;
8964   }
8965 }
8966
8967 /* collect all segment info for @stream.
8968  */
8969 static gboolean
8970 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8971     GNode * trak)
8972 {
8973   GNode *edts;
8974   /* accept edts if they contain gaps at start and there is only
8975    * one media segment */
8976   gboolean allow_pushbased_edts = TRUE;
8977   gint media_segments_count = 0;
8978
8979   /* parse and prepare segment info from the edit list */
8980   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8981   stream->n_segments = 0;
8982   stream->segments = NULL;
8983   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8984     GNode *elst;
8985     gint n_segments;
8986     gint i, count, entry_size;
8987     guint64 time;
8988     GstClockTime stime;
8989     const guint8 *buffer;
8990     guint8 version;
8991     guint32 size;
8992
8993     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8994     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8995       goto done;
8996
8997     buffer = elst->data;
8998
8999     size = QT_UINT32 (buffer);
9000     /* version, flags, n_segments */
9001     if (size < 16) {
9002       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9003       goto done;
9004     }
9005     version = QT_UINT8 (buffer + 8);
9006     entry_size = (version == 1) ? 20 : 12;
9007
9008     n_segments = QT_UINT32 (buffer + 12);
9009
9010     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9011       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9012       goto done;
9013     }
9014
9015     /* we might allocate a bit too much, at least allocate 1 segment */
9016     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9017
9018     /* segments always start from 0 */
9019     time = 0;
9020     stime = 0;
9021     count = 0;
9022     buffer += 16;
9023     for (i = 0; i < n_segments; i++) {
9024       guint64 duration;
9025       guint64 media_time;
9026       gboolean time_valid = TRUE;
9027       QtDemuxSegment *segment;
9028       guint32 rate_int;
9029       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9030
9031       if (version == 1) {
9032         media_time = QT_UINT64 (buffer + 8);
9033         duration = QT_UINT64 (buffer);
9034         if (media_time == G_MAXUINT64)
9035           time_valid = FALSE;
9036       } else {
9037         media_time = QT_UINT32 (buffer + 4);
9038         duration = QT_UINT32 (buffer);
9039         if (media_time == G_MAXUINT32)
9040           time_valid = FALSE;
9041       }
9042
9043       if (time_valid)
9044         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9045
9046       segment = &stream->segments[count++];
9047
9048       /* time and duration expressed in global timescale */
9049       segment->time = stime;
9050       /* add non scaled values so we don't cause roundoff errors */
9051       if (duration || media_start == GST_CLOCK_TIME_NONE) {
9052         time += duration;
9053         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9054         segment->duration = stime - segment->time;
9055       } else {
9056         /* zero duration does not imply media_start == media_stop
9057          * but, only specify media_start.*/
9058         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9059         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9060             && stime >= media_start) {
9061           segment->duration = stime - media_start;
9062         } else {
9063           segment->duration = GST_CLOCK_TIME_NONE;
9064         }
9065       }
9066       segment->stop_time = stime;
9067
9068       segment->trak_media_start = media_time;
9069       /* media_time expressed in stream timescale */
9070       if (time_valid) {
9071         segment->media_start = media_start;
9072         segment->media_stop = segment->media_start + segment->duration;
9073         media_segments_count++;
9074       } else {
9075         segment->media_start = GST_CLOCK_TIME_NONE;
9076         segment->media_stop = GST_CLOCK_TIME_NONE;
9077       }
9078       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9079
9080       if (rate_int <= 1) {
9081         /* 0 is not allowed, some programs write 1 instead of the floating point
9082          * value */
9083         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9084             rate_int);
9085         segment->rate = 1;
9086       } else {
9087         segment->rate = rate_int / 65536.0;
9088       }
9089
9090       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9091           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9092           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9093           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9094           i, GST_TIME_ARGS (segment->time),
9095           GST_TIME_ARGS (segment->duration),
9096           GST_TIME_ARGS (segment->media_start), media_time,
9097           GST_TIME_ARGS (segment->media_stop),
9098           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9099           stream->timescale);
9100       if (segment->stop_time > qtdemux->segment.stop) {
9101         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9102             " extends to %" GST_TIME_FORMAT
9103             " past the end of the file duration %" GST_TIME_FORMAT
9104             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9105             GST_TIME_ARGS (qtdemux->segment.stop));
9106         qtdemux->segment.stop = segment->stop_time;
9107       }
9108
9109       buffer += entry_size;
9110     }
9111     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9112     stream->n_segments = count;
9113     if (media_segments_count != 1)
9114       allow_pushbased_edts = FALSE;
9115   }
9116 done:
9117
9118   /* push based does not handle segments, so act accordingly here,
9119    * and warn if applicable */
9120   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9121     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9122     /* remove and use default one below, we stream like it anyway */
9123     g_free (stream->segments);
9124     stream->segments = NULL;
9125     stream->n_segments = 0;
9126   }
9127
9128   /* no segments, create one to play the complete trak */
9129   if (stream->n_segments == 0) {
9130     GstClockTime stream_duration =
9131         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9132
9133     if (stream->segments == NULL)
9134       stream->segments = g_new (QtDemuxSegment, 1);
9135
9136     /* represent unknown our way */
9137     if (stream_duration == 0)
9138       stream_duration = GST_CLOCK_TIME_NONE;
9139
9140     stream->segments[0].time = 0;
9141     stream->segments[0].stop_time = stream_duration;
9142     stream->segments[0].duration = stream_duration;
9143     stream->segments[0].media_start = 0;
9144     stream->segments[0].media_stop = stream_duration;
9145     stream->segments[0].rate = 1.0;
9146     stream->segments[0].trak_media_start = 0;
9147
9148     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9149         GST_TIME_ARGS (stream_duration));
9150     stream->n_segments = 1;
9151     stream->dummy_segment = TRUE;
9152   }
9153   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9154
9155   return TRUE;
9156 }
9157
9158 /*
9159  * Parses the stsd atom of a svq3 trak looking for
9160  * the SMI and gama atoms.
9161  */
9162 static void
9163 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9164     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9165 {
9166   const guint8 *_gamma = NULL;
9167   GstBuffer *_seqh = NULL;
9168   const guint8 *stsd_data = stsd_entry_data;
9169   guint32 length = QT_UINT32 (stsd_data);
9170   guint16 version;
9171
9172   if (length < 32) {
9173     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9174     goto end;
9175   }
9176
9177   stsd_data += 16;
9178   length -= 16;
9179   version = QT_UINT16 (stsd_data);
9180   if (version == 3) {
9181     if (length >= 70) {
9182       length -= 70;
9183       stsd_data += 70;
9184       while (length > 8) {
9185         guint32 fourcc, size;
9186         const guint8 *data;
9187         size = QT_UINT32 (stsd_data);
9188         fourcc = QT_FOURCC (stsd_data + 4);
9189         data = stsd_data + 8;
9190
9191         if (size == 0) {
9192           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9193               "svq3 atom parsing");
9194           goto end;
9195         }
9196
9197         switch (fourcc) {
9198           case FOURCC_gama:{
9199             if (size == 12) {
9200               _gamma = data;
9201             } else {
9202               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9203                   " for gama atom, expected 12", size);
9204             }
9205             break;
9206           }
9207           case FOURCC_SMI_:{
9208             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9209               guint32 seqh_size;
9210               if (_seqh != NULL) {
9211                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9212                     " found, ignoring");
9213               } else {
9214                 seqh_size = QT_UINT32 (data + 4);
9215                 if (seqh_size > 0) {
9216                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9217                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9218                 }
9219               }
9220             }
9221             break;
9222           }
9223           default:{
9224             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9225                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9226           }
9227         }
9228
9229         if (size <= length) {
9230           length -= size;
9231           stsd_data += size;
9232         }
9233       }
9234     } else {
9235       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9236     }
9237   } else {
9238     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9239         G_GUINT16_FORMAT, version);
9240     goto end;
9241   }
9242
9243 end:
9244   if (gamma) {
9245     *gamma = _gamma;
9246   }
9247   if (seqh) {
9248     *seqh = _seqh;
9249   } else if (_seqh) {
9250     gst_buffer_unref (_seqh);
9251   }
9252 }
9253
9254 static gchar *
9255 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9256 {
9257   GNode *dinf;
9258   GstByteReader dref;
9259   gchar *uri = NULL;
9260
9261   /*
9262    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9263    * atom that might contain a 'data' atom with the rtsp uri.
9264    * This case was reported in bug #597497, some info about
9265    * the hndl atom can be found in TN1195
9266    */
9267   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9268   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9269
9270   if (dinf) {
9271     guint32 dref_num_entries = 0;
9272     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9273         gst_byte_reader_skip (&dref, 4) &&
9274         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9275       gint i;
9276
9277       /* search dref entries for hndl atom */
9278       for (i = 0; i < dref_num_entries; i++) {
9279         guint32 size = 0, type;
9280         guint8 string_len = 0;
9281         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9282             qt_atom_parser_get_fourcc (&dref, &type)) {
9283           if (type == FOURCC_hndl) {
9284             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9285
9286             /* skip data reference handle bytes and the
9287              * following pascal string and some extra 4
9288              * bytes I have no idea what are */
9289             if (!gst_byte_reader_skip (&dref, 4) ||
9290                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9291                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9292               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9293               break;
9294             }
9295
9296             /* iterate over the atoms to find the data atom */
9297             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9298               guint32 atom_size;
9299               guint32 atom_type;
9300
9301               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9302                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9303                 if (atom_type == FOURCC_data) {
9304                   const guint8 *uri_aux = NULL;
9305
9306                   /* found the data atom that might contain the rtsp uri */
9307                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9308                       "hndl atom, interpreting it as an URI");
9309                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9310                           &uri_aux)) {
9311                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9312                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9313                     else
9314                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9315                           "didn't contain a rtsp address");
9316                   } else {
9317                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9318                         "atom contents");
9319                   }
9320                   break;
9321                 }
9322                 /* skipping to the next entry */
9323                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9324                   break;
9325               } else {
9326                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9327                     "atom header");
9328                 break;
9329               }
9330             }
9331             break;
9332           }
9333           /* skip to the next entry */
9334           if (!gst_byte_reader_skip (&dref, size - 8))
9335             break;
9336         } else {
9337           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9338         }
9339       }
9340       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9341     }
9342   }
9343   return uri;
9344 }
9345
9346 #define AMR_NB_ALL_MODES        0x81ff
9347 #define AMR_WB_ALL_MODES        0x83ff
9348 static guint
9349 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9350 {
9351   /* The 'damr' atom is of the form:
9352    *
9353    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9354    *    32 b       8 b          16 b           8 b                 8 b
9355    *
9356    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9357    * represents the highest mode used in the stream (and thus the maximum
9358    * bitrate), with a couple of special cases as seen below.
9359    */
9360
9361   /* Map of frame type ID -> bitrate */
9362   static const guint nb_bitrates[] = {
9363     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9364   };
9365   static const guint wb_bitrates[] = {
9366     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9367   };
9368   GstMapInfo map;
9369   gsize max_mode;
9370   guint16 mode_set;
9371
9372   gst_buffer_map (buf, &map, GST_MAP_READ);
9373
9374   if (map.size != 0x11) {
9375     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9376     goto bad_data;
9377   }
9378
9379   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9380     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9381         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9382     goto bad_data;
9383   }
9384
9385   mode_set = QT_UINT16 (map.data + 13);
9386
9387   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9388     max_mode = 7 + (wb ? 1 : 0);
9389   else
9390     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9391     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9392
9393   if (max_mode == -1) {
9394     GST_DEBUG ("No mode indication was found (mode set) = %x",
9395         (guint) mode_set);
9396     goto bad_data;
9397   }
9398
9399   gst_buffer_unmap (buf, &map);
9400   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9401
9402 bad_data:
9403   gst_buffer_unmap (buf, &map);
9404   return 0;
9405 }
9406
9407 static gboolean
9408 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9409     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9410 {
9411   /*
9412    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9413    * [0 1 2]
9414    * [3 4 5]
9415    * [6 7 8]
9416    */
9417
9418   if (gst_byte_reader_get_remaining (reader) < 36)
9419     return FALSE;
9420
9421   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9422   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9423   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9424   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9425   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9426   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9427   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9428   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9429   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9430
9431   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9432   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9433       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9434       matrix[2] & 0xFF);
9435   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9436       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9437       matrix[5] & 0xFF);
9438   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9439       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9440       matrix[8] & 0xFF);
9441
9442   return TRUE;
9443 }
9444
9445 static void
9446 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9447     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9448 {
9449
9450 /* [a b c]
9451  * [d e f]
9452  * [g h i]
9453  *
9454  * This macro will only compare value abdegh, it expects cfi to have already
9455  * been checked
9456  */
9457 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9458                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9459
9460   /* only handle the cases where the last column has standard values */
9461   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9462     const gchar *rotation_tag = NULL;
9463
9464     /* no rotation needed */
9465     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9466       /* NOP */
9467     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9468       rotation_tag = "rotate-90";
9469     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9470       rotation_tag = "rotate-180";
9471     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9472       rotation_tag = "rotate-270";
9473     } else {
9474       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9475     }
9476
9477     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9478         rotation_tag);
9479     if (rotation_tag != NULL) {
9480       if (*taglist == NULL)
9481         *taglist = gst_tag_list_new_empty ();
9482       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9483           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9484     }
9485   } else {
9486     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9487   }
9488 }
9489
9490 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9491  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9492  * Common Encryption (cenc), the function will also parse the tenc box (defined
9493  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9494  * (typically an enc[v|a|t|s] sample entry); the function will set
9495  * @original_fmt to the fourcc of the original unencrypted stream format.
9496  * Returns TRUE if successful; FALSE otherwise. */
9497 static gboolean
9498 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9499     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9500 {
9501   GNode *sinf;
9502   GNode *frma;
9503   GNode *schm;
9504   GNode *schi;
9505
9506   g_return_val_if_fail (qtdemux != NULL, FALSE);
9507   g_return_val_if_fail (stream != NULL, FALSE);
9508   g_return_val_if_fail (container != NULL, FALSE);
9509   g_return_val_if_fail (original_fmt != NULL, FALSE);
9510
9511   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9512   if (G_UNLIKELY (!sinf)) {
9513     if (stream->protection_scheme_type == FOURCC_cenc) {
9514       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9515           "mandatory for Common Encryption");
9516       return FALSE;
9517     }
9518     return TRUE;
9519   }
9520
9521   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9522   if (G_UNLIKELY (!frma)) {
9523     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9524     return FALSE;
9525   }
9526
9527   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9528   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9529       GST_FOURCC_ARGS (*original_fmt));
9530
9531   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9532   if (!schm) {
9533     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9534     return FALSE;
9535   }
9536   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9537   stream->protection_scheme_version =
9538       QT_UINT32 ((const guint8 *) schm->data + 16);
9539
9540   GST_DEBUG_OBJECT (qtdemux,
9541       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9542       "protection_scheme_version: %#010x",
9543       GST_FOURCC_ARGS (stream->protection_scheme_type),
9544       stream->protection_scheme_version);
9545
9546   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9547   if (!schi) {
9548     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9549     return FALSE;
9550   }
9551   if (stream->protection_scheme_type == FOURCC_cenc) {
9552     QtDemuxCencSampleSetInfo *info;
9553     GNode *tenc;
9554     const guint8 *tenc_data;
9555     guint32 isEncrypted;
9556     guint8 iv_size;
9557     const guint8 *default_kid;
9558     GstBuffer *kid_buf;
9559
9560     if (G_UNLIKELY (!stream->protection_scheme_info))
9561       stream->protection_scheme_info =
9562           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9563
9564     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9565
9566     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9567     if (!tenc) {
9568       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9569           "which is mandatory for Common Encryption");
9570       return FALSE;
9571     }
9572     tenc_data = (const guint8 *) tenc->data + 12;
9573     isEncrypted = QT_UINT24 (tenc_data);
9574     iv_size = QT_UINT8 (tenc_data + 3);
9575     default_kid = (tenc_data + 4);
9576     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9577     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9578     if (info->default_properties)
9579       gst_structure_free (info->default_properties);
9580     info->default_properties =
9581         gst_structure_new ("application/x-cenc",
9582         "iv_size", G_TYPE_UINT, iv_size,
9583         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9584         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9585     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9586         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9587     gst_buffer_unref (kid_buf);
9588   }
9589   return TRUE;
9590 }
9591
9592 /* parse the traks.
9593  * With each track we associate a new QtDemuxStream that contains all the info
9594  * about the trak.
9595  * traks that do not decode to something (like strm traks) will not have a pad.
9596  */
9597 static gboolean
9598 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9599 {
9600   GstByteReader tkhd;
9601   int offset;
9602   GNode *mdia;
9603   GNode *mdhd;
9604   GNode *hdlr;
9605   GNode *minf;
9606   GNode *stbl;
9607   GNode *stsd;
9608   GNode *mp4a;
9609   GNode *mp4v;
9610   GNode *wave;
9611   GNode *esds;
9612   GNode *pasp;
9613   GNode *colr;
9614   GNode *tref;
9615   GNode *udta;
9616   GNode *svmi;
9617   GNode *fiel;
9618
9619   QtDemuxStream *stream = NULL;
9620   gboolean new_stream = FALSE;
9621   gchar *codec = NULL;
9622   const guint8 *stsd_data;
9623   const guint8 *stsd_entry_data;
9624   guint remaining_stsd_len;
9625   guint stsd_entry_count;
9626   guint stsd_index;
9627   guint16 lang_code;            /* quicktime lang code or packed iso code */
9628   guint32 version;
9629   guint32 tkhd_flags = 0;
9630   guint8 tkhd_version = 0;
9631   guint32 w = 0, h = 0;
9632   guint32 fourcc;
9633   guint value_size, stsd_len, len;
9634   guint32 track_id;
9635   guint32 dummy;
9636
9637   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9638
9639   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9640       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9641       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9642     goto corrupt_file;
9643
9644   /* pick between 64 or 32 bits */
9645   value_size = tkhd_version == 1 ? 8 : 4;
9646   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9647       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9648     goto corrupt_file;
9649
9650   if (!qtdemux->got_moov) {
9651     if (qtdemux_find_stream (qtdemux, track_id))
9652       goto existing_stream;
9653     stream = _create_stream ();
9654     stream->track_id = track_id;
9655     new_stream = TRUE;
9656   } else {
9657     stream = qtdemux_find_stream (qtdemux, track_id);
9658     if (!stream) {
9659       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9660       goto skip_track;
9661     }
9662
9663     /* reset reused stream */
9664     gst_qtdemux_stream_reset (qtdemux, stream);
9665   }
9666   /* need defaults for fragments */
9667   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9668
9669   if ((tkhd_flags & 1) == 0)
9670     stream->disabled = TRUE;
9671
9672   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9673       tkhd_version, tkhd_flags, stream->track_id);
9674
9675   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9676     goto corrupt_file;
9677
9678   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9679     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9680     if (qtdemux->major_brand != FOURCC_mjp2 ||
9681         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9682       goto corrupt_file;
9683   }
9684
9685   len = QT_UINT32 ((guint8 *) mdhd->data);
9686   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9687   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9688   if (version == 0x01000000) {
9689     if (len < 38)
9690       goto corrupt_file;
9691     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9692     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9693     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9694   } else {
9695     if (len < 30)
9696       goto corrupt_file;
9697     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9698     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9699     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9700   }
9701
9702   if (lang_code < 0x400) {
9703     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9704   } else if (lang_code == 0x7fff) {
9705     stream->lang_id[0] = 0;     /* unspecified */
9706   } else {
9707     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9708     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9709     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9710     stream->lang_id[3] = 0;
9711   }
9712
9713   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9714       stream->timescale);
9715   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9716       stream->duration);
9717   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9718       lang_code, stream->lang_id);
9719
9720   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9721     goto corrupt_file;
9722
9723   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9724     /* chapters track reference */
9725     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9726     if (chap) {
9727       gsize length = GST_READ_UINT32_BE (chap->data);
9728       if (qtdemux->chapters_track_id)
9729         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9730
9731       if (length >= 12) {
9732         qtdemux->chapters_track_id =
9733             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9734       }
9735     }
9736   }
9737
9738   /* fragmented files may have bogus duration in moov */
9739   if (!qtdemux->fragmented &&
9740       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9741     guint64 tdur1, tdur2;
9742
9743     /* don't overflow */
9744     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9745     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9746
9747     /* HACK:
9748      * some of those trailers, nowadays, have prologue images that are
9749      * themselves video tracks as well. I haven't really found a way to
9750      * identify those yet, except for just looking at their duration. */
9751     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9752       GST_WARNING_OBJECT (qtdemux,
9753           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9754           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9755           "found, assuming preview image or something; skipping track",
9756           stream->duration, stream->timescale, qtdemux->duration,
9757           qtdemux->timescale);
9758       if (new_stream)
9759         gst_qtdemux_stream_free (qtdemux, stream);
9760       return TRUE;
9761     }
9762   }
9763
9764   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9765     goto corrupt_file;
9766
9767   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9768       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9769
9770   len = QT_UINT32 ((guint8 *) hdlr->data);
9771   if (len >= 20)
9772     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9773   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9774       GST_FOURCC_ARGS (stream->subtype));
9775
9776   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9777     goto corrupt_file;
9778
9779   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9780     goto corrupt_file;
9781
9782   /*parse svmi header if existing */
9783   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9784   if (svmi) {
9785     len = QT_UINT32 ((guint8 *) svmi->data);
9786     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9787     if (!version) {
9788       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9789       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9790       guint8 frame_type, frame_layout;
9791
9792       /* MPEG-A stereo video */
9793       if (qtdemux->major_brand == FOURCC_ss02)
9794         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9795
9796       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9797       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9798       switch (frame_type) {
9799         case 0:
9800           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9801           break;
9802         case 1:
9803           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9804           break;
9805         case 2:
9806           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9807           break;
9808         case 3:
9809           /* mode 3 is primary/secondary view sequence, ie
9810            * left/right views in separate tracks. See section 7.2
9811            * of ISO/IEC 23000-11:2009 */
9812           GST_FIXME_OBJECT (qtdemux,
9813               "Implement stereo video in separate streams");
9814       }
9815
9816       if ((frame_layout & 0x1) == 0)
9817         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9818
9819       GST_LOG_OBJECT (qtdemux,
9820           "StereoVideo: composition type: %u, is_left_first: %u",
9821           frame_type, frame_layout);
9822       stream->multiview_mode = mode;
9823       stream->multiview_flags = flags;
9824     }
9825   }
9826
9827   /* parse rest of tkhd */
9828   if (stream->subtype == FOURCC_vide) {
9829     guint32 matrix[9];
9830
9831     /* version 1 uses some 64-bit ints */
9832     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9833       goto corrupt_file;
9834
9835     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9836       goto corrupt_file;
9837
9838     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9839         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9840       goto corrupt_file;
9841
9842     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9843         &stream->stream_tags);
9844   }
9845
9846   /* parse stsd */
9847   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9848     goto corrupt_file;
9849   stsd_data = (const guint8 *) stsd->data;
9850
9851   /* stsd should at least have one entry */
9852   stsd_len = QT_UINT32 (stsd_data);
9853   if (stsd_len < 24) {
9854     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9855     if (stream->subtype == FOURCC_vivo) {
9856       if (new_stream)
9857         gst_qtdemux_stream_free (qtdemux, stream);
9858       return TRUE;
9859     } else {
9860       goto corrupt_file;
9861     }
9862   }
9863
9864   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9865   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9866   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9867   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9868
9869   stsd_entry_data = stsd_data + 16;
9870   remaining_stsd_len = stsd_len - 16;
9871   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9872     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9873
9874     /* and that entry should fit within stsd */
9875     len = QT_UINT32 (stsd_entry_data);
9876     if (len > remaining_stsd_len)
9877       goto corrupt_file;
9878
9879     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9880     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9881         GST_FOURCC_ARGS (entry->fourcc));
9882     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9883
9884     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9885       goto error_encrypted;
9886
9887     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9888       /* FIXME this looks wrong, there might be multiple children
9889        * with the same type */
9890       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9891       stream->protected = TRUE;
9892       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9893         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9894     }
9895
9896     if (stream->subtype == FOURCC_vide) {
9897       gboolean gray;
9898       gint depth, palette_size, palette_count;
9899       guint32 *palette_data = NULL;
9900
9901       entry->sampled = TRUE;
9902
9903       stream->display_width = w >> 16;
9904       stream->display_height = h >> 16;
9905
9906       offset = 16;
9907       if (len < 86)             /* TODO verify */
9908         goto corrupt_file;
9909
9910       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
9911       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
9912       entry->fps_n = 0;         /* this is filled in later */
9913       entry->fps_d = 0;         /* this is filled in later */
9914       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
9915       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
9916
9917       /* if color_table_id is 0, ctab atom must follow; however some files
9918        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9919        * if color table is not present we'll correct the value */
9920       if (entry->color_table_id == 0 &&
9921           (len < 90
9922               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
9923         entry->color_table_id = -1;
9924       }
9925
9926       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9927           entry->width, entry->height, entry->bits_per_sample,
9928           entry->color_table_id);
9929
9930       depth = entry->bits_per_sample;
9931
9932       /* more than 32 bits means grayscale */
9933       gray = (depth > 32);
9934       /* low 32 bits specify the depth  */
9935       depth &= 0x1F;
9936
9937       /* different number of palette entries is determined by depth. */
9938       palette_count = 0;
9939       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9940         palette_count = (1 << depth);
9941       palette_size = palette_count * 4;
9942
9943       if (entry->color_table_id) {
9944         switch (palette_count) {
9945           case 0:
9946             break;
9947           case 2:
9948             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9949             break;
9950           case 4:
9951             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9952             break;
9953           case 16:
9954             if (gray)
9955               palette_data =
9956                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
9957             else
9958               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9959             break;
9960           case 256:
9961             if (gray)
9962               palette_data =
9963                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
9964             else
9965               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9966             break;
9967           default:
9968             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9969                 (_("The video in this file might not play correctly.")),
9970                 ("unsupported palette depth %d", depth));
9971             break;
9972         }
9973       } else {
9974         gint i, j, start, end;
9975
9976         if (len < 94)
9977           goto corrupt_file;
9978
9979         /* read table */
9980         start = QT_UINT32 (stsd_entry_data + offset + 70);
9981         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
9982         end = QT_UINT16 (stsd_entry_data + offset + 76);
9983
9984         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9985             start, end, palette_count);
9986
9987         if (end > 255)
9988           end = 255;
9989         if (start > end)
9990           start = end;
9991
9992         if (len < 94 + (end - start) * 8)
9993           goto corrupt_file;
9994
9995         /* palette is always the same size */
9996         palette_data = g_malloc0 (256 * 4);
9997         palette_size = 256 * 4;
9998
9999         for (j = 0, i = start; i <= end; j++, i++) {
10000           guint32 a, r, g, b;
10001
10002           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10003           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10004           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10005           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10006
10007           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10008               (g & 0xff00) | (b >> 8);
10009         }
10010       }
10011
10012       if (entry->caps)
10013         gst_caps_unref (entry->caps);
10014
10015       entry->caps =
10016           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10017           &codec);
10018       if (G_UNLIKELY (!entry->caps)) {
10019         g_free (palette_data);
10020         goto unknown_stream;
10021       }
10022
10023       if (codec) {
10024         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10025             GST_TAG_VIDEO_CODEC, codec, NULL);
10026         g_free (codec);
10027         codec = NULL;
10028       }
10029
10030       if (palette_data) {
10031         GstStructure *s;
10032
10033         if (entry->rgb8_palette)
10034           gst_memory_unref (entry->rgb8_palette);
10035         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10036             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10037
10038         s = gst_caps_get_structure (entry->caps, 0);
10039
10040         /* non-raw video has a palette_data property. raw video has the palette as
10041          * an extra plane that we append to the output buffers before we push
10042          * them*/
10043         if (!gst_structure_has_name (s, "video/x-raw")) {
10044           GstBuffer *palette;
10045
10046           palette = gst_buffer_new ();
10047           gst_buffer_append_memory (palette, entry->rgb8_palette);
10048           entry->rgb8_palette = NULL;
10049
10050           gst_caps_set_simple (entry->caps, "palette_data",
10051               GST_TYPE_BUFFER, palette, NULL);
10052           gst_buffer_unref (palette);
10053         }
10054       } else if (palette_count != 0) {
10055         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10056             (NULL), ("Unsupported palette depth %d", depth));
10057       }
10058
10059       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10060           QT_UINT16 (stsd_entry_data + offset + 32));
10061
10062       esds = NULL;
10063       pasp = NULL;
10064       colr = NULL;
10065       fiel = NULL;
10066       /* pick 'the' stsd child */
10067       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10068       if (!stream->protected) {
10069         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10070           mp4v = NULL;
10071         }
10072       } else {
10073         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10074           mp4v = NULL;
10075         }
10076       }
10077
10078       if (mp4v) {
10079         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10080         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10081         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10082         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10083       }
10084
10085       if (pasp) {
10086         const guint8 *pasp_data = (const guint8 *) pasp->data;
10087         gint len = QT_UINT32 (pasp_data);
10088
10089         if (len == 16) {
10090           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10091           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10092         } else {
10093           CUR_STREAM (stream)->par_w = 0;
10094           CUR_STREAM (stream)->par_h = 0;
10095         }
10096       } else {
10097         CUR_STREAM (stream)->par_w = 0;
10098         CUR_STREAM (stream)->par_h = 0;
10099       }
10100
10101       if (fiel) {
10102         const guint8 *fiel_data = (const guint8 *) fiel->data;
10103         gint len = QT_UINT32 (fiel_data);
10104
10105         if (len == 10) {
10106           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10107           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10108         }
10109       }
10110
10111       if (colr) {
10112         const guint8 *colr_data = (const guint8 *) colr->data;
10113         gint len = QT_UINT32 (colr_data);
10114
10115         if (len == 19 || len == 18) {
10116           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10117
10118           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10119             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10120             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10121             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10122             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10123
10124             switch (primaries) {
10125               case 1:
10126                 CUR_STREAM (stream)->colorimetry.primaries =
10127                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10128                 break;
10129               case 5:
10130                 CUR_STREAM (stream)->colorimetry.primaries =
10131                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10132                 break;
10133               case 6:
10134                 CUR_STREAM (stream)->colorimetry.primaries =
10135                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10136                 break;
10137               case 9:
10138                 CUR_STREAM (stream)->colorimetry.primaries =
10139                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10140                 break;
10141               default:
10142                 break;
10143             }
10144
10145             switch (transfer_function) {
10146               case 1:
10147                 CUR_STREAM (stream)->colorimetry.transfer =
10148                     GST_VIDEO_TRANSFER_BT709;
10149                 break;
10150               case 7:
10151                 CUR_STREAM (stream)->colorimetry.transfer =
10152                     GST_VIDEO_TRANSFER_SMPTE240M;
10153                 break;
10154               default:
10155                 break;
10156             }
10157
10158             switch (matrix) {
10159               case 1:
10160                 CUR_STREAM (stream)->colorimetry.matrix =
10161                     GST_VIDEO_COLOR_MATRIX_BT709;
10162                 break;
10163               case 6:
10164                 CUR_STREAM (stream)->colorimetry.matrix =
10165                     GST_VIDEO_COLOR_MATRIX_BT601;
10166                 break;
10167               case 7:
10168                 CUR_STREAM (stream)->colorimetry.matrix =
10169                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10170                 break;
10171               case 9:
10172                 CUR_STREAM (stream)->colorimetry.matrix =
10173                     GST_VIDEO_COLOR_MATRIX_BT2020;
10174                 break;
10175               default:
10176                 break;
10177             }
10178
10179             CUR_STREAM (stream)->colorimetry.range =
10180                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10181                 GST_VIDEO_COLOR_RANGE_16_235;
10182           } else {
10183             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10184           }
10185         } else {
10186           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10187         }
10188       }
10189
10190       if (esds) {
10191         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10192             stream->stream_tags);
10193       } else {
10194         switch (fourcc) {
10195           case FOURCC_H264:
10196           case FOURCC_avc1:
10197           case FOURCC_avc3:
10198           {
10199             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10200             const guint8 *avc_data = stsd_entry_data + 0x56;
10201
10202             /* find avcC */
10203             while (len >= 0x8) {
10204               gint size;
10205
10206               if (QT_UINT32 (avc_data) <= len)
10207                 size = QT_UINT32 (avc_data) - 0x8;
10208               else
10209                 size = len - 0x8;
10210
10211               if (size < 1)
10212                 /* No real data, so break out */
10213                 break;
10214
10215               switch (QT_FOURCC (avc_data + 0x4)) {
10216                 case FOURCC_avcC:
10217                 {
10218                   /* parse, if found */
10219                   GstBuffer *buf;
10220
10221                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10222
10223                   /* First 4 bytes are the length of the atom, the next 4 bytes
10224                    * are the fourcc, the next 1 byte is the version, and the
10225                    * subsequent bytes are profile_tier_level structure like data. */
10226                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10227                       avc_data + 8 + 1, size - 1);
10228                   buf = gst_buffer_new_and_alloc (size);
10229                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10230                   gst_caps_set_simple (entry->caps,
10231                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10232                   gst_buffer_unref (buf);
10233
10234                   break;
10235                 }
10236                 case FOURCC_strf:
10237                 {
10238                   GstBuffer *buf;
10239
10240                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10241
10242                   /* First 4 bytes are the length of the atom, the next 4 bytes
10243                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10244                    * next 1 byte is the version, and the
10245                    * subsequent bytes are sequence parameter set like data. */
10246
10247                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10248                   if (size > 1) {
10249                     gst_codec_utils_h264_caps_set_level_and_profile
10250                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10251
10252                     buf = gst_buffer_new_and_alloc (size);
10253                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10254                     gst_caps_set_simple (entry->caps,
10255                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10256                     gst_buffer_unref (buf);
10257                   }
10258                   break;
10259                 }
10260                 case FOURCC_btrt:
10261                 {
10262                   guint avg_bitrate, max_bitrate;
10263
10264                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10265                   if (size < 12)
10266                     break;
10267
10268                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10269                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10270
10271                   if (!max_bitrate && !avg_bitrate)
10272                     break;
10273
10274                   /* Some muxers seem to swap the average and maximum bitrates
10275                    * (I'm looking at you, YouTube), so we swap for sanity. */
10276                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10277                     guint temp = avg_bitrate;
10278
10279                     avg_bitrate = max_bitrate;
10280                     max_bitrate = temp;
10281                   }
10282
10283                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10284                     gst_tag_list_add (stream->stream_tags,
10285                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10286                         max_bitrate, NULL);
10287                   }
10288                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10289                     gst_tag_list_add (stream->stream_tags,
10290                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10291                         NULL);
10292                   }
10293
10294                   break;
10295                 }
10296
10297                 default:
10298                   break;
10299               }
10300
10301               len -= size + 8;
10302               avc_data += size + 8;
10303             }
10304
10305             break;
10306           }
10307           case FOURCC_H265:
10308           case FOURCC_hvc1:
10309           case FOURCC_hev1:
10310           {
10311             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10312             const guint8 *hevc_data = stsd_entry_data + 0x56;
10313
10314             /* find hevc */
10315             while (len >= 0x8) {
10316               gint size;
10317
10318               if (QT_UINT32 (hevc_data) <= len)
10319                 size = QT_UINT32 (hevc_data) - 0x8;
10320               else
10321                 size = len - 0x8;
10322
10323               if (size < 1)
10324                 /* No real data, so break out */
10325                 break;
10326
10327               switch (QT_FOURCC (hevc_data + 0x4)) {
10328                 case FOURCC_hvcC:
10329                 {
10330                   /* parse, if found */
10331                   GstBuffer *buf;
10332
10333                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10334
10335                   /* First 4 bytes are the length of the atom, the next 4 bytes
10336                    * are the fourcc, the next 1 byte is the version, and the
10337                    * subsequent bytes are sequence parameter set like data. */
10338                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10339                       (entry->caps, hevc_data + 8 + 1, size - 1);
10340
10341                   buf = gst_buffer_new_and_alloc (size);
10342                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10343                   gst_caps_set_simple (entry->caps,
10344                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10345                   gst_buffer_unref (buf);
10346                   break;
10347                 }
10348                 default:
10349                   break;
10350               }
10351               len -= size + 8;
10352               hevc_data += size + 8;
10353             }
10354             break;
10355           }
10356           case FOURCC_mp4v:
10357           case FOURCC_MP4V:
10358           case FOURCC_fmp4:
10359           case FOURCC_FMP4:
10360           case FOURCC_xvid:
10361           case FOURCC_XVID:
10362           {
10363             GNode *glbl;
10364
10365             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10366                 GST_FOURCC_ARGS (fourcc));
10367
10368             /* codec data might be in glbl extension atom */
10369             glbl = mp4v ?
10370                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10371             if (glbl) {
10372               guint8 *data;
10373               GstBuffer *buf;
10374               gint len;
10375
10376               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10377               data = glbl->data;
10378               len = QT_UINT32 (data);
10379               if (len > 0x8) {
10380                 len -= 0x8;
10381                 buf = gst_buffer_new_and_alloc (len);
10382                 gst_buffer_fill (buf, 0, data + 8, len);
10383                 gst_caps_set_simple (entry->caps,
10384                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10385                 gst_buffer_unref (buf);
10386               }
10387             }
10388             break;
10389           }
10390           case FOURCC_mjp2:
10391           {
10392             /* see annex I of the jpeg2000 spec */
10393             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10394             const guint8 *data;
10395             const gchar *colorspace = NULL;
10396             gint ncomp = 0;
10397             guint32 ncomp_map = 0;
10398             gint32 *comp_map = NULL;
10399             guint32 nchan_def = 0;
10400             gint32 *chan_def = NULL;
10401
10402             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10403             /* some required atoms */
10404             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10405             if (!mjp2)
10406               break;
10407             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10408             if (!jp2h)
10409               break;
10410
10411             /* number of components; redundant with info in codestream, but useful
10412                to a muxer */
10413             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10414             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10415               break;
10416             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10417
10418             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10419             if (!colr)
10420               break;
10421             GST_DEBUG_OBJECT (qtdemux, "found colr");
10422             /* extract colour space info */
10423             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10424               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10425                 case 16:
10426                   colorspace = "sRGB";
10427                   break;
10428                 case 17:
10429                   colorspace = "GRAY";
10430                   break;
10431                 case 18:
10432                   colorspace = "sYUV";
10433                   break;
10434                 default:
10435                   colorspace = NULL;
10436                   break;
10437               }
10438             }
10439             if (!colorspace)
10440               /* colr is required, and only values 16, 17, and 18 are specified,
10441                  so error if we have no colorspace */
10442               break;
10443
10444             /* extract component mapping */
10445             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10446             if (cmap) {
10447               guint32 cmap_len = 0;
10448               int i;
10449               cmap_len = QT_UINT32 (cmap->data);
10450               if (cmap_len >= 8) {
10451                 /* normal box, subtract off header */
10452                 cmap_len -= 8;
10453                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10454                 if (cmap_len % 4 == 0) {
10455                   ncomp_map = (cmap_len / 4);
10456                   comp_map = g_new0 (gint32, ncomp_map);
10457                   for (i = 0; i < ncomp_map; i++) {
10458                     guint16 cmp;
10459                     guint8 mtyp, pcol;
10460                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10461                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10462                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10463                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10464                   }
10465                 }
10466               }
10467             }
10468             /* extract channel definitions */
10469             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10470             if (cdef) {
10471               guint32 cdef_len = 0;
10472               int i;
10473               cdef_len = QT_UINT32 (cdef->data);
10474               if (cdef_len >= 10) {
10475                 /* normal box, subtract off header and len */
10476                 cdef_len -= 10;
10477                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10478                 if (cdef_len % 6 == 0) {
10479                   nchan_def = (cdef_len / 6);
10480                   chan_def = g_new0 (gint32, nchan_def);
10481                   for (i = 0; i < nchan_def; i++)
10482                     chan_def[i] = -1;
10483                   for (i = 0; i < nchan_def; i++) {
10484                     guint16 cn, typ, asoc;
10485                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10486                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10487                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10488                     if (cn < nchan_def) {
10489                       switch (typ) {
10490                         case 0:
10491                           chan_def[cn] = asoc;
10492                           break;
10493                         case 1:
10494                           chan_def[cn] = 0;     /* alpha */
10495                           break;
10496                         default:
10497                           chan_def[cn] = -typ;
10498                       }
10499                     }
10500                   }
10501                 }
10502               }
10503             }
10504
10505             gst_caps_set_simple (entry->caps,
10506                 "num-components", G_TYPE_INT, ncomp, NULL);
10507             gst_caps_set_simple (entry->caps,
10508                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10509
10510             if (comp_map) {
10511               GValue arr = { 0, };
10512               GValue elt = { 0, };
10513               int i;
10514               g_value_init (&arr, GST_TYPE_ARRAY);
10515               g_value_init (&elt, G_TYPE_INT);
10516               for (i = 0; i < ncomp_map; i++) {
10517                 g_value_set_int (&elt, comp_map[i]);
10518                 gst_value_array_append_value (&arr, &elt);
10519               }
10520               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10521                   "component-map", &arr);
10522               g_value_unset (&elt);
10523               g_value_unset (&arr);
10524               g_free (comp_map);
10525             }
10526
10527             if (chan_def) {
10528               GValue arr = { 0, };
10529               GValue elt = { 0, };
10530               int i;
10531               g_value_init (&arr, GST_TYPE_ARRAY);
10532               g_value_init (&elt, G_TYPE_INT);
10533               for (i = 0; i < nchan_def; i++) {
10534                 g_value_set_int (&elt, chan_def[i]);
10535                 gst_value_array_append_value (&arr, &elt);
10536               }
10537               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10538                   "channel-definitions", &arr);
10539               g_value_unset (&elt);
10540               g_value_unset (&arr);
10541               g_free (chan_def);
10542             }
10543
10544             /* some optional atoms */
10545             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10546             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10547
10548             /* indicate possible fields in caps */
10549             if (field) {
10550               data = (guint8 *) field->data + 8;
10551               if (*data != 1)
10552                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10553                     (gint) * data, NULL);
10554             }
10555             /* add codec_data if provided */
10556             if (prefix) {
10557               GstBuffer *buf;
10558               gint len;
10559
10560               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10561               data = prefix->data;
10562               len = QT_UINT32 (data);
10563               if (len > 0x8) {
10564                 len -= 0x8;
10565                 buf = gst_buffer_new_and_alloc (len);
10566                 gst_buffer_fill (buf, 0, data + 8, len);
10567                 gst_caps_set_simple (entry->caps,
10568                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10569                 gst_buffer_unref (buf);
10570               }
10571             }
10572             break;
10573           }
10574           case FOURCC_SVQ3:
10575           case FOURCC_VP31:
10576           {
10577             GstBuffer *buf;
10578             GstBuffer *seqh = NULL;
10579             const guint8 *gamma_data = NULL;
10580             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10581
10582             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10583                 &seqh);
10584             if (gamma_data) {
10585               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10586                   QT_FP32 (gamma_data), NULL);
10587             }
10588             if (seqh) {
10589               /* sorry for the bad name, but we don't know what this is, other
10590                * than its own fourcc */
10591               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10592                   NULL);
10593               gst_buffer_unref (seqh);
10594             }
10595
10596             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10597             buf = gst_buffer_new_and_alloc (len);
10598             gst_buffer_fill (buf, 0, stsd_data, len);
10599             gst_caps_set_simple (entry->caps,
10600                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10601             gst_buffer_unref (buf);
10602             break;
10603           }
10604           case FOURCC_jpeg:
10605           {
10606             /* https://developer.apple.com/standards/qtff-2001.pdf,
10607              * page 92, "Video Sample Description", under table 3.1 */
10608             GstByteReader br;
10609
10610             const gint compressor_offset =
10611                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10612             const gint min_size = compressor_offset + 32 + 2 + 2;
10613             GNode *jpeg;
10614             guint32 len;
10615             guint16 color_table_id = 0;
10616             gboolean ok;
10617
10618             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10619
10620             /* recover information on interlaced/progressive */
10621             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10622             if (!jpeg)
10623               break;
10624
10625             len = QT_UINT32 (jpeg->data);
10626             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10627                 min_size);
10628             if (len >= min_size) {
10629               gst_byte_reader_init (&br, jpeg->data, len);
10630
10631               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10632               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10633               if (color_table_id != 0) {
10634                 /* the spec says there can be concatenated chunks in the data, and we want
10635                  * to find one called field. Walk through them. */
10636                 gint offset = min_size;
10637                 while (offset + 8 < len) {
10638                   guint32 size = 0, tag;
10639                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10640                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10641                   if (!ok || size < 8) {
10642                     GST_WARNING_OBJECT (qtdemux,
10643                         "Failed to walk optional chunk list");
10644                     break;
10645                   }
10646                   GST_DEBUG_OBJECT (qtdemux,
10647                       "Found optional %4.4s chunk, size %u",
10648                       (const char *) &tag, size);
10649                   if (tag == FOURCC_fiel) {
10650                     guint8 n_fields = 0, ordering = 0;
10651                     gst_byte_reader_get_uint8 (&br, &n_fields);
10652                     gst_byte_reader_get_uint8 (&br, &ordering);
10653                     if (n_fields == 1 || n_fields == 2) {
10654                       GST_DEBUG_OBJECT (qtdemux,
10655                           "Found fiel tag with %u fields, ordering %u",
10656                           n_fields, ordering);
10657                       if (n_fields == 2)
10658                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10659                             "interlace-mode", G_TYPE_STRING, "interleaved",
10660                             NULL);
10661                     } else {
10662                       GST_WARNING_OBJECT (qtdemux,
10663                           "Found fiel tag with invalid fields (%u)", n_fields);
10664                     }
10665                   }
10666                   offset += size;
10667                 }
10668               } else {
10669                 GST_DEBUG_OBJECT (qtdemux,
10670                     "Color table ID is 0, not trying to get interlacedness");
10671               }
10672             } else {
10673               GST_WARNING_OBJECT (qtdemux,
10674                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10675             }
10676
10677             break;
10678           }
10679           case FOURCC_rle_:
10680           case FOURCC_WRLE:
10681           {
10682             gst_caps_set_simple (entry->caps,
10683                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
10684                 NULL);
10685             break;
10686           }
10687           case FOURCC_XiTh:
10688           {
10689             GNode *xith, *xdxt;
10690
10691             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10692             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10693             if (!xith)
10694               break;
10695
10696             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10697             if (!xdxt)
10698               break;
10699
10700             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10701             /* collect the headers and store them in a stream list so that we can
10702              * send them out first */
10703             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10704             break;
10705           }
10706           case FOURCC_ovc1:
10707           {
10708             GNode *ovc1;
10709             guint8 *ovc1_data;
10710             guint ovc1_len;
10711             GstBuffer *buf;
10712
10713             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10714             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10715             if (!ovc1)
10716               break;
10717             ovc1_data = ovc1->data;
10718             ovc1_len = QT_UINT32 (ovc1_data);
10719             if (ovc1_len <= 198) {
10720               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10721               break;
10722             }
10723             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10724             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10725             gst_caps_set_simple (entry->caps,
10726                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10727             gst_buffer_unref (buf);
10728             break;
10729           }
10730           case FOURCC_vc_1:
10731           {
10732             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10733             const guint8 *vc1_data = stsd_entry_data + 0x56;
10734
10735             /* find dvc1 */
10736             while (len >= 8) {
10737               gint size;
10738
10739               if (QT_UINT32 (vc1_data) <= len)
10740                 size = QT_UINT32 (vc1_data) - 8;
10741               else
10742                 size = len - 8;
10743
10744               if (size < 1)
10745                 /* No real data, so break out */
10746                 break;
10747
10748               switch (QT_FOURCC (vc1_data + 0x4)) {
10749                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10750                 {
10751                   GstBuffer *buf;
10752
10753                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10754                   buf = gst_buffer_new_and_alloc (size);
10755                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10756                   gst_caps_set_simple (entry->caps,
10757                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10758                   gst_buffer_unref (buf);
10759                   break;
10760                 }
10761                 default:
10762                   break;
10763               }
10764               len -= size + 8;
10765               vc1_data += size + 8;
10766             }
10767             break;
10768           }
10769           default:
10770             break;
10771         }
10772       }
10773
10774       GST_INFO_OBJECT (qtdemux,
10775           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10776           GST_FOURCC_ARGS (fourcc), entry->caps);
10777
10778     } else if (stream->subtype == FOURCC_soun) {
10779       int version, samplesize;
10780       guint16 compression_id;
10781       gboolean amrwb = FALSE;
10782
10783       offset = 16;
10784       /* sample description entry (16) + sound sample description v0 (20) */
10785       if (len < 36)
10786         goto corrupt_file;
10787
10788       version = QT_UINT32 (stsd_entry_data + offset);
10789       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10790       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10791       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10792       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10793
10794       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10795       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10796           QT_UINT32 (stsd_entry_data + offset + 4));
10797       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10798       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10799       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10800       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10801           QT_UINT16 (stsd_entry_data + offset + 14));
10802       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10803
10804       if (compression_id == 0xfffe)
10805         entry->sampled = TRUE;
10806
10807       /* first assume uncompressed audio */
10808       entry->bytes_per_sample = samplesize / 8;
10809       entry->samples_per_frame = entry->n_channels;
10810       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10811       entry->samples_per_packet = entry->samples_per_frame;
10812       entry->bytes_per_packet = entry->bytes_per_sample;
10813
10814       offset = 36;
10815       switch (fourcc) {
10816           /* Yes, these have to be hard-coded */
10817         case FOURCC_MAC6:
10818         {
10819           entry->samples_per_packet = 6;
10820           entry->bytes_per_packet = 1;
10821           entry->bytes_per_frame = 1 * entry->n_channels;
10822           entry->bytes_per_sample = 1;
10823           entry->samples_per_frame = 6 * entry->n_channels;
10824           break;
10825         }
10826         case FOURCC_MAC3:
10827         {
10828           entry->samples_per_packet = 3;
10829           entry->bytes_per_packet = 1;
10830           entry->bytes_per_frame = 1 * entry->n_channels;
10831           entry->bytes_per_sample = 1;
10832           entry->samples_per_frame = 3 * entry->n_channels;
10833           break;
10834         }
10835         case FOURCC_ima4:
10836         {
10837           entry->samples_per_packet = 64;
10838           entry->bytes_per_packet = 34;
10839           entry->bytes_per_frame = 34 * entry->n_channels;
10840           entry->bytes_per_sample = 2;
10841           entry->samples_per_frame = 64 * entry->n_channels;
10842           break;
10843         }
10844         case FOURCC_ulaw:
10845         case FOURCC_alaw:
10846         {
10847           entry->samples_per_packet = 1;
10848           entry->bytes_per_packet = 1;
10849           entry->bytes_per_frame = 1 * entry->n_channels;
10850           entry->bytes_per_sample = 1;
10851           entry->samples_per_frame = 1 * entry->n_channels;
10852           break;
10853         }
10854         case FOURCC_agsm:
10855         {
10856           entry->samples_per_packet = 160;
10857           entry->bytes_per_packet = 33;
10858           entry->bytes_per_frame = 33 * entry->n_channels;
10859           entry->bytes_per_sample = 2;
10860           entry->samples_per_frame = 160 * entry->n_channels;
10861           break;
10862         }
10863         default:
10864           break;
10865       }
10866
10867       if (version == 0x00010000) {
10868         /* sample description entry (16) + sound sample description v1 (20+16) */
10869         if (len < 52)
10870           goto corrupt_file;
10871
10872         switch (fourcc) {
10873           case FOURCC_twos:
10874           case FOURCC_sowt:
10875           case FOURCC_raw_:
10876           case FOURCC_lpcm:
10877             break;
10878           default:
10879           {
10880             /* only parse extra decoding config for non-pcm audio */
10881             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10882             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10883             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10884             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10885
10886             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10887                 entry->samples_per_packet);
10888             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10889                 entry->bytes_per_packet);
10890             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10891                 entry->bytes_per_frame);
10892             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10893                 entry->bytes_per_sample);
10894
10895             if (!entry->sampled && entry->bytes_per_packet) {
10896               entry->samples_per_frame = (entry->bytes_per_frame /
10897                   entry->bytes_per_packet) * entry->samples_per_packet;
10898               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10899                   entry->samples_per_frame);
10900             }
10901             break;
10902           }
10903         }
10904       } else if (version == 0x00020000) {
10905         union
10906         {
10907           gdouble fp;
10908           guint64 val;
10909         } qtfp;
10910
10911         /* sample description entry (16) + sound sample description v2 (56) */
10912         if (len < 72)
10913           goto corrupt_file;
10914
10915         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
10916         entry->rate = qtfp.fp;
10917         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
10918
10919         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10920         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
10921         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
10922         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10923             QT_UINT32 (stsd_entry_data + offset + 20));
10924         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10925             QT_UINT32 (stsd_entry_data + offset + 24));
10926         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10927             QT_UINT32 (stsd_entry_data + offset + 28));
10928         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10929             QT_UINT32 (stsd_entry_data + offset + 32));
10930       } else if (version != 0x00000) {
10931         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
10932             version);
10933       }
10934
10935       if (entry->caps)
10936         gst_caps_unref (entry->caps);
10937
10938       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
10939           stsd_entry_data + 32, len - 16, &codec);
10940
10941       switch (fourcc) {
10942         case FOURCC_in24:
10943         {
10944           GNode *enda;
10945           GNode *in24;
10946
10947           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10948
10949           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10950           if (!enda) {
10951             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10952             if (wave)
10953               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10954           }
10955           if (enda) {
10956             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10957             gst_caps_set_simple (entry->caps,
10958                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
10959                 NULL);
10960           }
10961           break;
10962         }
10963         case FOURCC_owma:
10964         {
10965           const guint8 *owma_data;
10966           const gchar *codec_name = NULL;
10967           guint owma_len;
10968           GstBuffer *buf;
10969           gint version = 1;
10970           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10971           /* FIXME this should also be gst_riff_strf_auds,
10972            * but the latter one is actually missing bits-per-sample :( */
10973           typedef struct
10974           {
10975             gint16 wFormatTag;
10976             gint16 nChannels;
10977             gint32 nSamplesPerSec;
10978             gint32 nAvgBytesPerSec;
10979             gint16 nBlockAlign;
10980             gint16 wBitsPerSample;
10981             gint16 cbSize;
10982           } WAVEFORMATEX;
10983           WAVEFORMATEX *wfex;
10984
10985           GST_DEBUG_OBJECT (qtdemux, "parse owma");
10986           owma_data = stsd_entry_data;
10987           owma_len = QT_UINT32 (owma_data);
10988           if (owma_len <= 54) {
10989             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10990             break;
10991           }
10992           wfex = (WAVEFORMATEX *) (owma_data + 36);
10993           buf = gst_buffer_new_and_alloc (owma_len - 54);
10994           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10995           if (wfex->wFormatTag == 0x0161) {
10996             codec_name = "Windows Media Audio";
10997             version = 2;
10998           } else if (wfex->wFormatTag == 0x0162) {
10999             codec_name = "Windows Media Audio 9 Pro";
11000             version = 3;
11001           } else if (wfex->wFormatTag == 0x0163) {
11002             codec_name = "Windows Media Audio 9 Lossless";
11003             /* is that correct? gstffmpegcodecmap.c is missing it, but
11004              * fluendo codec seems to support it */
11005             version = 4;
11006           }
11007
11008           gst_caps_set_simple (entry->caps,
11009               "codec_data", GST_TYPE_BUFFER, buf,
11010               "wmaversion", G_TYPE_INT, version,
11011               "block_align", G_TYPE_INT,
11012               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11013               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11014               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11015               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11016           gst_buffer_unref (buf);
11017
11018           if (codec_name) {
11019             g_free (codec);
11020             codec = g_strdup (codec_name);
11021           }
11022           break;
11023         }
11024         case FOURCC_wma_:
11025         {
11026           gint len = QT_UINT32 (stsd_entry_data) - offset;
11027           const guint8 *wfex_data = stsd_entry_data + offset;
11028           const gchar *codec_name = NULL;
11029           gint version = 1;
11030           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11031           /* FIXME this should also be gst_riff_strf_auds,
11032            * but the latter one is actually missing bits-per-sample :( */
11033           typedef struct
11034           {
11035             gint16 wFormatTag;
11036             gint16 nChannels;
11037             gint32 nSamplesPerSec;
11038             gint32 nAvgBytesPerSec;
11039             gint16 nBlockAlign;
11040             gint16 wBitsPerSample;
11041             gint16 cbSize;
11042           } WAVEFORMATEX;
11043           WAVEFORMATEX wfex;
11044
11045           /* FIXME: unify with similar wavformatex parsing code above */
11046           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11047
11048           /* find wfex */
11049           while (len >= 8) {
11050             gint size;
11051
11052             if (QT_UINT32 (wfex_data) <= len)
11053               size = QT_UINT32 (wfex_data) - 8;
11054             else
11055               size = len - 8;
11056
11057             if (size < 1)
11058               /* No real data, so break out */
11059               break;
11060
11061             switch (QT_FOURCC (wfex_data + 4)) {
11062               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11063               {
11064                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11065
11066                 if (size < 8 + 18)
11067                   break;
11068
11069                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11070                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11071                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11072                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11073                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11074                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11075                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11076
11077                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11078                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11079                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11080                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11081                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11082                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11083
11084                 if (wfex.wFormatTag == 0x0161) {
11085                   codec_name = "Windows Media Audio";
11086                   version = 2;
11087                 } else if (wfex.wFormatTag == 0x0162) {
11088                   codec_name = "Windows Media Audio 9 Pro";
11089                   version = 3;
11090                 } else if (wfex.wFormatTag == 0x0163) {
11091                   codec_name = "Windows Media Audio 9 Lossless";
11092                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11093                    * fluendo codec seems to support it */
11094                   version = 4;
11095                 }
11096
11097                 gst_caps_set_simple (entry->caps,
11098                     "wmaversion", G_TYPE_INT, version,
11099                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11100                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11101                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11102                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11103
11104                 if (size > wfex.cbSize) {
11105                   GstBuffer *buf;
11106
11107                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11108                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11109                       size - wfex.cbSize);
11110                   gst_caps_set_simple (entry->caps,
11111                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11112                   gst_buffer_unref (buf);
11113                 } else {
11114                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11115                 }
11116
11117                 if (codec_name) {
11118                   g_free (codec);
11119                   codec = g_strdup (codec_name);
11120                 }
11121                 break;
11122               }
11123               default:
11124                 break;
11125             }
11126             len -= size + 8;
11127             wfex_data += size + 8;
11128           }
11129           break;
11130         }
11131         case FOURCC_opus:
11132         {
11133           const guint8 *opus_data;
11134           guint8 *channel_mapping = NULL;
11135           guint32 rate;
11136           guint8 channels;
11137           guint8 channel_mapping_family;
11138           guint8 stream_count;
11139           guint8 coupled_count;
11140           guint8 i;
11141
11142           opus_data = stsd_entry_data;
11143
11144           channels = GST_READ_UINT8 (opus_data + 45);
11145           rate = GST_READ_UINT32_LE (opus_data + 48);
11146           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11147           stream_count = GST_READ_UINT8 (opus_data + 55);
11148           coupled_count = GST_READ_UINT8 (opus_data + 56);
11149
11150           if (channels > 0) {
11151             channel_mapping = g_malloc (channels * sizeof (guint8));
11152             for (i = 0; i < channels; i++)
11153               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11154           }
11155
11156           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11157               channel_mapping_family, stream_count, coupled_count,
11158               channel_mapping);
11159           break;
11160         }
11161         default:
11162           break;
11163       }
11164
11165       if (codec) {
11166         GstStructure *s;
11167         gint bitrate = 0;
11168
11169         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11170             GST_TAG_AUDIO_CODEC, codec, NULL);
11171         g_free (codec);
11172         codec = NULL;
11173
11174         /* some bitrate info may have ended up in caps */
11175         s = gst_caps_get_structure (entry->caps, 0);
11176         gst_structure_get_int (s, "bitrate", &bitrate);
11177         if (bitrate > 0)
11178           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11179               GST_TAG_BITRATE, bitrate, NULL);
11180       }
11181
11182       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11183       if (!stream->protected) {
11184       } else {
11185         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11186           mp4v = NULL;
11187         }
11188       }
11189       if (stream->protected && fourcc == FOURCC_mp4a) {
11190         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11191           mp4a = NULL;
11192         }
11193       } else {
11194         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11195           mp4a = NULL;
11196         }
11197       }
11198
11199       wave = NULL;
11200       esds = NULL;
11201       if (mp4a) {
11202         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11203         if (wave)
11204           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11205         if (!esds)
11206           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11207       }
11208
11209
11210       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11211          16 bits is a byte-swapped wave-style codec identifier,
11212          and we can find a WAVE header internally to a 'wave' atom here.
11213          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11214          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11215          is big-endian).
11216        */
11217       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11218         if (len < offset + 20) {
11219           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11220         } else {
11221           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11222           const guint8 *data = stsd_entry_data + offset + 16;
11223           GNode *wavenode;
11224           GNode *waveheadernode;
11225
11226           wavenode = g_node_new ((guint8 *) data);
11227           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11228             const guint8 *waveheader;
11229             guint32 headerlen;
11230
11231             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11232             if (waveheadernode) {
11233               waveheader = (const guint8 *) waveheadernode->data;
11234               headerlen = QT_UINT32 (waveheader);
11235
11236               if (headerlen > 8) {
11237                 gst_riff_strf_auds *header = NULL;
11238                 GstBuffer *headerbuf;
11239                 GstBuffer *extra;
11240
11241                 waveheader += 8;
11242                 headerlen -= 8;
11243
11244                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11245                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11246
11247                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11248                         headerbuf, &header, &extra)) {
11249                   gst_caps_unref (entry->caps);
11250                   /* FIXME: Need to do something with the channel reorder map */
11251                   entry->caps =
11252                       gst_riff_create_audio_caps (header->format, NULL, header,
11253                       extra, NULL, NULL, NULL);
11254
11255                   if (extra)
11256                     gst_buffer_unref (extra);
11257                   g_free (header);
11258                 }
11259               }
11260             } else
11261               GST_DEBUG ("Didn't find waveheadernode for this codec");
11262           }
11263           g_node_destroy (wavenode);
11264         }
11265       } else if (esds) {
11266         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11267             stream->stream_tags);
11268       } else {
11269         switch (fourcc) {
11270 #if 0
11271             /* FIXME: what is in the chunk? */
11272           case FOURCC_QDMC:
11273           {
11274             gint len = QT_UINT32 (stsd_data);
11275
11276             /* seems to be always = 116 = 0x74 */
11277             break;
11278           }
11279 #endif
11280           case FOURCC_QDM2:
11281           {
11282             gint len = QT_UINT32 (stsd_entry_data);
11283
11284             if (len > 0x3C) {
11285               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11286
11287               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11288               gst_caps_set_simple (entry->caps,
11289                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11290               gst_buffer_unref (buf);
11291             }
11292             gst_caps_set_simple (entry->caps,
11293                 "samplesize", G_TYPE_INT, samplesize, NULL);
11294             break;
11295           }
11296           case FOURCC_alac:
11297           {
11298             GNode *alac, *wave = NULL;
11299
11300             /* apparently, m4a has this atom appended directly in the stsd entry,
11301              * while mov has it in a wave atom */
11302             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11303             if (alac) {
11304               /* alac now refers to stsd entry atom */
11305               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11306               if (wave)
11307                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11308               else
11309                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11310             }
11311             if (alac) {
11312               const guint8 *alac_data = alac->data;
11313               gint len = QT_UINT32 (alac->data);
11314               GstBuffer *buf;
11315
11316               if (len < 36) {
11317                 GST_DEBUG_OBJECT (qtdemux,
11318                     "discarding alac atom with unexpected len %d", len);
11319               } else {
11320                 /* codec-data contains alac atom size and prefix,
11321                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11322                 buf = gst_buffer_new_and_alloc (len);
11323                 gst_buffer_fill (buf, 0, alac->data, len);
11324                 gst_caps_set_simple (entry->caps,
11325                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11326                 gst_buffer_unref (buf);
11327
11328                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11329                 entry->n_channels = QT_UINT8 (alac_data + 21);
11330                 entry->rate = QT_UINT32 (alac_data + 32);
11331               }
11332             }
11333             gst_caps_set_simple (entry->caps,
11334                 "samplesize", G_TYPE_INT, samplesize, NULL);
11335             break;
11336           }
11337           case FOURCC_fLaC:
11338           {
11339             /* The codingname of the sample entry is 'fLaC' */
11340             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11341
11342             if (flac) {
11343               /* The 'dfLa' box is added to the sample entry to convey
11344                  initializing information for the decoder. */
11345               const GNode *dfla =
11346                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11347
11348               if (dfla) {
11349                 const guint32 len = QT_UINT32 (dfla->data);
11350
11351                 /* Must contain at least dfLa box header (12),
11352                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11353                 if (len < 50) {
11354                   GST_DEBUG_OBJECT (qtdemux,
11355                       "discarding dfla atom with unexpected len %d", len);
11356                 } else {
11357                   /* skip dfLa header to get the METADATA_BLOCKs */
11358                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11359                   const guint32 metadata_blocks_len = len - 12;
11360
11361                   gchar *stream_marker = g_strdup ("fLaC");
11362                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11363                       strlen (stream_marker));
11364
11365                   guint32 index = 0;
11366                   guint32 remainder = 0;
11367                   guint32 block_size = 0;
11368                   gboolean is_last = FALSE;
11369
11370                   GValue array = G_VALUE_INIT;
11371                   GValue value = G_VALUE_INIT;
11372
11373                   g_value_init (&array, GST_TYPE_ARRAY);
11374                   g_value_init (&value, GST_TYPE_BUFFER);
11375
11376                   gst_value_set_buffer (&value, block);
11377                   gst_value_array_append_value (&array, &value);
11378                   g_value_reset (&value);
11379
11380                   gst_buffer_unref (block);
11381
11382                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11383                    * of data, and we haven't already finished parsing */
11384                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11385                     remainder = metadata_blocks_len - index;
11386
11387                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11388                     block_size = 4 +
11389                         (metadata_blocks[index + 1] << 16) +
11390                         (metadata_blocks[index + 2] << 8) +
11391                         metadata_blocks[index + 3];
11392
11393                     /* be careful not to read off end of box */
11394                     if (block_size > remainder) {
11395                       break;
11396                     }
11397
11398                     is_last = metadata_blocks[index] >> 7;
11399
11400                     block = gst_buffer_new_and_alloc (block_size);
11401
11402                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11403                         block_size);
11404
11405                     gst_value_set_buffer (&value, block);
11406                     gst_value_array_append_value (&array, &value);
11407                     g_value_reset (&value);
11408
11409                     gst_buffer_unref (block);
11410
11411                     index += block_size;
11412                   }
11413
11414                   /* only append the metadata if we successfully read all of it */
11415                   if (is_last) {
11416                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11417                             (stream)->caps, 0), "streamheader", &array);
11418                   } else {
11419                     GST_WARNING_OBJECT (qtdemux,
11420                         "discarding all METADATA_BLOCKs due to invalid "
11421                         "block_size %d at idx %d, rem %d", block_size, index,
11422                         remainder);
11423                   }
11424
11425                   g_value_unset (&value);
11426                   g_value_unset (&array);
11427
11428                   /* The sample rate obtained from the stsd may not be accurate
11429                    * since it cannot represent rates greater than 65535Hz, so
11430                    * override that value with the sample rate from the
11431                    * METADATA_BLOCK_STREAMINFO block */
11432                   CUR_STREAM (stream)->rate =
11433                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11434                 }
11435               }
11436             }
11437             break;
11438           }
11439           case FOURCC_sawb:
11440             /* Fallthrough! */
11441             amrwb = TRUE;
11442           case FOURCC_samr:
11443           {
11444             gint len = QT_UINT32 (stsd_entry_data);
11445
11446             if (len > 0x24) {
11447               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11448               guint bitrate;
11449
11450               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11451
11452               /* If we have enough data, let's try to get the 'damr' atom. See
11453                * the 3GPP container spec (26.244) for more details. */
11454               if ((len - 0x34) > 8 &&
11455                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11456                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11457                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11458               }
11459
11460               gst_caps_set_simple (entry->caps,
11461                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11462               gst_buffer_unref (buf);
11463             }
11464             break;
11465           }
11466           case FOURCC_mp4a:
11467           {
11468             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11469             gint len = QT_UINT32 (stsd_entry_data);
11470
11471             if (len >= 34) {
11472               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11473
11474               if (sound_version == 1) {
11475                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11476                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11477                 guint8 codec_data[2];
11478                 GstBuffer *buf;
11479                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11480
11481                 gint sample_rate_index =
11482                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11483
11484                 /* build AAC codec data */
11485                 codec_data[0] = profile << 3;
11486                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11487                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11488                 codec_data[1] |= (channels & 0xF) << 3;
11489
11490                 buf = gst_buffer_new_and_alloc (2);
11491                 gst_buffer_fill (buf, 0, codec_data, 2);
11492                 gst_caps_set_simple (entry->caps,
11493                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11494                 gst_buffer_unref (buf);
11495               }
11496             }
11497             break;
11498           }
11499           case FOURCC_lpcm:
11500             /* Fully handled elsewhere */
11501             break;
11502           default:
11503             GST_INFO_OBJECT (qtdemux,
11504                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11505             break;
11506         }
11507       }
11508       GST_INFO_OBJECT (qtdemux,
11509           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11510           GST_FOURCC_ARGS (fourcc), entry->caps);
11511
11512     } else if (stream->subtype == FOURCC_strm) {
11513       if (fourcc == FOURCC_rtsp) {
11514         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11515       } else {
11516         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11517             GST_FOURCC_ARGS (fourcc));
11518         goto unknown_stream;
11519       }
11520       entry->sampled = TRUE;
11521     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11522         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11523
11524       entry->sampled = TRUE;
11525       entry->sparse = TRUE;
11526
11527       entry->caps =
11528           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11529           &codec);
11530       if (codec) {
11531         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11532             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11533         g_free (codec);
11534         codec = NULL;
11535       }
11536
11537       /* hunt for sort-of codec data */
11538       switch (fourcc) {
11539         case FOURCC_mp4s:
11540         {
11541           GNode *mp4s = NULL;
11542           GNode *esds = NULL;
11543
11544           /* look for palette in a stsd->mp4s->esds sub-atom */
11545           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11546           if (mp4s)
11547             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11548           if (esds == NULL) {
11549             /* Invalid STSD */
11550             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11551             break;
11552           }
11553
11554           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11555               stream->stream_tags);
11556           break;
11557         }
11558         default:
11559           GST_INFO_OBJECT (qtdemux,
11560               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11561           break;
11562       }
11563       GST_INFO_OBJECT (qtdemux,
11564           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11565           GST_FOURCC_ARGS (fourcc), entry->caps);
11566     } else {
11567       /* everything in 1 sample */
11568       entry->sampled = TRUE;
11569
11570       entry->caps =
11571           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11572           &codec);
11573
11574       if (entry->caps == NULL)
11575         goto unknown_stream;
11576
11577       if (codec) {
11578         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11579             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11580         g_free (codec);
11581         codec = NULL;
11582       }
11583     }
11584
11585     /* promote to sampled format */
11586     if (entry->fourcc == FOURCC_samr) {
11587       /* force mono 8000 Hz for AMR */
11588       entry->sampled = TRUE;
11589       entry->n_channels = 1;
11590       entry->rate = 8000;
11591     } else if (entry->fourcc == FOURCC_sawb) {
11592       /* force mono 16000 Hz for AMR-WB */
11593       entry->sampled = TRUE;
11594       entry->n_channels = 1;
11595       entry->rate = 16000;
11596     } else if (entry->fourcc == FOURCC_mp4a) {
11597       entry->sampled = TRUE;
11598     }
11599
11600
11601     stsd_entry_data += len;
11602     remaining_stsd_len -= len;
11603
11604   }
11605
11606   /* collect sample information */
11607   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11608     goto samples_failed;
11609
11610   if (qtdemux->fragmented) {
11611     guint64 offset;
11612
11613     /* need all moov samples as basis; probably not many if any at all */
11614     /* prevent moof parsing taking of at this time */
11615     offset = qtdemux->moof_offset;
11616     qtdemux->moof_offset = 0;
11617     if (stream->n_samples &&
11618         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11619       qtdemux->moof_offset = offset;
11620       goto samples_failed;
11621     }
11622     qtdemux->moof_offset = 0;
11623     /* movie duration more reliable in this case (e.g. mehd) */
11624     if (qtdemux->segment.duration &&
11625         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11626       stream->duration =
11627           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11628   }
11629
11630   /* configure segments */
11631   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11632     goto segments_failed;
11633
11634   /* add some language tag, if useful */
11635   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11636       strcmp (stream->lang_id, "und")) {
11637     const gchar *lang_code;
11638
11639     /* convert ISO 639-2 code to ISO 639-1 */
11640     lang_code = gst_tag_get_language_code (stream->lang_id);
11641     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11642         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11643   }
11644
11645   /* Check for UDTA tags */
11646   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11647     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11648   }
11649
11650   /* now we are ready to add the stream */
11651   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11652     goto too_many_streams;
11653
11654   if (!qtdemux->got_moov) {
11655     qtdemux->streams[qtdemux->n_streams] = stream;
11656     qtdemux->n_streams++;
11657     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11658   }
11659
11660   return TRUE;
11661
11662 /* ERRORS */
11663 skip_track:
11664   {
11665     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11666     if (new_stream)
11667       gst_qtdemux_stream_free (qtdemux, stream);
11668     return TRUE;
11669   }
11670 corrupt_file:
11671   {
11672     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11673         (_("This file is corrupt and cannot be played.")), (NULL));
11674     if (new_stream)
11675       gst_qtdemux_stream_free (qtdemux, stream);
11676     return FALSE;
11677   }
11678 error_encrypted:
11679   {
11680     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11681     if (new_stream)
11682       gst_qtdemux_stream_free (qtdemux, stream);
11683     return FALSE;
11684   }
11685 samples_failed:
11686 segments_failed:
11687   {
11688     /* we posted an error already */
11689     /* free stbl sub-atoms */
11690     gst_qtdemux_stbl_free (stream);
11691     if (new_stream)
11692       gst_qtdemux_stream_free (qtdemux, stream);
11693     return FALSE;
11694   }
11695 existing_stream:
11696   {
11697     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11698         track_id);
11699     if (new_stream)
11700       gst_qtdemux_stream_free (qtdemux, stream);
11701     return TRUE;
11702   }
11703 unknown_stream:
11704   {
11705     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11706         GST_FOURCC_ARGS (stream->subtype));
11707     if (new_stream)
11708       gst_qtdemux_stream_free (qtdemux, stream);
11709     return TRUE;
11710   }
11711 too_many_streams:
11712   {
11713     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11714         (_("This file contains too many streams. Only playing first %d"),
11715             GST_QTDEMUX_MAX_STREAMS), (NULL));
11716     return TRUE;
11717   }
11718 }
11719
11720 /* If we can estimate the overall bitrate, and don't have information about the
11721  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11722  * the overall bitrate minus the sum of the bitrates of all other streams. This
11723  * should be useful for the common case where we have one audio and one video
11724  * stream and can estimate the bitrate of one, but not the other. */
11725 static void
11726 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11727 {
11728   QtDemuxStream *stream = NULL;
11729   gint64 size, sys_bitrate, sum_bitrate = 0;
11730   GstClockTime duration;
11731   gint i;
11732   guint bitrate;
11733
11734   if (qtdemux->fragmented)
11735     return;
11736
11737   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11738
11739   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11740       || size <= 0) {
11741     GST_DEBUG_OBJECT (qtdemux,
11742         "Size in bytes of the stream not known - bailing");
11743     return;
11744   }
11745
11746   /* Subtract the header size */
11747   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11748       size, qtdemux->header_size);
11749
11750   if (size < qtdemux->header_size)
11751     return;
11752
11753   size = size - qtdemux->header_size;
11754
11755   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11756     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11757     return;
11758   }
11759
11760   for (i = 0; i < qtdemux->n_streams; i++) {
11761     switch (qtdemux->streams[i]->subtype) {
11762       case FOURCC_soun:
11763       case FOURCC_vide:
11764         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11765             CUR_STREAM (qtdemux->streams[i])->caps);
11766         /* retrieve bitrate, prefer avg then max */
11767         bitrate = 0;
11768         if (qtdemux->streams[i]->stream_tags) {
11769           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11770                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
11771             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11772           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11773                   GST_TAG_NOMINAL_BITRATE, &bitrate))
11774             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11775           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11776                   GST_TAG_BITRATE, &bitrate))
11777             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11778         }
11779         if (bitrate)
11780           sum_bitrate += bitrate;
11781         else {
11782           if (stream) {
11783             GST_DEBUG_OBJECT (qtdemux,
11784                 ">1 stream with unknown bitrate - bailing");
11785             return;
11786           } else
11787             stream = qtdemux->streams[i];
11788         }
11789
11790       default:
11791         /* For other subtypes, we assume no significant impact on bitrate */
11792         break;
11793     }
11794   }
11795
11796   if (!stream) {
11797     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11798     return;
11799   }
11800
11801   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11802
11803   if (sys_bitrate < sum_bitrate) {
11804     /* This can happen, since sum_bitrate might be derived from maximum
11805      * bitrates and not average bitrates */
11806     GST_DEBUG_OBJECT (qtdemux,
11807         "System bitrate less than sum bitrate - bailing");
11808     return;
11809   }
11810
11811   bitrate = sys_bitrate - sum_bitrate;
11812   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11813       ", Stream bitrate = %u", sys_bitrate, bitrate);
11814
11815   if (!stream->stream_tags)
11816     stream->stream_tags = gst_tag_list_new_empty ();
11817   else
11818     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11819
11820   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11821       GST_TAG_BITRATE, bitrate, NULL);
11822 }
11823
11824 static GstFlowReturn
11825 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11826 {
11827   gint i;
11828   GstFlowReturn ret = GST_FLOW_OK;
11829
11830   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11831
11832   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11833     QtDemuxStream *stream = qtdemux->streams[i];
11834     guint32 sample_num = 0;
11835
11836     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11837         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11838
11839     if (qtdemux->fragmented) {
11840       /* need all moov samples first */
11841       GST_OBJECT_LOCK (qtdemux);
11842       while (stream->n_samples == 0)
11843         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11844           break;
11845       GST_OBJECT_UNLOCK (qtdemux);
11846     } else {
11847       /* discard any stray moof */
11848       qtdemux->moof_offset = 0;
11849     }
11850
11851     /* prepare braking */
11852     if (ret != GST_FLOW_ERROR)
11853       ret = GST_FLOW_OK;
11854
11855     /* in pull mode, we should have parsed some sample info by now;
11856      * and quite some code will not handle no samples.
11857      * in push mode, we'll just have to deal with it */
11858     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11859       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11860       gst_qtdemux_remove_stream (qtdemux, i);
11861       i--;
11862       continue;
11863     }
11864
11865     /* parse the initial sample for use in setting the frame rate cap */
11866     while (sample_num == 0 && sample_num < stream->n_samples) {
11867       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11868         break;
11869       ++sample_num;
11870     }
11871     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11872       stream->first_duration = stream->samples[0].duration;
11873       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11874           stream->track_id, stream->first_duration);
11875     }
11876   }
11877
11878   return ret;
11879 }
11880
11881 static GstFlowReturn
11882 qtdemux_expose_streams (GstQTDemux * qtdemux)
11883 {
11884   gint i;
11885   GSList *oldpads = NULL;
11886   GSList *iter;
11887
11888   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11889
11890   for (i = 0; i < qtdemux->n_streams; i++) {
11891     QtDemuxStream *stream = qtdemux->streams[i];
11892     GstPad *oldpad = stream->pad;
11893     GstTagList *list;
11894
11895     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11896         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11897
11898     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11899         stream->track_id == qtdemux->chapters_track_id) {
11900       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11901          so that it doesn't look like a subtitle track */
11902       gst_qtdemux_remove_stream (qtdemux, i);
11903       i--;
11904       continue;
11905     }
11906
11907     /* now we have all info and can expose */
11908     list = stream->stream_tags;
11909     stream->stream_tags = NULL;
11910     if (oldpad)
11911       oldpads = g_slist_prepend (oldpads, oldpad);
11912     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11913       return GST_FLOW_ERROR;
11914   }
11915
11916   gst_qtdemux_guess_bitrate (qtdemux);
11917
11918   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11919
11920   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11921     GstPad *oldpad = iter->data;
11922     GstEvent *event;
11923
11924     event = gst_event_new_eos ();
11925     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
11926       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11927
11928     gst_pad_push_event (oldpad, event);
11929     gst_pad_set_active (oldpad, FALSE);
11930     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11931     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11932     gst_object_unref (oldpad);
11933   }
11934
11935   /* check if we should post a redirect in case there is a single trak
11936    * and it is a redirecting trak */
11937   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11938     GstMessage *m;
11939
11940     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11941         "an external content");
11942     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11943         gst_structure_new ("redirect",
11944             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11945             NULL));
11946     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11947     qtdemux->posted_redirect = TRUE;
11948   }
11949
11950   for (i = 0; i < qtdemux->n_streams; i++) {
11951     QtDemuxStream *stream = qtdemux->streams[i];
11952
11953     qtdemux_do_allocation (qtdemux, stream);
11954   }
11955
11956   qtdemux->exposed = TRUE;
11957   return GST_FLOW_OK;
11958 }
11959
11960 /* check if major or compatible brand is 3GP */
11961 static inline gboolean
11962 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11963 {
11964   if (major) {
11965     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11966         FOURCC_3g__);
11967   } else if (qtdemux->comp_brands != NULL) {
11968     GstMapInfo map;
11969     guint8 *data;
11970     gsize size;
11971     gboolean res = FALSE;
11972
11973     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11974     data = map.data;
11975     size = map.size;
11976     while (size >= 4) {
11977       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11978           FOURCC_3g__);
11979       data += 4;
11980       size -= 4;
11981     }
11982     gst_buffer_unmap (qtdemux->comp_brands, &map);
11983     return res;
11984   } else {
11985     return FALSE;
11986   }
11987 }
11988
11989 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11990 static inline gboolean
11991 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11992 {
11993   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11994       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11995       || fourcc == FOURCC_albm;
11996 }
11997
11998 static void
11999 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12000     const char *tag, const char *dummy, GNode * node)
12001 {
12002   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12003   int offset;
12004   char *name;
12005   gchar *data;
12006   gdouble longitude, latitude, altitude;
12007   gint len;
12008
12009   len = QT_UINT32 (node->data);
12010   if (len <= 14)
12011     goto short_read;
12012
12013   data = node->data;
12014   offset = 14;
12015
12016   /* TODO: language code skipped */
12017
12018   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12019
12020   if (!name) {
12021     /* do not alarm in trivial case, but bail out otherwise */
12022     if (*(data + offset) != 0) {
12023       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12024           "giving up", tag);
12025     }
12026   } else {
12027     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12028         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12029     offset += strlen (name);
12030     g_free (name);
12031   }
12032
12033   if (len < offset + 2 + 4 + 4 + 4)
12034     goto short_read;
12035
12036   /* +1 +1 = skip null-terminator and location role byte */
12037   offset += 1 + 1;
12038   /* table in spec says unsigned, semantics say negative has meaning ... */
12039   longitude = QT_SFP32 (data + offset);
12040
12041   offset += 4;
12042   latitude = QT_SFP32 (data + offset);
12043
12044   offset += 4;
12045   altitude = QT_SFP32 (data + offset);
12046
12047   /* one invalid means all are invalid */
12048   if (longitude >= -180.0 && longitude <= 180.0 &&
12049       latitude >= -90.0 && latitude <= 90.0) {
12050     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12051         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12052         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12053         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12054   }
12055
12056   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12057
12058   return;
12059
12060   /* ERRORS */
12061 short_read:
12062   {
12063     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12064     return;
12065   }
12066 }
12067
12068
12069 static void
12070 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12071     const char *tag, const char *dummy, GNode * node)
12072 {
12073   guint16 y;
12074   GDate *date;
12075   gint len;
12076
12077   len = QT_UINT32 (node->data);
12078   if (len < 14)
12079     return;
12080
12081   y = QT_UINT16 ((guint8 *) node->data + 12);
12082   if (y == 0) {
12083     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12084     return;
12085   }
12086   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12087
12088   date = g_date_new_dmy (1, 1, y);
12089   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12090   g_date_free (date);
12091 }
12092
12093 static void
12094 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12095     const char *tag, const char *dummy, GNode * node)
12096 {
12097   int offset;
12098   char *tag_str = NULL;
12099   guint8 *entity;
12100   guint16 table;
12101   gint len;
12102
12103   len = QT_UINT32 (node->data);
12104   if (len <= 20)
12105     goto short_read;
12106
12107   offset = 12;
12108   entity = (guint8 *) node->data + offset;
12109   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12110     GST_DEBUG_OBJECT (qtdemux,
12111         "classification info: %c%c%c%c invalid classification entity",
12112         entity[0], entity[1], entity[2], entity[3]);
12113     return;
12114   }
12115
12116   offset += 4;
12117   table = QT_UINT16 ((guint8 *) node->data + offset);
12118
12119   /* Language code skipped */
12120
12121   offset += 4;
12122
12123   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12124    * XXXX: classification entity, fixed length 4 chars.
12125    * Y[YYYY]: classification table, max 5 chars.
12126    */
12127   tag_str = g_strdup_printf ("----://%u/%s",
12128       table, (char *) node->data + offset);
12129
12130   /* memcpy To be sure we're preserving byte order */
12131   memcpy (tag_str, entity, 4);
12132   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12133
12134   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12135
12136   g_free (tag_str);
12137
12138   return;
12139
12140   /* ERRORS */
12141 short_read:
12142   {
12143     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12144     return;
12145   }
12146 }
12147
12148 static gboolean
12149 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12150     const char *tag, const char *dummy, GNode * node)
12151 {
12152   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12153   GNode *data;
12154   char *s;
12155   int len;
12156   guint32 type;
12157   int offset;
12158   gboolean ret = TRUE;
12159   const gchar *charset = NULL;
12160
12161   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12162   if (data) {
12163     len = QT_UINT32 (data->data);
12164     type = QT_UINT32 ((guint8 *) data->data + 8);
12165     if (type == 0x00000001 && len > 16) {
12166       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12167           env_vars);
12168       if (s) {
12169         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12170         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12171         g_free (s);
12172       } else {
12173         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12174       }
12175     }
12176   } else {
12177     len = QT_UINT32 (node->data);
12178     type = QT_UINT32 ((guint8 *) node->data + 4);
12179     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12180       gint str_len;
12181       gint lang_code;
12182
12183       /* Type starts with the (C) symbol, so the next data is a list
12184        * of (string size(16), language code(16), string) */
12185
12186       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12187       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12188
12189       /* the string + fourcc + size + 2 16bit fields,
12190        * means that there are more tags in this atom */
12191       if (len > str_len + 8 + 4) {
12192         /* TODO how to represent the same tag in different languages? */
12193         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12194             "text alternatives, reading only first one");
12195       }
12196
12197       offset = 12;
12198       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12199       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12200
12201       if (lang_code < 0x800) {  /* MAC encoded string */
12202         charset = "mac";
12203       }
12204     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12205             QT_FOURCC ((guint8 *) node->data + 4))) {
12206       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12207
12208       /* we go for 3GP style encoding if major brands claims so,
12209        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12210       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12211           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12212               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12213         offset = 14;
12214         /* 16-bit Language code is ignored here as well */
12215         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12216       } else {
12217         goto normal;
12218       }
12219     } else {
12220     normal:
12221       offset = 8;
12222       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12223       ret = FALSE;              /* may have to fallback */
12224     }
12225     if (charset) {
12226       GError *err = NULL;
12227
12228       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12229           charset, NULL, NULL, &err);
12230       if (err) {
12231         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12232             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12233             err->message);
12234         g_error_free (err);
12235       }
12236     } else {
12237       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12238           len - offset, env_vars);
12239     }
12240     if (s) {
12241       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12242       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12243       g_free (s);
12244       ret = TRUE;
12245     } else {
12246       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12247     }
12248   }
12249   return ret;
12250 }
12251
12252 static void
12253 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12254     const char *tag, const char *dummy, GNode * node)
12255 {
12256   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12257 }
12258
12259 static void
12260 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12261     const char *tag, const char *dummy, GNode * node)
12262 {
12263   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12264   guint8 *data;
12265   char *s, *t, *k = NULL;
12266   int len;
12267   int offset;
12268   int count;
12269
12270   /* first try normal string tag if major brand not 3GP */
12271   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12272     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12273       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12274        * let's try it 3gpp way after minor safety check */
12275       data = node->data;
12276       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12277         return;
12278     } else
12279       return;
12280   }
12281
12282   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12283
12284   data = node->data;
12285
12286   len = QT_UINT32 (data);
12287   if (len < 15)
12288     goto short_read;
12289
12290   count = QT_UINT8 (data + 14);
12291   offset = 15;
12292   for (; count; count--) {
12293     gint slen;
12294
12295     if (offset + 1 > len)
12296       goto short_read;
12297     slen = QT_UINT8 (data + offset);
12298     offset += 1;
12299     if (offset + slen > len)
12300       goto short_read;
12301     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12302         slen, env_vars);
12303     if (s) {
12304       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12305       if (k) {
12306         t = g_strjoin (",", k, s, NULL);
12307         g_free (s);
12308         g_free (k);
12309         k = t;
12310       } else {
12311         k = s;
12312       }
12313     } else {
12314       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12315     }
12316     offset += slen;
12317   }
12318
12319 done:
12320   if (k) {
12321     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12322     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12323   }
12324   g_free (k);
12325
12326   return;
12327
12328   /* ERRORS */
12329 short_read:
12330   {
12331     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12332     goto done;
12333   }
12334 }
12335
12336 static void
12337 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12338     const char *tag1, const char *tag2, GNode * node)
12339 {
12340   GNode *data;
12341   int len;
12342   int type;
12343   int n1, n2;
12344
12345   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12346   if (data) {
12347     len = QT_UINT32 (data->data);
12348     type = QT_UINT32 ((guint8 *) data->data + 8);
12349     if (type == 0x00000000 && len >= 22) {
12350       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12351       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12352       if (n1 > 0) {
12353         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12354         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12355       }
12356       if (n2 > 0) {
12357         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12358         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12359       }
12360     }
12361   }
12362 }
12363
12364 static void
12365 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12366     const char *tag1, const char *dummy, GNode * node)
12367 {
12368   GNode *data;
12369   int len;
12370   int type;
12371   int n1;
12372
12373   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12374   if (data) {
12375     len = QT_UINT32 (data->data);
12376     type = QT_UINT32 ((guint8 *) data->data + 8);
12377     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12378     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12379     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12380       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12381       if (n1) {
12382         /* do not add bpm=0 */
12383         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12384         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12385             NULL);
12386       }
12387     }
12388   }
12389 }
12390
12391 static void
12392 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12393     const char *tag1, const char *dummy, GNode * node)
12394 {
12395   GNode *data;
12396   int len;
12397   int type;
12398   guint32 num;
12399
12400   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12401   if (data) {
12402     len = QT_UINT32 (data->data);
12403     type = QT_UINT32 ((guint8 *) data->data + 8);
12404     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12405     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12406     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12407       num = QT_UINT32 ((guint8 *) data->data + 16);
12408       if (num) {
12409         /* do not add num=0 */
12410         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12411         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12412       }
12413     }
12414   }
12415 }
12416
12417 static void
12418 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12419     const char *tag1, const char *dummy, GNode * node)
12420 {
12421   GNode *data;
12422   int len;
12423   int type;
12424   GstSample *sample;
12425
12426   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12427   if (data) {
12428     len = QT_UINT32 (data->data);
12429     type = QT_UINT32 ((guint8 *) data->data + 8);
12430     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12431     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12432       GstTagImageType image_type;
12433
12434       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12435         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12436       else
12437         image_type = GST_TAG_IMAGE_TYPE_NONE;
12438
12439       if ((sample =
12440               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12441                   len - 16, image_type))) {
12442         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12443         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12444         gst_sample_unref (sample);
12445       }
12446     }
12447   }
12448 }
12449
12450 static void
12451 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12452     const char *tag, const char *dummy, GNode * node)
12453 {
12454   GNode *data;
12455   char *s;
12456   int len;
12457   int type;
12458
12459   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12460   if (data) {
12461     len = QT_UINT32 (data->data);
12462     type = QT_UINT32 ((guint8 *) data->data + 8);
12463     if (type == 0x00000001 && len > 16) {
12464       guint y, m = 1, d = 1;
12465       gint ret;
12466
12467       s = g_strndup ((char *) data->data + 16, len - 16);
12468       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12469       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12470       if (ret >= 1 && y > 1500 && y < 3000) {
12471         GDate *date;
12472
12473         date = g_date_new_dmy (d, m, y);
12474         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12475         g_date_free (date);
12476       } else {
12477         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12478       }
12479       g_free (s);
12480     }
12481   }
12482 }
12483
12484 static void
12485 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12486     const char *tag, const char *dummy, GNode * node)
12487 {
12488   GNode *data;
12489
12490   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12491
12492   /* re-route to normal string tag if major brand says so
12493    * or no data atom and compatible brand suggests so */
12494   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12495       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12496     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12497     return;
12498   }
12499
12500   if (data) {
12501     guint len, type, n;
12502
12503     len = QT_UINT32 (data->data);
12504     type = QT_UINT32 ((guint8 *) data->data + 8);
12505     if (type == 0x00000000 && len >= 18) {
12506       n = QT_UINT16 ((guint8 *) data->data + 16);
12507       if (n > 0) {
12508         const gchar *genre;
12509
12510         genre = gst_tag_id3_genre_get (n - 1);
12511         if (genre != NULL) {
12512           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12513           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12514         }
12515       }
12516     }
12517   }
12518 }
12519
12520 static void
12521 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12522     const gchar * tag, guint8 * data, guint32 datasize)
12523 {
12524   gdouble value;
12525   gchar *datacopy;
12526
12527   /* make a copy to have \0 at the end */
12528   datacopy = g_strndup ((gchar *) data, datasize);
12529
12530   /* convert the str to double */
12531   if (sscanf (datacopy, "%lf", &value) == 1) {
12532     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12533     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12534   } else {
12535     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12536         datacopy);
12537   }
12538   g_free (datacopy);
12539 }
12540
12541
12542 static void
12543 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12544     const char *tag, const char *tag_bis, GNode * node)
12545 {
12546   GNode *mean;
12547   GNode *name;
12548   GNode *data;
12549   guint32 meansize;
12550   guint32 namesize;
12551   guint32 datatype;
12552   guint32 datasize;
12553   const gchar *meanstr;
12554   const gchar *namestr;
12555
12556   /* checking the whole ---- atom size for consistency */
12557   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12558     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12559     return;
12560   }
12561
12562   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12563   if (!mean) {
12564     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12565     return;
12566   }
12567
12568   meansize = QT_UINT32 (mean->data);
12569   if (meansize <= 12) {
12570     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12571     return;
12572   }
12573   meanstr = ((gchar *) mean->data) + 12;
12574   meansize -= 12;
12575
12576   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12577   if (!name) {
12578     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12579     return;
12580   }
12581
12582   namesize = QT_UINT32 (name->data);
12583   if (namesize <= 12) {
12584     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12585     return;
12586   }
12587   namestr = ((gchar *) name->data) + 12;
12588   namesize -= 12;
12589
12590   /*
12591    * Data atom is:
12592    * uint32 - size
12593    * uint32 - name
12594    * uint8  - version
12595    * uint24 - data type
12596    * uint32 - all 0
12597    * rest   - the data
12598    */
12599   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12600   if (!data) {
12601     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12602     return;
12603   }
12604   datasize = QT_UINT32 (data->data);
12605   if (datasize <= 16) {
12606     GST_WARNING_OBJECT (demux, "Data atom too small");
12607     return;
12608   }
12609   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12610
12611   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12612       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12613     static const struct
12614     {
12615       const gchar name[28];
12616       const gchar tag[28];
12617     } tags[] = {
12618       {
12619       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12620       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12621       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12622       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12623       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12624       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12625       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12626       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12627     };
12628     int i;
12629
12630     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12631       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12632         switch (gst_tag_get_type (tags[i].tag)) {
12633           case G_TYPE_DOUBLE:
12634             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12635                 ((guint8 *) data->data) + 16, datasize - 16);
12636             break;
12637           case G_TYPE_STRING:
12638             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12639             break;
12640           default:
12641             /* not reached */
12642             break;
12643         }
12644         break;
12645       }
12646     }
12647     if (i == G_N_ELEMENTS (tags))
12648       goto unknown_tag;
12649   } else {
12650     goto unknown_tag;
12651   }
12652
12653   return;
12654
12655 /* errors */
12656 unknown_tag:
12657 #ifndef GST_DISABLE_GST_DEBUG
12658   {
12659     gchar *namestr_dbg;
12660     gchar *meanstr_dbg;
12661
12662     meanstr_dbg = g_strndup (meanstr, meansize);
12663     namestr_dbg = g_strndup (namestr, namesize);
12664
12665     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12666         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12667
12668     g_free (namestr_dbg);
12669     g_free (meanstr_dbg);
12670   }
12671 #endif
12672   return;
12673 }
12674
12675 static void
12676 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12677     const char *tag_bis, GNode * node)
12678 {
12679   guint8 *data;
12680   GstBuffer *buf;
12681   guint len;
12682   GstTagList *id32_taglist = NULL;
12683
12684   GST_LOG_OBJECT (demux, "parsing ID32");
12685
12686   data = node->data;
12687   len = GST_READ_UINT32_BE (data);
12688
12689   /* need at least full box and language tag */
12690   if (len < 12 + 2)
12691     return;
12692
12693   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12694   gst_buffer_fill (buf, 0, data + 14, len - 14);
12695
12696   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12697   if (id32_taglist) {
12698     GST_LOG_OBJECT (demux, "parsing ok");
12699     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12700     gst_tag_list_unref (id32_taglist);
12701   } else {
12702     GST_LOG_OBJECT (demux, "parsing failed");
12703   }
12704
12705   gst_buffer_unref (buf);
12706 }
12707
12708 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12709     const char *tag, const char *tag_bis, GNode * node);
12710
12711 /* unmapped tags
12712 FOURCC_pcst -> if media is a podcast -> bool
12713 FOURCC_cpil -> if media is part of a compilation -> bool
12714 FOURCC_pgap -> if media is part of a gapless context -> bool
12715 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12716 */
12717
12718 static const struct
12719 {
12720   guint32 fourcc;
12721   const gchar *gst_tag;
12722   const gchar *gst_tag_bis;
12723   const GstQTDemuxAddTagFunc func;
12724 } add_funcs[] = {
12725   {
12726   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12727   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12728   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12729   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12730   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12731   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12732   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12733   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12734   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12735   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12736   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12737   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12738   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12739   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12740   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12741   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12742   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12743   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12744   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12745   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12746   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12747   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12748   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12749         qtdemux_tag_add_num}, {
12750   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12751         qtdemux_tag_add_num}, {
12752   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12753   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12754   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12755   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12756   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12757   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12758   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12759   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12760   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12761   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12762   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12763   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12764   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12765   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12766   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12767   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12768   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12769   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12770         qtdemux_tag_add_classification}, {
12771   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12772   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12773   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12774
12775     /* This is a special case, some tags are stored in this
12776      * 'reverse dns naming', according to:
12777      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12778      * bug #614471
12779      */
12780   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12781     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12782   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12783 };
12784
12785 struct _GstQtDemuxTagList
12786 {
12787   GstQTDemux *demux;
12788   GstTagList *taglist;
12789 };
12790 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12791
12792 static void
12793 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12794 {
12795   gint len;
12796   guint8 *data;
12797   GstBuffer *buf;
12798   gchar *media_type;
12799   const gchar *style;
12800   GstSample *sample;
12801   GstStructure *s;
12802   guint i;
12803   guint8 ndata[4];
12804   GstQTDemux *demux = qtdemuxtaglist->demux;
12805   GstTagList *taglist = qtdemuxtaglist->taglist;
12806
12807   data = node->data;
12808   len = QT_UINT32 (data);
12809   buf = gst_buffer_new_and_alloc (len);
12810   gst_buffer_fill (buf, 0, data, len);
12811
12812   /* heuristic to determine style of tag */
12813   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12814       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12815     style = "itunes";
12816   else if (demux->major_brand == FOURCC_qt__)
12817     style = "quicktime";
12818   /* fall back to assuming iso/3gp tag style */
12819   else
12820     style = "iso";
12821
12822   /* santize the name for the caps. */
12823   for (i = 0; i < 4; i++) {
12824     guint8 d = data[4 + i];
12825     if (g_ascii_isalnum (d))
12826       ndata[i] = g_ascii_tolower (d);
12827     else
12828       ndata[i] = '_';
12829   }
12830
12831   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12832       ndata[0], ndata[1], ndata[2], ndata[3]);
12833   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12834
12835   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12836   sample = gst_sample_new (buf, NULL, NULL, s);
12837   gst_buffer_unref (buf);
12838   g_free (media_type);
12839
12840   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12841       len, s);
12842
12843   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12844       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12845
12846   gst_sample_unref (sample);
12847 }
12848
12849 static void
12850 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12851 {
12852   GNode *meta;
12853   GNode *ilst;
12854   GNode *xmp_;
12855   GNode *node;
12856   gint i;
12857   GstQtDemuxTagList demuxtaglist;
12858
12859   demuxtaglist.demux = qtdemux;
12860   demuxtaglist.taglist = taglist;
12861
12862   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12863   if (meta != NULL) {
12864     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12865     if (ilst == NULL) {
12866       GST_LOG_OBJECT (qtdemux, "no ilst");
12867       return;
12868     }
12869   } else {
12870     ilst = udta;
12871     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12872   }
12873
12874   i = 0;
12875   while (i < G_N_ELEMENTS (add_funcs)) {
12876     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12877     if (node) {
12878       gint len;
12879
12880       len = QT_UINT32 (node->data);
12881       if (len < 12) {
12882         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12883             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12884       } else {
12885         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12886             add_funcs[i].gst_tag_bis, node);
12887       }
12888       g_node_destroy (node);
12889     } else {
12890       i++;
12891     }
12892   }
12893
12894   /* parsed nodes have been removed, pass along remainder as blob */
12895   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12896       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12897
12898   /* parse up XMP_ node if existing */
12899   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12900   if (xmp_ != NULL) {
12901     GstBuffer *buf;
12902     GstTagList *xmptaglist;
12903
12904     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12905         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12906     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12907     gst_buffer_unref (buf);
12908
12909     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12910   } else {
12911     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12912   }
12913 }
12914
12915 typedef struct
12916 {
12917   GstStructure *structure;      /* helper for sort function */
12918   gchar *location;
12919   guint min_req_bitrate;
12920   guint min_req_qt_version;
12921 } GstQtReference;
12922
12923 static gint
12924 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12925 {
12926   GstQtReference *ref_a = (GstQtReference *) a;
12927   GstQtReference *ref_b = (GstQtReference *) b;
12928
12929   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12930     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12931
12932   /* known bitrates go before unknown; higher bitrates go first */
12933   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12934 }
12935
12936 /* sort the redirects and post a message for the application.
12937  */
12938 static void
12939 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12940 {
12941   GstQtReference *best;
12942   GstStructure *s;
12943   GstMessage *msg;
12944   GValue list_val = { 0, };
12945   GList *l;
12946
12947   g_assert (references != NULL);
12948
12949   references = g_list_sort (references, qtdemux_redirects_sort_func);
12950
12951   best = (GstQtReference *) references->data;
12952
12953   g_value_init (&list_val, GST_TYPE_LIST);
12954
12955   for (l = references; l != NULL; l = l->next) {
12956     GstQtReference *ref = (GstQtReference *) l->data;
12957     GValue struct_val = { 0, };
12958
12959     ref->structure = gst_structure_new ("redirect",
12960         "new-location", G_TYPE_STRING, ref->location, NULL);
12961
12962     if (ref->min_req_bitrate > 0) {
12963       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12964           ref->min_req_bitrate, NULL);
12965     }
12966
12967     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12968     g_value_set_boxed (&struct_val, ref->structure);
12969     gst_value_list_append_value (&list_val, &struct_val);
12970     g_value_unset (&struct_val);
12971     /* don't free anything here yet, since we need best->structure below */
12972   }
12973
12974   g_assert (best != NULL);
12975   s = gst_structure_copy (best->structure);
12976
12977   if (g_list_length (references) > 1) {
12978     gst_structure_set_value (s, "locations", &list_val);
12979   }
12980
12981   g_value_unset (&list_val);
12982
12983   for (l = references; l != NULL; l = l->next) {
12984     GstQtReference *ref = (GstQtReference *) l->data;
12985
12986     gst_structure_free (ref->structure);
12987     g_free (ref->location);
12988     g_free (ref);
12989   }
12990   g_list_free (references);
12991
12992   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12993   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12994   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12995   qtdemux->posted_redirect = TRUE;
12996 }
12997
12998 /* look for redirect nodes, collect all redirect information and
12999  * process it.
13000  */
13001 static gboolean
13002 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13003 {
13004   GNode *rmra, *rmda, *rdrf;
13005
13006   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13007   if (rmra) {
13008     GList *redirects = NULL;
13009
13010     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13011     while (rmda) {
13012       GstQtReference ref = { NULL, NULL, 0, 0 };
13013       GNode *rmdr, *rmvc;
13014
13015       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13016         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13017         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13018             ref.min_req_bitrate);
13019       }
13020
13021       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13022         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13023         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13024
13025 #ifndef GST_DISABLE_GST_DEBUG
13026         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13027 #endif
13028         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13029
13030         GST_LOG_OBJECT (qtdemux,
13031             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13032             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13033             bitmask, check_type);
13034         if (package == FOURCC_qtim && check_type == 0) {
13035           ref.min_req_qt_version = version;
13036         }
13037       }
13038
13039       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13040       if (rdrf) {
13041         guint32 ref_type;
13042         guint8 *ref_data;
13043         guint ref_len;
13044
13045         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13046         if (ref_len > 20) {
13047           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13048           ref_data = (guint8 *) rdrf->data + 20;
13049           if (ref_type == FOURCC_alis) {
13050             guint record_len, record_version, fn_len;
13051
13052             if (ref_len > 70) {
13053               /* MacOSX alias record, google for alias-layout.txt */
13054               record_len = QT_UINT16 (ref_data + 4);
13055               record_version = QT_UINT16 (ref_data + 4 + 2);
13056               fn_len = QT_UINT8 (ref_data + 50);
13057               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13058                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13059               }
13060             } else {
13061               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13062                   ref_len);
13063             }
13064           } else if (ref_type == FOURCC_url_) {
13065             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13066           } else {
13067             GST_DEBUG_OBJECT (qtdemux,
13068                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13069                 GST_FOURCC_ARGS (ref_type));
13070           }
13071           if (ref.location != NULL) {
13072             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13073             redirects =
13074                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13075           } else {
13076             GST_WARNING_OBJECT (qtdemux,
13077                 "Failed to extract redirect location from rdrf atom");
13078           }
13079         } else {
13080           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13081         }
13082       }
13083
13084       /* look for others */
13085       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13086     }
13087
13088     if (redirects != NULL) {
13089       qtdemux_process_redirects (qtdemux, redirects);
13090     }
13091   }
13092   return TRUE;
13093 }
13094
13095 static GstTagList *
13096 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13097 {
13098   const gchar *fmt;
13099
13100   if (tags == NULL) {
13101     tags = gst_tag_list_new_empty ();
13102     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13103   }
13104
13105   if (qtdemux->major_brand == FOURCC_mjp2)
13106     fmt = "Motion JPEG 2000";
13107   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13108     fmt = "3GP";
13109   else if (qtdemux->major_brand == FOURCC_qt__)
13110     fmt = "Quicktime";
13111   else if (qtdemux->fragmented)
13112     fmt = "ISO fMP4";
13113   else
13114     fmt = "ISO MP4/M4A";
13115
13116   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13117       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13118
13119   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13120       fmt, NULL);
13121
13122   return tags;
13123 }
13124
13125 /* we have read the complete moov node now.
13126  * This function parses all of the relevant info, creates the traks and
13127  * prepares all data structures for playback
13128  */
13129 static gboolean
13130 qtdemux_parse_tree (GstQTDemux * qtdemux)
13131 {
13132   GNode *mvhd;
13133   GNode *trak;
13134   GNode *udta;
13135   GNode *mvex;
13136   GstClockTime duration;
13137   GNode *pssh;
13138   guint64 creation_time;
13139   GstDateTime *datetime = NULL;
13140   gint version;
13141
13142   /* make sure we have a usable taglist */
13143   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13144
13145   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13146   if (mvhd == NULL) {
13147     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13148     return qtdemux_parse_redirects (qtdemux);
13149   }
13150
13151   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13152   if (version == 1) {
13153     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13154     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13155     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13156   } else if (version == 0) {
13157     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13158     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13159     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13160   } else {
13161     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13162     return FALSE;
13163   }
13164
13165   /* Moving qt creation time (secs since 1904) to unix time */
13166   if (creation_time != 0) {
13167     /* Try to use epoch first as it should be faster and more commonly found */
13168     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13169       GTimeVal now;
13170
13171       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13172       /* some data cleansing sanity */
13173       g_get_current_time (&now);
13174       if (now.tv_sec + 24 * 3600 < creation_time) {
13175         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13176       } else {
13177         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13178       }
13179     } else {
13180       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13181       GDateTime *dt, *dt_local;
13182
13183       dt = g_date_time_add_seconds (base_dt, creation_time);
13184       dt_local = g_date_time_to_local (dt);
13185       datetime = gst_date_time_new_from_g_date_time (dt_local);
13186
13187       g_date_time_unref (base_dt);
13188       g_date_time_unref (dt);
13189     }
13190   }
13191   if (datetime) {
13192     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13193     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13194         datetime, NULL);
13195     gst_date_time_unref (datetime);
13196   }
13197
13198   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13199   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13200
13201   /* check for fragmented file and get some (default) data */
13202   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13203   if (mvex) {
13204     GNode *mehd;
13205     GstByteReader mehd_data;
13206
13207     /* let track parsing or anyone know weird stuff might happen ... */
13208     qtdemux->fragmented = TRUE;
13209
13210     /* compensate for total duration */
13211     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13212     if (mehd)
13213       qtdemux_parse_mehd (qtdemux, &mehd_data);
13214   }
13215
13216   /* set duration in the segment info */
13217   gst_qtdemux_get_duration (qtdemux, &duration);
13218   if (duration) {
13219     qtdemux->segment.duration = duration;
13220     /* also do not exceed duration; stop is set that way post seek anyway,
13221      * and segment activation falls back to duration,
13222      * whereas loop only checks stop, so let's align this here as well */
13223     qtdemux->segment.stop = duration;
13224   }
13225
13226   /* parse all traks */
13227   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13228   while (trak) {
13229     qtdemux_parse_trak (qtdemux, trak);
13230     /* iterate all siblings */
13231     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13232   }
13233
13234   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13235
13236   /* find tags */
13237   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13238   if (udta) {
13239     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13240   } else {
13241     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13242   }
13243
13244   /* maybe also some tags in meta box */
13245   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13246   if (udta) {
13247     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13248     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13249   } else {
13250     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13251   }
13252
13253   /* parse any protection system info */
13254   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13255   while (pssh) {
13256     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13257     qtdemux_parse_pssh (qtdemux, pssh);
13258     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13259   }
13260
13261   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13262
13263   return TRUE;
13264 }
13265
13266 /* taken from ffmpeg */
13267 static int
13268 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13269 {
13270   int count = 4;
13271   int len = 0;
13272
13273   while (count--) {
13274     int c;
13275
13276     if (ptr >= end)
13277       return -1;
13278
13279     c = *ptr++;
13280     len = (len << 7) | (c & 0x7f);
13281     if (!(c & 0x80))
13282       break;
13283   }
13284   *end_out = ptr;
13285   return len;
13286 }
13287
13288 /* this can change the codec originally present in @list */
13289 static void
13290 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13291     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13292 {
13293   int len = QT_UINT32 (esds->data);
13294   guint8 *ptr = esds->data;
13295   guint8 *end = ptr + len;
13296   int tag;
13297   guint8 *data_ptr = NULL;
13298   int data_len = 0;
13299   guint8 object_type_id = 0;
13300   const char *codec_name = NULL;
13301   GstCaps *caps = NULL;
13302
13303   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13304   ptr += 8;
13305   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13306   ptr += 4;
13307   while (ptr + 1 < end) {
13308     tag = QT_UINT8 (ptr);
13309     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13310     ptr++;
13311     len = read_descr_size (ptr, end, &ptr);
13312     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13313
13314     /* Check the stated amount of data is available for reading */
13315     if (len < 0 || ptr + len > end)
13316       break;
13317
13318     switch (tag) {
13319       case ES_DESCRIPTOR_TAG:
13320         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13321         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13322         ptr += 3;
13323         break;
13324       case DECODER_CONFIG_DESC_TAG:{
13325         guint max_bitrate, avg_bitrate;
13326
13327         object_type_id = QT_UINT8 (ptr);
13328         max_bitrate = QT_UINT32 (ptr + 5);
13329         avg_bitrate = QT_UINT32 (ptr + 9);
13330         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13331         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13332         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13333         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13334         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13335         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13336           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13337               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13338         }
13339         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13340           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13341               avg_bitrate, NULL);
13342         }
13343         ptr += 13;
13344         break;
13345       }
13346       case DECODER_SPECIFIC_INFO_TAG:
13347         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13348         if (object_type_id == 0xe0 && len == 0x40) {
13349           guint8 *data;
13350           GstStructure *s;
13351           guint32 clut[16];
13352           gint i;
13353
13354           GST_DEBUG_OBJECT (qtdemux,
13355               "Have VOBSUB palette. Creating palette event");
13356           /* move to decConfigDescr data and read palette */
13357           data = ptr;
13358           for (i = 0; i < 16; i++) {
13359             clut[i] = QT_UINT32 (data);
13360             data += 4;
13361           }
13362
13363           s = gst_structure_new ("application/x-gst-dvd", "event",
13364               G_TYPE_STRING, "dvd-spu-clut-change",
13365               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13366               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13367               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13368               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13369               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13370               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13371               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13372               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13373               NULL);
13374
13375           /* store event and trigger custom processing */
13376           stream->pending_event =
13377               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13378         } else {
13379           /* Generic codec_data handler puts it on the caps */
13380           data_ptr = ptr;
13381           data_len = len;
13382         }
13383
13384         ptr += len;
13385         break;
13386       case SL_CONFIG_DESC_TAG:
13387         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13388         ptr += 1;
13389         break;
13390       default:
13391         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13392             tag);
13393         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13394         ptr += len;
13395         break;
13396     }
13397   }
13398
13399   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13400    * in use, and should also be used to override some other parameters for some
13401    * codecs. */
13402   switch (object_type_id) {
13403     case 0x20:                 /* MPEG-4 */
13404       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13405        * profile_and_level_indication */
13406       if (data_ptr != NULL && data_len >= 5 &&
13407           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13408         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13409             data_ptr + 4, data_len - 4);
13410       }
13411       break;                    /* Nothing special needed here */
13412     case 0x21:                 /* H.264 */
13413       codec_name = "H.264 / AVC";
13414       caps = gst_caps_new_simple ("video/x-h264",
13415           "stream-format", G_TYPE_STRING, "avc",
13416           "alignment", G_TYPE_STRING, "au", NULL);
13417       break;
13418     case 0x40:                 /* AAC (any) */
13419     case 0x66:                 /* AAC Main */
13420     case 0x67:                 /* AAC LC */
13421     case 0x68:                 /* AAC SSR */
13422       /* Override channels and rate based on the codec_data, as it's often
13423        * wrong. */
13424       /* Only do so for basic setup without HE-AAC extension */
13425       if (data_ptr && data_len == 2) {
13426         guint channels, rate;
13427
13428         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13429         if (channels > 0)
13430           entry->n_channels = channels;
13431
13432         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13433         if (rate > 0)
13434           entry->rate = rate;
13435       }
13436
13437       /* Set level and profile if possible */
13438       if (data_ptr != NULL && data_len >= 2) {
13439         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13440             data_ptr, data_len);
13441       } else {
13442         const gchar *profile_str = NULL;
13443         GstBuffer *buffer;
13444         GstMapInfo map;
13445         guint8 *codec_data;
13446         gint rate_idx, profile;
13447
13448         /* No codec_data, let's invent something.
13449          * FIXME: This is wrong for SBR! */
13450
13451         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13452
13453         buffer = gst_buffer_new_and_alloc (2);
13454         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13455         codec_data = map.data;
13456
13457         rate_idx =
13458             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13459             (stream)->rate);
13460
13461         switch (object_type_id) {
13462           case 0x66:
13463             profile_str = "main";
13464             profile = 0;
13465             break;
13466           case 0x67:
13467             profile_str = "lc";
13468             profile = 1;
13469             break;
13470           case 0x68:
13471             profile_str = "ssr";
13472             profile = 2;
13473             break;
13474           default:
13475             profile = 3;
13476             break;
13477         }
13478
13479         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13480         codec_data[1] =
13481             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13482
13483         gst_buffer_unmap (buffer, &map);
13484         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13485             GST_TYPE_BUFFER, buffer, NULL);
13486         gst_buffer_unref (buffer);
13487
13488         if (profile_str) {
13489           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13490               G_TYPE_STRING, profile_str, NULL);
13491         }
13492       }
13493       break;
13494     case 0x60:                 /* MPEG-2, various profiles */
13495     case 0x61:
13496     case 0x62:
13497     case 0x63:
13498     case 0x64:
13499     case 0x65:
13500       codec_name = "MPEG-2 video";
13501       caps = gst_caps_new_simple ("video/mpeg",
13502           "mpegversion", G_TYPE_INT, 2,
13503           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13504       break;
13505     case 0x69:                 /* MPEG-2 BC audio */
13506     case 0x6B:                 /* MPEG-1 audio */
13507       caps = gst_caps_new_simple ("audio/mpeg",
13508           "mpegversion", G_TYPE_INT, 1, NULL);
13509       codec_name = "MPEG-1 audio";
13510       break;
13511     case 0x6A:                 /* MPEG-1 */
13512       codec_name = "MPEG-1 video";
13513       caps = gst_caps_new_simple ("video/mpeg",
13514           "mpegversion", G_TYPE_INT, 1,
13515           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13516       break;
13517     case 0x6C:                 /* MJPEG */
13518       caps =
13519           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13520           NULL);
13521       codec_name = "Motion-JPEG";
13522       break;
13523     case 0x6D:                 /* PNG */
13524       caps =
13525           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13526           NULL);
13527       codec_name = "PNG still images";
13528       break;
13529     case 0x6E:                 /* JPEG2000 */
13530       codec_name = "JPEG-2000";
13531       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13532       break;
13533     case 0xA4:                 /* Dirac */
13534       codec_name = "Dirac";
13535       caps = gst_caps_new_empty_simple ("video/x-dirac");
13536       break;
13537     case 0xA5:                 /* AC3 */
13538       codec_name = "AC-3 audio";
13539       caps = gst_caps_new_simple ("audio/x-ac3",
13540           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13541       break;
13542     case 0xA9:                 /* AC3 */
13543       codec_name = "DTS audio";
13544       caps = gst_caps_new_simple ("audio/x-dts",
13545           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13546       break;
13547     case 0xE1:                 /* QCELP */
13548       /* QCELP, the codec_data is a riff tag (little endian) with
13549        * 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). */
13550       caps = gst_caps_new_empty_simple ("audio/qcelp");
13551       codec_name = "QCELP";
13552       break;
13553     default:
13554       break;
13555   }
13556
13557   /* If we have a replacement caps, then change our caps for this stream */
13558   if (caps) {
13559     gst_caps_unref (entry->caps);
13560     entry->caps = caps;
13561   }
13562
13563   if (codec_name && list)
13564     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13565         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13566
13567   /* Add the codec_data attribute to caps, if we have it */
13568   if (data_ptr) {
13569     GstBuffer *buffer;
13570
13571     buffer = gst_buffer_new_and_alloc (data_len);
13572     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13573
13574     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13575     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13576
13577     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13578         buffer, NULL);
13579     gst_buffer_unref (buffer);
13580   }
13581
13582 }
13583
13584 static inline GstCaps *
13585 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13586 {
13587   GstCaps *caps;
13588   guint i;
13589   char *s, fourstr[5];
13590
13591   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13592   for (i = 0; i < 4; i++) {
13593     if (!g_ascii_isalnum (fourstr[i]))
13594       fourstr[i] = '_';
13595   }
13596   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13597   caps = gst_caps_new_empty_simple (s);
13598   g_free (s);
13599   return caps;
13600 }
13601
13602 #define _codec(name) \
13603   do { \
13604     if (codec_name) { \
13605       *codec_name = g_strdup (name); \
13606     } \
13607   } while (0)
13608
13609 static GstCaps *
13610 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13611     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13612     const guint8 * stsd_entry_data, gchar ** codec_name)
13613 {
13614   GstCaps *caps = NULL;
13615   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13616
13617   switch (fourcc) {
13618     case FOURCC_png:
13619       _codec ("PNG still images");
13620       caps = gst_caps_new_empty_simple ("image/png");
13621       break;
13622     case FOURCC_jpeg:
13623       _codec ("JPEG still images");
13624       caps =
13625           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13626           NULL);
13627       break;
13628     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13629     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13630     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13631     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13632       _codec ("Motion-JPEG");
13633       caps =
13634           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13635           NULL);
13636       break;
13637     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13638       _codec ("Motion-JPEG format B");
13639       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13640       break;
13641     case FOURCC_mjp2:
13642       _codec ("JPEG-2000");
13643       /* override to what it should be according to spec, avoid palette_data */
13644       entry->bits_per_sample = 24;
13645       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13646       break;
13647     case FOURCC_SVQ3:
13648       _codec ("Sorensen video v.3");
13649       caps = gst_caps_new_simple ("video/x-svq",
13650           "svqversion", G_TYPE_INT, 3, NULL);
13651       break;
13652     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13653     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13654       _codec ("Sorensen video v.1");
13655       caps = gst_caps_new_simple ("video/x-svq",
13656           "svqversion", G_TYPE_INT, 1, NULL);
13657       break;
13658     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13659       caps = gst_caps_new_empty_simple ("video/x-raw");
13660       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13661       _codec ("Windows Raw RGB");
13662       stream->alignment = 32;
13663       break;
13664     case FOURCC_raw_:
13665     {
13666       guint16 bps;
13667
13668       bps = QT_UINT16 (stsd_entry_data + 82);
13669       switch (bps) {
13670         case 15:
13671           format = GST_VIDEO_FORMAT_RGB15;
13672           break;
13673         case 16:
13674           format = GST_VIDEO_FORMAT_RGB16;
13675           break;
13676         case 24:
13677           format = GST_VIDEO_FORMAT_RGB;
13678           break;
13679         case 32:
13680           format = GST_VIDEO_FORMAT_ARGB;
13681           break;
13682         default:
13683           /* unknown */
13684           break;
13685       }
13686       break;
13687     }
13688     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13689       format = GST_VIDEO_FORMAT_I420;
13690       break;
13691     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13692     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13693       format = GST_VIDEO_FORMAT_I420;
13694       break;
13695     case FOURCC_2vuy:
13696     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13697       format = GST_VIDEO_FORMAT_UYVY;
13698       break;
13699     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13700       format = GST_VIDEO_FORMAT_v308;
13701       break;
13702     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13703       format = GST_VIDEO_FORMAT_v216;
13704       break;
13705     case FOURCC_v210:
13706       format = GST_VIDEO_FORMAT_v210;
13707       break;
13708     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13709       format = GST_VIDEO_FORMAT_r210;
13710       break;
13711       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13712          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13713          format = GST_VIDEO_FORMAT_v410;
13714          break;
13715        */
13716       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13717        * but different order than AYUV
13718        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13719        format = GST_VIDEO_FORMAT_v408;
13720        break;
13721        */
13722     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13723     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13724       _codec ("MPEG-1 video");
13725       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13726           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13727       break;
13728     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13729     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13730     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13731     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13732     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13733     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13734     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13735     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13736     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13737     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13738     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13739     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13740     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13741     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13742     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13743     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13744     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13745     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13746     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13747     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13748     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13749     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13750     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13751     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13752     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13753     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13754     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13755     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13756     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13757     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13758     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13759     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13760     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13761     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13762     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13763     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13764     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13765     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13766     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13767     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13768     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13769     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13770     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13771     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13772     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13773     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13774     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13775       _codec ("MPEG-2 video");
13776       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13777           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13778       break;
13779     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13780       _codec ("GIF still images");
13781       caps = gst_caps_new_empty_simple ("image/gif");
13782       break;
13783     case FOURCC_h263:
13784     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13785     case FOURCC_s263:
13786     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13787       _codec ("H.263");
13788       /* ffmpeg uses the height/width props, don't know why */
13789       caps = gst_caps_new_simple ("video/x-h263",
13790           "variant", G_TYPE_STRING, "itu", NULL);
13791       break;
13792     case FOURCC_mp4v:
13793     case FOURCC_MP4V:
13794       _codec ("MPEG-4 video");
13795       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13796           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13797       break;
13798     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13799     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13800       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13801       caps = gst_caps_new_simple ("video/x-msmpeg",
13802           "msmpegversion", G_TYPE_INT, 43, NULL);
13803       break;
13804     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13805       _codec ("DivX 3");
13806       caps = gst_caps_new_simple ("video/x-divx",
13807           "divxversion", G_TYPE_INT, 3, NULL);
13808       break;
13809     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13810     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13811       _codec ("DivX 4");
13812       caps = gst_caps_new_simple ("video/x-divx",
13813           "divxversion", G_TYPE_INT, 4, NULL);
13814       break;
13815     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13816       _codec ("DivX 5");
13817       caps = gst_caps_new_simple ("video/x-divx",
13818           "divxversion", G_TYPE_INT, 5, NULL);
13819       break;
13820
13821     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13822       _codec ("FFV1");
13823       caps = gst_caps_new_simple ("video/x-ffv",
13824           "ffvversion", G_TYPE_INT, 1, NULL);
13825       break;
13826
13827     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13828     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13829     case FOURCC_XVID:
13830     case FOURCC_xvid:
13831     case FOURCC_FMP4:
13832     case FOURCC_fmp4:
13833     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13834       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13835           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13836       _codec ("MPEG-4");
13837       break;
13838
13839     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13840       _codec ("Cinepak");
13841       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13842       break;
13843     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13844       _codec ("Apple QuickDraw");
13845       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13846       break;
13847     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13848       _codec ("Apple video");
13849       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13850       break;
13851     case FOURCC_H264:
13852     case FOURCC_avc1:
13853       _codec ("H.264 / AVC");
13854       caps = gst_caps_new_simple ("video/x-h264",
13855           "stream-format", G_TYPE_STRING, "avc",
13856           "alignment", G_TYPE_STRING, "au", NULL);
13857       break;
13858     case FOURCC_avc3:
13859       _codec ("H.264 / AVC");
13860       caps = gst_caps_new_simple ("video/x-h264",
13861           "stream-format", G_TYPE_STRING, "avc3",
13862           "alignment", G_TYPE_STRING, "au", NULL);
13863       break;
13864     case FOURCC_H265:
13865     case FOURCC_hvc1:
13866       _codec ("H.265 / HEVC");
13867       caps = gst_caps_new_simple ("video/x-h265",
13868           "stream-format", G_TYPE_STRING, "hvc1",
13869           "alignment", G_TYPE_STRING, "au", NULL);
13870       break;
13871     case FOURCC_hev1:
13872       _codec ("H.265 / HEVC");
13873       caps = gst_caps_new_simple ("video/x-h265",
13874           "stream-format", G_TYPE_STRING, "hev1",
13875           "alignment", G_TYPE_STRING, "au", NULL);
13876       break;
13877     case FOURCC_rle_:
13878       _codec ("Run-length encoding");
13879       caps = gst_caps_new_simple ("video/x-rle",
13880           "layout", G_TYPE_STRING, "quicktime", NULL);
13881       break;
13882     case FOURCC_WRLE:
13883       _codec ("Run-length encoding");
13884       caps = gst_caps_new_simple ("video/x-rle",
13885           "layout", G_TYPE_STRING, "microsoft", NULL);
13886       break;
13887     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13888     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13889       _codec ("Indeo Video 3");
13890       caps = gst_caps_new_simple ("video/x-indeo",
13891           "indeoversion", G_TYPE_INT, 3, NULL);
13892       break;
13893     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13894     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13895       _codec ("Intel Video 4");
13896       caps = gst_caps_new_simple ("video/x-indeo",
13897           "indeoversion", G_TYPE_INT, 4, NULL);
13898       break;
13899     case FOURCC_dvcp:
13900     case FOURCC_dvc_:
13901     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13902     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13903     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13904     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13905     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13906     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13907       _codec ("DV Video");
13908       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13909           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13910       break;
13911     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13912     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13913       _codec ("DVCPro50 Video");
13914       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13915           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13916       break;
13917     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13918     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13919       _codec ("DVCProHD Video");
13920       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13921           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13922       break;
13923     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13924       _codec ("Apple Graphics (SMC)");
13925       caps = gst_caps_new_empty_simple ("video/x-smc");
13926       break;
13927     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13928       _codec ("VP3");
13929       caps = gst_caps_new_empty_simple ("video/x-vp3");
13930       break;
13931     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13932       _codec ("VP6 Flash");
13933       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13934       break;
13935     case FOURCC_XiTh:
13936       _codec ("Theora");
13937       caps = gst_caps_new_empty_simple ("video/x-theora");
13938       /* theora uses one byte of padding in the data stream because it does not
13939        * allow 0 sized packets while theora does */
13940       entry->padding = 1;
13941       break;
13942     case FOURCC_drac:
13943       _codec ("Dirac");
13944       caps = gst_caps_new_empty_simple ("video/x-dirac");
13945       break;
13946     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13947       _codec ("TIFF still images");
13948       caps = gst_caps_new_empty_simple ("image/tiff");
13949       break;
13950     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13951       _codec ("Apple Intermediate Codec");
13952       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13953       break;
13954     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13955       _codec ("AVID DNxHD");
13956       caps = gst_caps_from_string ("video/x-dnxhd");
13957       break;
13958     case FOURCC_VP80:
13959     case FOURCC_vp08:
13960       _codec ("On2 VP8");
13961       caps = gst_caps_from_string ("video/x-vp8");
13962       break;
13963     case FOURCC_vp09:
13964       _codec ("Google VP9");
13965       caps = gst_caps_from_string ("video/x-vp9");
13966       break;
13967     case FOURCC_apcs:
13968       _codec ("Apple ProRes LT");
13969       caps =
13970           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13971           NULL);
13972       break;
13973     case FOURCC_apch:
13974       _codec ("Apple ProRes HQ");
13975       caps =
13976           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13977           NULL);
13978       break;
13979     case FOURCC_apcn:
13980       _codec ("Apple ProRes");
13981       caps =
13982           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13983           "standard", NULL);
13984       break;
13985     case FOURCC_apco:
13986       _codec ("Apple ProRes Proxy");
13987       caps =
13988           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13989           "proxy", NULL);
13990       break;
13991     case FOURCC_ap4h:
13992       _codec ("Apple ProRes 4444");
13993       caps =
13994           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13995           "4444", NULL);
13996       break;
13997     case FOURCC_ap4x:
13998       _codec ("Apple ProRes 4444 XQ");
13999       caps =
14000           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14001           "4444xq", NULL);
14002       break;
14003     case FOURCC_cfhd:
14004       _codec ("GoPro CineForm");
14005       caps = gst_caps_from_string ("video/x-cineform");
14006       break;
14007     case FOURCC_vc_1:
14008     case FOURCC_ovc1:
14009       _codec ("VC-1");
14010       caps = gst_caps_new_simple ("video/x-wmv",
14011           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14012       break;
14013     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14014     default:
14015     {
14016       caps = _get_unknown_codec_name ("video", fourcc);
14017       break;
14018     }
14019   }
14020
14021   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14022     GstVideoInfo info;
14023
14024     gst_video_info_init (&info);
14025     gst_video_info_set_format (&info, format, entry->width, entry->height);
14026
14027     caps = gst_video_info_to_caps (&info);
14028     *codec_name = gst_pb_utils_get_codec_description (caps);
14029
14030     /* enable clipping for raw video streams */
14031     stream->need_clip = TRUE;
14032     stream->alignment = 32;
14033   }
14034
14035   return caps;
14036 }
14037
14038 static guint
14039 round_up_pow2 (guint n)
14040 {
14041   n = n - 1;
14042   n = n | (n >> 1);
14043   n = n | (n >> 2);
14044   n = n | (n >> 4);
14045   n = n | (n >> 8);
14046   n = n | (n >> 16);
14047   return n + 1;
14048 }
14049
14050 static GstCaps *
14051 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14052     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14053     int len, gchar ** codec_name)
14054 {
14055   GstCaps *caps;
14056   const GstStructure *s;
14057   const gchar *name;
14058   gint endian = 0;
14059   GstAudioFormat format = 0;
14060   gint depth;
14061
14062   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14063
14064   depth = entry->bytes_per_packet * 8;
14065
14066   switch (fourcc) {
14067     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14068     case FOURCC_raw_:
14069       /* 8-bit audio is unsigned */
14070       if (depth == 8)
14071         format = GST_AUDIO_FORMAT_U8;
14072       /* otherwise it's signed and big-endian just like 'twos' */
14073     case FOURCC_twos:
14074       endian = G_BIG_ENDIAN;
14075       /* fall-through */
14076     case FOURCC_sowt:
14077     {
14078       gchar *str;
14079
14080       if (!endian)
14081         endian = G_LITTLE_ENDIAN;
14082
14083       if (!format)
14084         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14085
14086       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14087       _codec (str);
14088       g_free (str);
14089
14090       caps = gst_caps_new_simple ("audio/x-raw",
14091           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14092           "layout", G_TYPE_STRING, "interleaved", NULL);
14093       stream->alignment = GST_ROUND_UP_8 (depth);
14094       stream->alignment = round_up_pow2 (stream->alignment);
14095       break;
14096     }
14097     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14098       _codec ("Raw 64-bit floating-point audio");
14099       caps = gst_caps_new_simple ("audio/x-raw",
14100           "format", G_TYPE_STRING, "F64BE",
14101           "layout", G_TYPE_STRING, "interleaved", NULL);
14102       stream->alignment = 8;
14103       break;
14104     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14105       _codec ("Raw 32-bit floating-point audio");
14106       caps = gst_caps_new_simple ("audio/x-raw",
14107           "format", G_TYPE_STRING, "F32BE",
14108           "layout", G_TYPE_STRING, "interleaved", NULL);
14109       stream->alignment = 4;
14110       break;
14111     case FOURCC_in24:
14112       _codec ("Raw 24-bit PCM audio");
14113       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14114        * endian later */
14115       caps = gst_caps_new_simple ("audio/x-raw",
14116           "format", G_TYPE_STRING, "S24BE",
14117           "layout", G_TYPE_STRING, "interleaved", NULL);
14118       stream->alignment = 4;
14119       break;
14120     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14121       _codec ("Raw 32-bit PCM audio");
14122       caps = gst_caps_new_simple ("audio/x-raw",
14123           "format", G_TYPE_STRING, "S32BE",
14124           "layout", G_TYPE_STRING, "interleaved", NULL);
14125       stream->alignment = 4;
14126       break;
14127     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14128       _codec ("Raw 16-bit PCM audio");
14129       caps = gst_caps_new_simple ("audio/x-raw",
14130           "format", G_TYPE_STRING, "S16LE",
14131           "layout", G_TYPE_STRING, "interleaved", NULL);
14132       stream->alignment = 2;
14133       break;
14134     case FOURCC_ulaw:
14135       _codec ("Mu-law audio");
14136       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14137       break;
14138     case FOURCC_alaw:
14139       _codec ("A-law audio");
14140       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14141       break;
14142     case 0x0200736d:
14143     case 0x6d730002:
14144       _codec ("Microsoft ADPCM");
14145       /* Microsoft ADPCM-ACM code 2 */
14146       caps = gst_caps_new_simple ("audio/x-adpcm",
14147           "layout", G_TYPE_STRING, "microsoft", NULL);
14148       break;
14149     case 0x1100736d:
14150     case 0x6d730011:
14151       _codec ("DVI/IMA ADPCM");
14152       caps = gst_caps_new_simple ("audio/x-adpcm",
14153           "layout", G_TYPE_STRING, "dvi", NULL);
14154       break;
14155     case 0x1700736d:
14156     case 0x6d730017:
14157       _codec ("DVI/Intel IMA ADPCM");
14158       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14159       caps = gst_caps_new_simple ("audio/x-adpcm",
14160           "layout", G_TYPE_STRING, "quicktime", NULL);
14161       break;
14162     case 0x5500736d:
14163     case 0x6d730055:
14164       /* MPEG layer 3, CBR only (pre QT4.1) */
14165     case FOURCC__mp3:
14166       _codec ("MPEG-1 layer 3");
14167       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14168       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14169           "mpegversion", G_TYPE_INT, 1, NULL);
14170       break;
14171     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14172       _codec ("MPEG-1 layer 2");
14173       /* MPEG layer 2 */
14174       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14175           "mpegversion", G_TYPE_INT, 1, NULL);
14176       break;
14177     case 0x20736d:
14178     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14179       _codec ("EAC-3 audio");
14180       caps = gst_caps_new_simple ("audio/x-eac3",
14181           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14182       entry->sampled = TRUE;
14183       break;
14184     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14185     case FOURCC_ac_3:
14186       _codec ("AC-3 audio");
14187       caps = gst_caps_new_simple ("audio/x-ac3",
14188           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14189       entry->sampled = TRUE;
14190       break;
14191     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14192     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14193       _codec ("DTS audio");
14194       caps = gst_caps_new_simple ("audio/x-dts",
14195           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14196       entry->sampled = TRUE;
14197       break;
14198     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14199     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14200       _codec ("DTS-HD audio");
14201       caps = gst_caps_new_simple ("audio/x-dts",
14202           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14203       entry->sampled = TRUE;
14204       break;
14205     case FOURCC_MAC3:
14206       _codec ("MACE-3");
14207       caps = gst_caps_new_simple ("audio/x-mace",
14208           "maceversion", G_TYPE_INT, 3, NULL);
14209       break;
14210     case FOURCC_MAC6:
14211       _codec ("MACE-6");
14212       caps = gst_caps_new_simple ("audio/x-mace",
14213           "maceversion", G_TYPE_INT, 6, NULL);
14214       break;
14215     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14216       /* ogg/vorbis */
14217       caps = gst_caps_new_empty_simple ("application/ogg");
14218       break;
14219     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14220       _codec ("DV audio");
14221       caps = gst_caps_new_empty_simple ("audio/x-dv");
14222       break;
14223     case FOURCC_mp4a:
14224       _codec ("MPEG-4 AAC audio");
14225       caps = gst_caps_new_simple ("audio/mpeg",
14226           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14227           "stream-format", G_TYPE_STRING, "raw", NULL);
14228       break;
14229     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14230       _codec ("QDesign Music");
14231       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14232       break;
14233     case FOURCC_QDM2:
14234       _codec ("QDesign Music v.2");
14235       /* FIXME: QDesign music version 2 (no constant) */
14236       if (FALSE && data) {
14237         caps = gst_caps_new_simple ("audio/x-qdm2",
14238             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14239             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14240             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14241       } else {
14242         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14243       }
14244       break;
14245     case FOURCC_agsm:
14246       _codec ("GSM audio");
14247       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14248       break;
14249     case FOURCC_samr:
14250       _codec ("AMR audio");
14251       caps = gst_caps_new_empty_simple ("audio/AMR");
14252       break;
14253     case FOURCC_sawb:
14254       _codec ("AMR-WB audio");
14255       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14256       break;
14257     case FOURCC_ima4:
14258       _codec ("Quicktime IMA ADPCM");
14259       caps = gst_caps_new_simple ("audio/x-adpcm",
14260           "layout", G_TYPE_STRING, "quicktime", NULL);
14261       break;
14262     case FOURCC_alac:
14263       _codec ("Apple lossless audio");
14264       caps = gst_caps_new_empty_simple ("audio/x-alac");
14265       break;
14266     case FOURCC_fLaC:
14267       _codec ("Free Lossless Audio Codec");
14268       caps = gst_caps_new_simple ("audio/x-flac",
14269           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14270       break;
14271     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14272       _codec ("QualComm PureVoice");
14273       caps = gst_caps_from_string ("audio/qcelp");
14274       break;
14275     case FOURCC_wma_:
14276     case FOURCC_owma:
14277       _codec ("WMA");
14278       caps = gst_caps_new_empty_simple ("audio/x-wma");
14279       break;
14280     case FOURCC_opus:
14281       _codec ("Opus");
14282       caps = gst_caps_new_empty_simple ("audio/x-opus");
14283       break;
14284     case FOURCC_lpcm:
14285     {
14286       guint32 flags = 0;
14287       guint32 depth = 0;
14288       guint32 width = 0;
14289       GstAudioFormat format;
14290       enum
14291       {
14292         FLAG_IS_FLOAT = 0x1,
14293         FLAG_IS_BIG_ENDIAN = 0x2,
14294         FLAG_IS_SIGNED = 0x4,
14295         FLAG_IS_PACKED = 0x8,
14296         FLAG_IS_ALIGNED_HIGH = 0x10,
14297         FLAG_IS_NON_INTERLEAVED = 0x20
14298       };
14299       _codec ("Raw LPCM audio");
14300
14301       if (data && len >= 36) {
14302         depth = QT_UINT32 (data + 24);
14303         flags = QT_UINT32 (data + 28);
14304         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14305       }
14306       if ((flags & FLAG_IS_FLOAT) == 0) {
14307         if (depth == 0)
14308           depth = 16;
14309         if (width == 0)
14310           width = 16;
14311         if ((flags & FLAG_IS_ALIGNED_HIGH))
14312           depth = width;
14313
14314         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14315             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14316             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14317         caps = gst_caps_new_simple ("audio/x-raw",
14318             "format", G_TYPE_STRING,
14319             format !=
14320             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14321             "UNKNOWN", "layout", G_TYPE_STRING,
14322             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14323             "interleaved", NULL);
14324         stream->alignment = GST_ROUND_UP_8 (depth);
14325         stream->alignment = round_up_pow2 (stream->alignment);
14326       } else {
14327         if (width == 0)
14328           width = 32;
14329         if (width == 64) {
14330           if (flags & FLAG_IS_BIG_ENDIAN)
14331             format = GST_AUDIO_FORMAT_F64BE;
14332           else
14333             format = GST_AUDIO_FORMAT_F64LE;
14334         } else {
14335           if (flags & FLAG_IS_BIG_ENDIAN)
14336             format = GST_AUDIO_FORMAT_F32BE;
14337           else
14338             format = GST_AUDIO_FORMAT_F32LE;
14339         }
14340         caps = gst_caps_new_simple ("audio/x-raw",
14341             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14342             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14343             "non-interleaved" : "interleaved", NULL);
14344         stream->alignment = width / 8;
14345       }
14346       break;
14347     }
14348     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14349       /* ? */
14350     default:
14351     {
14352       caps = _get_unknown_codec_name ("audio", fourcc);
14353       break;
14354     }
14355   }
14356
14357   if (caps) {
14358     GstCaps *templ_caps =
14359         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14360     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14361     gst_caps_unref (caps);
14362     gst_caps_unref (templ_caps);
14363     caps = intersection;
14364   }
14365
14366   /* enable clipping for raw audio streams */
14367   s = gst_caps_get_structure (caps, 0);
14368   name = gst_structure_get_name (s);
14369   if (g_str_has_prefix (name, "audio/x-raw")) {
14370     stream->need_clip = TRUE;
14371     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14372     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14373   }
14374   return caps;
14375 }
14376
14377 static GstCaps *
14378 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14379     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14380     const guint8 * stsd_entry_data, gchar ** codec_name)
14381 {
14382   GstCaps *caps;
14383
14384   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14385
14386   switch (fourcc) {
14387     case FOURCC_mp4s:
14388       _codec ("DVD subtitle");
14389       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14390       stream->need_process = TRUE;
14391       break;
14392     case FOURCC_text:
14393       _codec ("Quicktime timed text");
14394       goto text;
14395     case FOURCC_tx3g:
14396       _codec ("3GPP timed text");
14397     text:
14398       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14399           "utf8", NULL);
14400       /* actual text piece needs to be extracted */
14401       stream->need_process = TRUE;
14402       break;
14403     case FOURCC_stpp:
14404       _codec ("XML subtitles");
14405       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14406       break;
14407     default:
14408     {
14409       caps = _get_unknown_codec_name ("text", fourcc);
14410       break;
14411     }
14412   }
14413   return caps;
14414 }
14415
14416 static GstCaps *
14417 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14418     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14419     const guint8 * stsd_entry_data, gchar ** codec_name)
14420 {
14421   GstCaps *caps;
14422
14423   switch (fourcc) {
14424     case FOURCC_m1v:
14425       _codec ("MPEG 1 video");
14426       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14427           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14428       break;
14429     default:
14430       caps = NULL;
14431       break;
14432   }
14433   return caps;
14434 }
14435
14436 static void
14437 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14438     const gchar * system_id)
14439 {
14440   gint i;
14441
14442   if (!qtdemux->protection_system_ids)
14443     qtdemux->protection_system_ids =
14444         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14445   /* Check whether we already have an entry for this system ID. */
14446   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14447     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14448     if (g_ascii_strcasecmp (system_id, id) == 0) {
14449       return;
14450     }
14451   }
14452   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14453   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14454           -1));
14455 }