qtdemux: get stsd child by index instead of type
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59
60 #include "qtatomparser.h"
61 #include "qtdemux_types.h"
62 #include "qtdemux_dump.h"
63 #include "fourcc.h"
64 #include "descriptors.h"
65 #include "qtdemux_lang.h"
66 #include "qtdemux.h"
67 #include "qtpalette.h"
68
69 #include "gst/riff/riff-media.h"
70 #include "gst/riff/riff-read.h"
71
72 #include <gst/pbutils/pbutils.h>
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 GST_DEBUG_CATEGORY (qtdemux_debug);
104
105 typedef struct _QtDemuxSegment QtDemuxSegment;
106 typedef struct _QtDemuxSample QtDemuxSample;
107
108 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
109
110 struct _QtDemuxSample
111 {
112   guint32 size;
113   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
114   guint64 offset;
115   guint64 timestamp;            /* DTS In mov time */
116   guint32 duration;             /* In mov time */
117   gboolean keyframe;            /* TRUE when this packet is a keyframe */
118 };
119
120 /* Macros for converting to/from timescale */
121 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
122 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
123
124 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
125 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
126
127 /* timestamp is the DTS */
128 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
129 /* timestamp + offset + cslg_shift is the outgoing PTS */
130 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
131 /* timestamp + offset is the PTS used for internal seek calcuations */
132 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
133 /* timestamp + duration - dts is the duration */
134 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
135
136 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
137
138 /*
139  * Quicktime has tracks and segments. A track is a continuous piece of
140  * multimedia content. The track is not always played from start to finish but
141  * instead, pieces of the track are 'cut out' and played in sequence. This is
142  * what the segments do.
143  *
144  * Inside the track we have keyframes (K) and delta frames. The track has its
145  * own timing, which starts from 0 and extends to end. The position in the track
146  * is called the media_time.
147  *
148  * The segments now describe the pieces that should be played from this track
149  * and are basically tuples of media_time/duration/rate entries. We can have
150  * multiple segments and they are all played after one another. An example:
151  *
152  * segment 1: media_time: 1 second, duration: 1 second, rate 1
153  * segment 2: media_time: 3 second, duration: 2 second, rate 2
154  *
155  * To correctly play back this track, one must play: 1 second of media starting
156  * from media_time 1 followed by 2 seconds of media starting from media_time 3
157  * at a rate of 2.
158  *
159  * Each of the segments will be played at a specific time, the first segment at
160  * time 0, the second one after the duration of the first one, etc.. Note that
161  * the time in resulting playback is not identical to the media_time of the
162  * track anymore.
163  *
164  * Visually, assuming the track has 4 second of media_time:
165  *
166  *                (a)                   (b)          (c)              (d)
167  *         .-----------------------------------------------------------.
168  * track:  | K.....K.........K........K.......K.......K...........K... |
169  *         '-----------------------------------------------------------'
170  *         0              1              2              3              4
171  *           .------------^              ^   .----------^              ^
172  *          /              .-------------'  /       .------------------'
173  *         /              /          .-----'       /
174  *         .--------------.         .--------------.
175  *         | segment 1    |         | segment 2    |
176  *         '--------------'         '--------------'
177  *
178  * The challenge here is to cut out the right pieces of the track for each of
179  * the playback segments. This fortunately can easily be done with the SEGMENT
180  * events of GStreamer.
181  *
182  * For playback of segment 1, we need to provide the decoder with the keyframe
183  * (a), in the above figure, but we must instruct it only to output the decoded
184  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
185  * position set to the time of the segment: 0.
186  *
187  * We then proceed to push data from keyframe (a) to frame (b). The decoder
188  * decodes but clips all before media_time 1.
189  *
190  * After finishing a segment, we push out a new SEGMENT event with the clipping
191  * boundaries of the new data.
192  *
193  * This is a good usecase for the GStreamer accumulated SEGMENT events.
194  */
195
196 struct _QtDemuxSegment
197 {
198   /* global time and duration, all gst time */
199   GstClockTime time;
200   GstClockTime stop_time;
201   GstClockTime duration;
202   /* media time of trak, all gst time */
203   GstClockTime media_start;
204   GstClockTime media_stop;
205   gdouble rate;
206   /* Media start time in trak timescale units */
207   guint32 trak_media_start;
208 };
209
210 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
211
212 /* Used with fragmented MP4 files (mfra atom) */
213 typedef struct
214 {
215   GstClockTime ts;
216   guint64 moof_offset;
217 } QtDemuxRandomAccessEntry;
218
219 struct _QtDemuxStream
220 {
221   GstPad *pad;
222
223   /* stream type */
224   guint32 subtype;
225   GstCaps *caps;
226   guint32 fourcc;
227   gboolean sparse;
228
229   gboolean new_caps;            /* If TRUE, caps need to be generated (by
230                                  * calling _configure_stream()) This happens
231                                  * for MSS and fragmented streams */
232
233   gboolean new_stream;          /* signals that a stream_start is required */
234   gboolean on_keyframe;         /* if this stream last pushed buffer was a
235                                  * keyframe. This is important to identify
236                                  * where to stop pushing buffers after a
237                                  * segment stop time */
238
239   /* if the stream has a redirect URI in its headers, we store it here */
240   gchar *redirect_uri;
241
242   /* track id */
243   guint track_id;
244
245   /* duration/scale */
246   guint64 duration;             /* in timescale units */
247   guint32 timescale;
248
249   /* language */
250   gchar lang_id[4];             /* ISO 639-2T language code */
251
252   /* our samples */
253   guint32 n_samples;
254   QtDemuxSample *samples;
255   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
256   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
257                                    the framerate */
258   guint32 n_samples_moof;       /* sample count in a moof */
259   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
260                                  * the framerate of fragmented format stream */
261   guint64 duration_last_moof;
262
263   guint32 offset_in_sample;     /* Offset in the current sample, used for
264                                  * streams which have got exceedingly big
265                                  * sample size (such as 24s of raw audio).
266                                  * Only used when max_buffer_size is non-NULL */
267   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
268                                  * Currently only set for raw audio streams*/
269
270   /* if we use chunks or samples */
271   gboolean sampled;
272   guint padding;
273
274   /* video info */
275   gint width;
276   gint height;
277   /* aspect ratio */
278   gint display_width;
279   gint display_height;
280   gint par_w;
281   gint par_h;
282   /* Numerator/denominator framerate */
283   gint fps_n;
284   gint fps_d;
285   GstVideoColorimetry colorimetry;
286   guint16 bits_per_sample;
287   guint16 color_table_id;
288   GstMemory *rgb8_palette;
289   guint interlace_mode;
290   guint field_order;
291
292   /* audio info */
293   gdouble rate;
294   gint n_channels;
295   guint samples_per_packet;
296   guint samples_per_frame;
297   guint bytes_per_packet;
298   guint bytes_per_sample;
299   guint bytes_per_frame;
300   guint compression;
301
302   /* allocation */
303   gboolean use_allocator;
304   GstAllocator *allocator;
305   GstAllocationParams params;
306
307   gsize alignment;
308
309   /* when a discontinuity is pending */
310   gboolean discont;
311
312   /* list of buffers to push first */
313   GSList *buffers;
314
315   /* if we need to clip this buffer. This is only needed for uncompressed
316    * data */
317   gboolean need_clip;
318
319   /* buffer needs some custom processing, e.g. subtitles */
320   gboolean need_process;
321
322   /* current position */
323   guint32 segment_index;
324   guint32 sample_index;
325   GstClockTime time_position;   /* in gst time */
326   guint64 accumulated_base;
327
328   /* the Gst segment we are processing out, used for clipping */
329   GstSegment segment;
330
331   /* quicktime segments */
332   guint32 n_segments;
333   QtDemuxSegment *segments;
334   gboolean dummy_segment;
335   guint32 from_sample;
336   guint32 to_sample;
337
338   gboolean sent_eos;
339   GstTagList *stream_tags;
340   gboolean send_global_tags;
341
342   GstEvent *pending_event;
343
344   GstByteReader stco;
345   GstByteReader stsz;
346   GstByteReader stsc;
347   GstByteReader stts;
348   GstByteReader stss;
349   GstByteReader stps;
350   GstByteReader ctts;
351
352   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
353   gint64 stbl_index;
354   /* stco */
355   guint co_size;
356   GstByteReader co_chunk;
357   guint32 first_chunk;
358   guint32 current_chunk;
359   guint32 last_chunk;
360   guint32 samples_per_chunk;
361   guint32 stco_sample_index;
362   /* stsz */
363   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
364   /* stsc */
365   guint32 stsc_index;
366   guint32 n_samples_per_chunk;
367   guint32 stsc_chunk_index;
368   guint32 stsc_sample_index;
369   guint64 chunk_offset;
370   /* stts */
371   guint32 stts_index;
372   guint32 stts_samples;
373   guint32 n_sample_times;
374   guint32 stts_sample_index;
375   guint64 stts_time;
376   guint32 stts_duration;
377   /* stss */
378   gboolean stss_present;
379   guint32 n_sample_syncs;
380   guint32 stss_index;
381   /* stps */
382   gboolean stps_present;
383   guint32 n_sample_partial_syncs;
384   guint32 stps_index;
385   QtDemuxRandomAccessEntry *ra_entries;
386   guint n_ra_entries;
387
388   const QtDemuxRandomAccessEntry *pending_seek;
389
390   /* ctts */
391   gboolean ctts_present;
392   guint32 n_composition_times;
393   guint32 ctts_index;
394   guint32 ctts_sample_index;
395   guint32 ctts_count;
396   gint32 ctts_soffset;
397
398   /* cslg */
399   guint32 cslg_shift;
400
401   /* fragmented */
402   gboolean parsed_trex;
403   guint32 def_sample_duration;
404   guint32 def_sample_size;
405   guint32 def_sample_flags;
406
407   gboolean disabled;
408
409   /* stereoscopic video streams */
410   GstVideoMultiviewMode multiview_mode;
411   GstVideoMultiviewFlags multiview_flags;
412
413   /* protected streams */
414   gboolean protected;
415   guint32 protection_scheme_type;
416   guint32 protection_scheme_version;
417   gpointer protection_scheme_info;      /* specific to the protection scheme */
418   GQueue protection_scheme_event_queue;
419 };
420
421 /* Contains properties and cryptographic info for a set of samples from a
422  * track protected using Common Encryption (cenc) */
423 struct _QtDemuxCencSampleSetInfo
424 {
425   GstStructure *default_properties;
426
427   /* @crypto_info holds one GstStructure per sample */
428   GPtrArray *crypto_info;
429 };
430
431 static const gchar *
432 qt_demux_state_string (enum QtDemuxState state)
433 {
434   switch (state) {
435     case QTDEMUX_STATE_INITIAL:
436       return "<INITIAL>";
437     case QTDEMUX_STATE_HEADER:
438       return "<HEADER>";
439     case QTDEMUX_STATE_MOVIE:
440       return "<MOVIE>";
441     case QTDEMUX_STATE_BUFFER_MDAT:
442       return "<BUFFER_MDAT>";
443     default:
444       return "<UNKNOWN>";
445   }
446 }
447
448 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
449 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
450     guint32 fourcc, GstByteReader * parser);
451 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
452 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
453     guint32 fourcc, GstByteReader * parser);
454
455 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
456
457 static GstStaticPadTemplate gst_qtdemux_sink_template =
458     GST_STATIC_PAD_TEMPLATE ("sink",
459     GST_PAD_SINK,
460     GST_PAD_ALWAYS,
461     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
462         "application/x-3gp")
463     );
464
465 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
466 GST_STATIC_PAD_TEMPLATE ("video_%u",
467     GST_PAD_SRC,
468     GST_PAD_SOMETIMES,
469     GST_STATIC_CAPS_ANY);
470
471 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
472 GST_STATIC_PAD_TEMPLATE ("audio_%u",
473     GST_PAD_SRC,
474     GST_PAD_SOMETIMES,
475     GST_STATIC_CAPS_ANY);
476
477 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
478 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
479     GST_PAD_SRC,
480     GST_PAD_SOMETIMES,
481     GST_STATIC_CAPS_ANY);
482
483 #define gst_qtdemux_parent_class parent_class
484 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
485
486 static void gst_qtdemux_dispose (GObject * object);
487
488 static guint32
489 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
490     GstClockTime media_time);
491 static guint32
492 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
493     QtDemuxStream * str, gint64 media_offset);
494
495 #if 0
496 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
497 static GstIndex *gst_qtdemux_get_index (GstElement * element);
498 #endif
499 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
500     GstStateChange transition);
501 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
502 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
503     GstObject * parent, GstPadMode mode, gboolean active);
504
505 static void gst_qtdemux_loop (GstPad * pad);
506 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
507     GstBuffer * inbuf);
508 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
509     GstEvent * event);
510 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
511 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
512     QtDemuxStream * stream);
513 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
514     gboolean force);
515
516 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
517     const guint8 * buffer, guint length);
518 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
519     const guint8 * buffer, guint length);
520 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
521 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
522     GNode * udta);
523
524 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
525     QtDemuxStream * stream, GNode * esds, GstTagList * list);
526 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
527     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
528     gchar ** codec_name);
529 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
530     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
531     gchar ** codec_name);
532 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
533     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
534     gchar ** codec_name);
535 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
536     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
537     gchar ** codec_name);
538
539 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
540     QtDemuxStream * stream, guint32 n);
541 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
542 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
543     QtDemuxStream * stream);
544 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
545     QtDemuxStream * stream);
546 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
547 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
548 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
549     QtDemuxStream * stream);
550 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
551     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
552 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
553     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
554     GstClockTime * _start, GstClockTime * _stop);
555 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
556     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
557
558 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
559 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
560
561 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
562
563 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
564     QtDemuxStream * stream, guint sample_index);
565 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
566     const gchar * id);
567 static void qtdemux_gst_structure_free (GstStructure * gststructure);
568
569 static void
570 gst_qtdemux_class_init (GstQTDemuxClass * klass)
571 {
572   GObjectClass *gobject_class;
573   GstElementClass *gstelement_class;
574
575   gobject_class = (GObjectClass *) klass;
576   gstelement_class = (GstElementClass *) klass;
577
578   parent_class = g_type_class_peek_parent (klass);
579
580   gobject_class->dispose = gst_qtdemux_dispose;
581
582   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
583 #if 0
584   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
585   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
586 #endif
587
588   gst_tag_register_musicbrainz_tags ();
589
590   gst_element_class_add_static_pad_template (gstelement_class,
591       &gst_qtdemux_sink_template);
592   gst_element_class_add_static_pad_template (gstelement_class,
593       &gst_qtdemux_videosrc_template);
594   gst_element_class_add_static_pad_template (gstelement_class,
595       &gst_qtdemux_audiosrc_template);
596   gst_element_class_add_static_pad_template (gstelement_class,
597       &gst_qtdemux_subsrc_template);
598   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
599       "Codec/Demuxer",
600       "Demultiplex a QuickTime file into audio and video streams",
601       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
602
603   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
604
605 }
606
607 static void
608 gst_qtdemux_init (GstQTDemux * qtdemux)
609 {
610   qtdemux->sinkpad =
611       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
612   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
613   gst_pad_set_activatemode_function (qtdemux->sinkpad,
614       qtdemux_sink_activate_mode);
615   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
616   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
617   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
618
619   qtdemux->state = QTDEMUX_STATE_INITIAL;
620   qtdemux->pullbased = FALSE;
621   qtdemux->posted_redirect = FALSE;
622   qtdemux->neededbytes = 16;
623   qtdemux->todrop = 0;
624   qtdemux->adapter = gst_adapter_new ();
625   qtdemux->offset = 0;
626   qtdemux->first_mdat = -1;
627   qtdemux->got_moov = FALSE;
628   qtdemux->mdatoffset = -1;
629   qtdemux->mdatbuffer = NULL;
630   qtdemux->restoredata_buffer = NULL;
631   qtdemux->restoredata_offset = -1;
632   qtdemux->fragment_start = -1;
633   qtdemux->fragment_start_offset = -1;
634   qtdemux->media_caps = NULL;
635   qtdemux->exposed = FALSE;
636   qtdemux->mss_mode = FALSE;
637   qtdemux->pending_newsegment = NULL;
638   qtdemux->upstream_format_is_time = FALSE;
639   qtdemux->have_group_id = FALSE;
640   qtdemux->group_id = G_MAXUINT;
641   qtdemux->cenc_aux_info_offset = 0;
642   qtdemux->cenc_aux_info_sizes = NULL;
643   qtdemux->cenc_aux_sample_count = 0;
644   qtdemux->protection_system_ids = NULL;
645   g_queue_init (&qtdemux->protection_event_queue);
646   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
647   qtdemux->tag_list = gst_tag_list_new_empty ();
648   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
649   qtdemux->flowcombiner = gst_flow_combiner_new ();
650
651   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
652 }
653
654 static void
655 gst_qtdemux_dispose (GObject * object)
656 {
657   GstQTDemux *qtdemux = GST_QTDEMUX (object);
658
659   if (qtdemux->adapter) {
660     g_object_unref (G_OBJECT (qtdemux->adapter));
661     qtdemux->adapter = NULL;
662   }
663   gst_tag_list_unref (qtdemux->tag_list);
664   gst_flow_combiner_free (qtdemux->flowcombiner);
665   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
666       NULL);
667   g_queue_clear (&qtdemux->protection_event_queue);
668
669   g_free (qtdemux->cenc_aux_info_sizes);
670   qtdemux->cenc_aux_info_sizes = NULL;
671
672   G_OBJECT_CLASS (parent_class)->dispose (object);
673 }
674
675 static void
676 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
677 {
678   if (qtdemux->posted_redirect) {
679     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
680         (_("This file contains no playable streams.")),
681         ("no known streams found, a redirect message has been posted"));
682   } else {
683     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
684         (_("This file contains no playable streams.")),
685         ("no known streams found"));
686   }
687 }
688
689 static GstBuffer *
690 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
691 {
692   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
693       mem, size, 0, size, mem, free_func);
694 }
695
696 static GstFlowReturn
697 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
698     GstBuffer ** buf)
699 {
700   GstFlowReturn flow;
701   GstMapInfo map;
702   gsize bsize;
703
704   if (G_UNLIKELY (size == 0)) {
705     GstFlowReturn ret;
706     GstBuffer *tmp = NULL;
707
708     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
709     if (ret != GST_FLOW_OK)
710       return ret;
711
712     gst_buffer_map (tmp, &map, GST_MAP_READ);
713     size = QT_UINT32 (map.data);
714     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
715
716     gst_buffer_unmap (tmp, &map);
717     gst_buffer_unref (tmp);
718   }
719
720   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
721   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
722     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
723       /* we're pulling header but already got most interesting bits,
724        * so never mind the rest (e.g. tags) (that much) */
725       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
726           size);
727       return GST_FLOW_EOS;
728     } else {
729       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
730           (_("This file is invalid and cannot be played.")),
731           ("atom has bogus size %" G_GUINT64_FORMAT, size));
732       return GST_FLOW_ERROR;
733     }
734   }
735
736   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
737
738   if (G_UNLIKELY (flow != GST_FLOW_OK))
739     return flow;
740
741   bsize = gst_buffer_get_size (*buf);
742   /* Catch short reads - we don't want any partial atoms */
743   if (G_UNLIKELY (bsize < size)) {
744     GST_WARNING_OBJECT (qtdemux,
745         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
746     gst_buffer_unref (*buf);
747     *buf = NULL;
748     return GST_FLOW_EOS;
749   }
750
751   return flow;
752 }
753
754 #if 1
755 static gboolean
756 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
757     GstFormat src_format, gint64 src_value, GstFormat dest_format,
758     gint64 * dest_value)
759 {
760   gboolean res = TRUE;
761   QtDemuxStream *stream = gst_pad_get_element_private (pad);
762   gint32 index;
763
764   if (stream->subtype != FOURCC_vide) {
765     res = FALSE;
766     goto done;
767   }
768
769   switch (src_format) {
770     case GST_FORMAT_TIME:
771       switch (dest_format) {
772         case GST_FORMAT_BYTES:{
773           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
774           if (-1 == index) {
775             res = FALSE;
776             goto done;
777           }
778
779           *dest_value = stream->samples[index].offset;
780
781           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
782               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
783               GST_TIME_ARGS (src_value), *dest_value);
784           break;
785         }
786         default:
787           res = FALSE;
788           break;
789       }
790       break;
791     case GST_FORMAT_BYTES:
792       switch (dest_format) {
793         case GST_FORMAT_TIME:{
794           index =
795               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
796               stream, src_value);
797
798           if (-1 == index) {
799             res = FALSE;
800             goto done;
801           }
802
803           *dest_value =
804               QTSTREAMTIME_TO_GSTTIME (stream,
805               stream->samples[index].timestamp);
806           GST_DEBUG_OBJECT (qtdemux,
807               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
808               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
809           break;
810         }
811         default:
812           res = FALSE;
813           break;
814       }
815       break;
816     default:
817       res = FALSE;
818       break;
819   }
820
821 done:
822   return res;
823 }
824 #endif
825
826 static gboolean
827 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
828 {
829   gboolean res = FALSE;
830
831   *duration = GST_CLOCK_TIME_NONE;
832
833   if (qtdemux->duration != 0 &&
834       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
835     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
836     res = TRUE;
837   } else {
838     *duration = GST_CLOCK_TIME_NONE;
839   }
840
841   return res;
842 }
843
844 static gboolean
845 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
846     GstQuery * query)
847 {
848   gboolean res = FALSE;
849   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
850
851   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
852
853   switch (GST_QUERY_TYPE (query)) {
854     case GST_QUERY_POSITION:{
855       GstFormat fmt;
856
857       gst_query_parse_position (query, &fmt, NULL);
858       if (fmt == GST_FORMAT_TIME
859           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
860         gst_query_set_position (query, GST_FORMAT_TIME,
861             qtdemux->segment.position);
862         res = TRUE;
863       }
864     }
865       break;
866     case GST_QUERY_DURATION:{
867       GstFormat fmt;
868
869       gst_query_parse_duration (query, &fmt, NULL);
870       if (fmt == GST_FORMAT_TIME) {
871         /* First try to query upstream */
872         res = gst_pad_query_default (pad, parent, query);
873         if (!res) {
874           GstClockTime duration;
875           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
876             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
877             res = TRUE;
878           }
879         }
880       }
881       break;
882     }
883     case GST_QUERY_CONVERT:{
884       GstFormat src_fmt, dest_fmt;
885       gint64 src_value, dest_value = 0;
886
887       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
888
889       res = gst_qtdemux_src_convert (qtdemux, pad,
890           src_fmt, src_value, dest_fmt, &dest_value);
891       if (res) {
892         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
893         res = TRUE;
894       }
895       break;
896     }
897     case GST_QUERY_FORMATS:
898       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
899       res = TRUE;
900       break;
901     case GST_QUERY_SEEKING:{
902       GstFormat fmt;
903       gboolean seekable;
904
905       /* try upstream first */
906       res = gst_pad_query_default (pad, parent, query);
907
908       if (!res) {
909         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
910         if (fmt == GST_FORMAT_TIME) {
911           GstClockTime duration;
912
913           gst_qtdemux_get_duration (qtdemux, &duration);
914           seekable = TRUE;
915           if (!qtdemux->pullbased) {
916             GstQuery *q;
917
918             /* we might be able with help from upstream */
919             seekable = FALSE;
920             q = gst_query_new_seeking (GST_FORMAT_BYTES);
921             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
922               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
923               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
924             }
925             gst_query_unref (q);
926           }
927           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
928           res = TRUE;
929         }
930       }
931       break;
932     }
933     case GST_QUERY_SEGMENT:
934     {
935       GstFormat format;
936       gint64 start, stop;
937
938       format = qtdemux->segment.format;
939
940       start =
941           gst_segment_to_stream_time (&qtdemux->segment, format,
942           qtdemux->segment.start);
943       if ((stop = qtdemux->segment.stop) == -1)
944         stop = qtdemux->segment.duration;
945       else
946         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
947
948       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
949       res = TRUE;
950       break;
951     }
952     default:
953       res = gst_pad_query_default (pad, parent, query);
954       break;
955   }
956
957   return res;
958 }
959
960 static void
961 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
962 {
963   if (G_LIKELY (stream->pad)) {
964     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
965         GST_DEBUG_PAD_NAME (stream->pad));
966
967     if (!gst_tag_list_is_empty (stream->stream_tags)) {
968       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
969           stream->stream_tags);
970       gst_pad_push_event (stream->pad,
971           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
972     }
973
974     if (G_UNLIKELY (stream->send_global_tags)) {
975       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
976           qtdemux->tag_list);
977       gst_pad_push_event (stream->pad,
978           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
979       stream->send_global_tags = FALSE;
980     }
981   }
982 }
983
984 /* push event on all source pads; takes ownership of the event */
985 static void
986 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
987 {
988   guint n;
989   gboolean has_valid_stream = FALSE;
990   GstEventType etype = GST_EVENT_TYPE (event);
991
992   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
993       GST_EVENT_TYPE_NAME (event));
994
995   for (n = 0; n < qtdemux->n_streams; n++) {
996     GstPad *pad;
997     QtDemuxStream *stream = qtdemux->streams[n];
998     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
999
1000     if ((pad = stream->pad)) {
1001       has_valid_stream = TRUE;
1002
1003       if (etype == GST_EVENT_EOS) {
1004         /* let's not send twice */
1005         if (stream->sent_eos)
1006           continue;
1007         stream->sent_eos = TRUE;
1008       }
1009
1010       gst_pad_push_event (pad, gst_event_ref (event));
1011     }
1012   }
1013
1014   gst_event_unref (event);
1015
1016   /* if it is EOS and there are no pads, post an error */
1017   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1018     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1019   }
1020 }
1021
1022 /* push a pending newsegment event, if any from the streaming thread */
1023 static void
1024 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1025 {
1026   if (qtdemux->pending_newsegment) {
1027     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1028     qtdemux->pending_newsegment = NULL;
1029   }
1030 }
1031
1032 typedef struct
1033 {
1034   guint64 media_time;
1035 } FindData;
1036
1037 static gint
1038 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1039 {
1040   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1041     return 1;
1042   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1043     return 0;
1044
1045   return -1;
1046 }
1047
1048 /* find the index of the sample that includes the data for @media_time using a
1049  * binary search.  Only to be called in optimized cases of linear search below.
1050  *
1051  * Returns the index of the sample.
1052  */
1053 static guint32
1054 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1055     guint64 media_time)
1056 {
1057   QtDemuxSample *result;
1058   guint32 index;
1059
1060   /* convert media_time to mov format */
1061   media_time =
1062       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1063
1064   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1065       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1066       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1067
1068   if (G_LIKELY (result))
1069     index = result - str->samples;
1070   else
1071     index = 0;
1072
1073   return index;
1074 }
1075
1076
1077
1078 /* find the index of the sample that includes the data for @media_offset using a
1079  * linear search
1080  *
1081  * Returns the index of the sample.
1082  */
1083 static guint32
1084 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1085     QtDemuxStream * str, gint64 media_offset)
1086 {
1087   QtDemuxSample *result = str->samples;
1088   guint32 index = 0;
1089
1090   if (result == NULL || str->n_samples == 0)
1091     return -1;
1092
1093   if (media_offset == result->offset)
1094     return index;
1095
1096   result++;
1097   while (index < str->n_samples - 1) {
1098     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1099       goto parse_failed;
1100
1101     if (media_offset < result->offset)
1102       break;
1103
1104     index++;
1105     result++;
1106   }
1107   return index;
1108
1109   /* ERRORS */
1110 parse_failed:
1111   {
1112     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1113     return -1;
1114   }
1115 }
1116
1117 /* find the index of the sample that includes the data for @media_time using a
1118  * linear search, and keeping in mind that not all samples may have been parsed
1119  * yet.  If possible, it will delegate to binary search.
1120  *
1121  * Returns the index of the sample.
1122  */
1123 static guint32
1124 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1125     GstClockTime media_time)
1126 {
1127   guint32 index = 0;
1128   guint64 mov_time;
1129   QtDemuxSample *sample;
1130
1131   /* convert media_time to mov format */
1132   mov_time =
1133       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1134
1135   sample = str->samples;
1136   if (mov_time == sample->timestamp + sample->pts_offset)
1137     return index;
1138
1139   /* use faster search if requested time in already parsed range */
1140   sample = str->samples + str->stbl_index;
1141   if (str->stbl_index >= 0 &&
1142       mov_time <= (sample->timestamp + sample->pts_offset))
1143     return gst_qtdemux_find_index (qtdemux, str, media_time);
1144
1145   while (index < str->n_samples - 1) {
1146     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1147       goto parse_failed;
1148
1149     sample = str->samples + index + 1;
1150     if (mov_time < (sample->timestamp + sample->pts_offset))
1151       break;
1152
1153     index++;
1154   }
1155   return index;
1156
1157   /* ERRORS */
1158 parse_failed:
1159   {
1160     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1161     return -1;
1162   }
1163 }
1164
1165 /* find the index of the keyframe needed to decode the sample at @index
1166  * of stream @str, or of a subsequent keyframe (depending on @next)
1167  *
1168  * Returns the index of the keyframe.
1169  */
1170 static guint32
1171 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1172     guint32 index, gboolean next)
1173 {
1174   guint32 new_index = index;
1175
1176   if (index >= str->n_samples) {
1177     new_index = str->n_samples;
1178     goto beach;
1179   }
1180
1181   /* all keyframes, return index */
1182   if (str->all_keyframe) {
1183     new_index = index;
1184     goto beach;
1185   }
1186
1187   /* else search until we have a keyframe */
1188   while (new_index < str->n_samples) {
1189     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1190       goto parse_failed;
1191
1192     if (str->samples[new_index].keyframe)
1193       break;
1194
1195     if (new_index == 0)
1196       break;
1197
1198     if (next)
1199       new_index++;
1200     else
1201       new_index--;
1202   }
1203
1204   if (new_index == str->n_samples) {
1205     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1206     new_index = -1;
1207   }
1208
1209 beach:
1210   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1211       "gave %u", next ? "after" : "before", index, new_index);
1212
1213   return new_index;
1214
1215   /* ERRORS */
1216 parse_failed:
1217   {
1218     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1219     return -1;
1220   }
1221 }
1222
1223 /* find the segment for @time_position for @stream
1224  *
1225  * Returns the index of the segment containing @time_position.
1226  * Returns the last segment and sets the @eos variable to TRUE
1227  * if the time is beyond the end. @eos may be NULL
1228  */
1229 static guint32
1230 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1231     GstClockTime time_position)
1232 {
1233   gint i;
1234   guint32 seg_idx;
1235
1236   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1237       GST_TIME_ARGS (time_position));
1238
1239   seg_idx = -1;
1240   for (i = 0; i < stream->n_segments; i++) {
1241     QtDemuxSegment *segment = &stream->segments[i];
1242
1243     GST_LOG_OBJECT (stream->pad,
1244         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1245         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1246
1247     /* For the last segment we include stop_time in the last segment */
1248     if (i < stream->n_segments - 1) {
1249       if (segment->time <= time_position && time_position < segment->stop_time) {
1250         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1251         seg_idx = i;
1252         break;
1253       }
1254     } else {
1255       /* Last segment always matches */
1256       seg_idx = i;
1257       break;
1258     }
1259   }
1260   return seg_idx;
1261 }
1262
1263 /* move the stream @str to the sample position @index.
1264  *
1265  * Updates @str->sample_index and marks discontinuity if needed.
1266  */
1267 static void
1268 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1269     guint32 index)
1270 {
1271   /* no change needed */
1272   if (index == str->sample_index)
1273     return;
1274
1275   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1276       str->n_samples);
1277
1278   /* position changed, we have a discont */
1279   str->sample_index = index;
1280   str->offset_in_sample = 0;
1281   /* Each time we move in the stream we store the position where we are
1282    * starting from */
1283   str->from_sample = index;
1284   str->discont = TRUE;
1285 }
1286
1287 static void
1288 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1289     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1290 {
1291   guint64 min_offset;
1292   gint64 min_byte_offset = -1;
1293   gint n;
1294
1295   min_offset = desired_time;
1296
1297   /* for each stream, find the index of the sample in the segment
1298    * and move back to the previous keyframe. */
1299   for (n = 0; n < qtdemux->n_streams; n++) {
1300     QtDemuxStream *str;
1301     guint32 index, kindex;
1302     guint32 seg_idx;
1303     GstClockTime media_start;
1304     GstClockTime media_time;
1305     GstClockTime seg_time;
1306     QtDemuxSegment *seg;
1307     gboolean empty_segment = FALSE;
1308
1309     str = qtdemux->streams[n];
1310
1311     if (str->sparse && !use_sparse)
1312       continue;
1313
1314     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1315     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1316
1317     /* get segment and time in the segment */
1318     seg = &str->segments[seg_idx];
1319     seg_time = (desired_time - seg->time) * seg->rate;
1320
1321     while (QTSEGMENT_IS_EMPTY (seg)) {
1322       seg_time = 0;
1323       empty_segment = TRUE;
1324       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1325           seg_idx);
1326       seg_idx++;
1327       if (seg_idx == str->n_segments)
1328         break;
1329       seg = &str->segments[seg_idx];
1330     }
1331
1332     if (seg_idx == str->n_segments) {
1333       /* FIXME track shouldn't have the last segment as empty, but if it
1334        * happens we better handle it */
1335       continue;
1336     }
1337
1338     /* get the media time in the segment */
1339     media_start = seg->media_start + seg_time;
1340
1341     /* get the index of the sample with media time */
1342     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1343     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1344         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1345         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1346         empty_segment);
1347
1348     /* shift to next frame if we are looking for next keyframe */
1349     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1350         && index < str->stbl_index)
1351       index++;
1352
1353     if (!empty_segment) {
1354       /* find previous keyframe */
1355       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1356
1357       /* we will settle for one before if none found after */
1358       if (next && kindex == -1)
1359         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1360
1361       /* if the keyframe is at a different position, we need to update the
1362        * requested seek time */
1363       if (index != kindex) {
1364         index = kindex;
1365
1366         /* get timestamp of keyframe */
1367         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1368         GST_DEBUG_OBJECT (qtdemux,
1369             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1370             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1371             str->samples[kindex].offset);
1372
1373         /* keyframes in the segment get a chance to change the
1374          * desired_offset. keyframes out of the segment are
1375          * ignored. */
1376         if (media_time >= seg->media_start) {
1377           GstClockTime seg_time;
1378
1379           /* this keyframe is inside the segment, convert back to
1380            * segment time */
1381           seg_time = (media_time - seg->media_start) + seg->time;
1382           if ((!next && (seg_time < min_offset)) ||
1383               (next && (seg_time > min_offset)))
1384             min_offset = seg_time;
1385         }
1386       }
1387     }
1388
1389     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1390       min_byte_offset = str->samples[index].offset;
1391   }
1392
1393   if (key_time)
1394     *key_time = min_offset;
1395   if (key_offset)
1396     *key_offset = min_byte_offset;
1397 }
1398
1399 static gboolean
1400 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1401     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1402 {
1403   gboolean res;
1404
1405   g_return_val_if_fail (format != NULL, FALSE);
1406   g_return_val_if_fail (cur != NULL, FALSE);
1407   g_return_val_if_fail (stop != NULL, FALSE);
1408
1409   if (*format == GST_FORMAT_TIME)
1410     return TRUE;
1411
1412   res = TRUE;
1413   if (cur_type != GST_SEEK_TYPE_NONE)
1414     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1415   if (res && stop_type != GST_SEEK_TYPE_NONE)
1416     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1417
1418   if (res)
1419     *format = GST_FORMAT_TIME;
1420
1421   return res;
1422 }
1423
1424 /* perform seek in push based mode:
1425    find BYTE position to move to based on time and delegate to upstream
1426 */
1427 static gboolean
1428 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1429 {
1430   gdouble rate;
1431   GstFormat format;
1432   GstSeekFlags flags;
1433   GstSeekType cur_type, stop_type;
1434   gint64 cur, stop, key_cur;
1435   gboolean res;
1436   gint64 byte_cur;
1437   gint64 original_stop;
1438   guint32 seqnum;
1439
1440   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1441
1442   gst_event_parse_seek (event, &rate, &format, &flags,
1443       &cur_type, &cur, &stop_type, &stop);
1444   seqnum = gst_event_get_seqnum (event);
1445
1446   /* only forward streaming and seeking is possible */
1447   if (rate <= 0)
1448     goto unsupported_seek;
1449
1450   /* convert to TIME if needed and possible */
1451   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1452           stop_type, &stop))
1453     goto no_format;
1454
1455   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1456    * the original stop position to use when upstream pushes the new segment
1457    * for this seek */
1458   original_stop = stop;
1459   stop = -1;
1460
1461   /* find reasonable corresponding BYTE position,
1462    * also try to mind about keyframes, since we can not go back a bit for them
1463    * later on */
1464   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1465    * mostly just work, but let's not yet boldly go there  ... */
1466   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1467
1468   if (byte_cur == -1)
1469     goto abort_seek;
1470
1471   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1472       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1473       stop);
1474
1475   GST_OBJECT_LOCK (qtdemux);
1476   qtdemux->seek_offset = byte_cur;
1477   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1478     qtdemux->push_seek_start = cur;
1479   } else {
1480     qtdemux->push_seek_start = key_cur;
1481   }
1482
1483   if (stop_type == GST_SEEK_TYPE_NONE) {
1484     qtdemux->push_seek_stop = qtdemux->segment.stop;
1485   } else {
1486     qtdemux->push_seek_stop = original_stop;
1487   }
1488   GST_OBJECT_UNLOCK (qtdemux);
1489
1490   /* BYTE seek event */
1491   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1492       stop_type, stop);
1493   gst_event_set_seqnum (event, seqnum);
1494   res = gst_pad_push_event (qtdemux->sinkpad, event);
1495
1496   return res;
1497
1498   /* ERRORS */
1499 abort_seek:
1500   {
1501     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1502         "seek aborted.");
1503     return FALSE;
1504   }
1505 unsupported_seek:
1506   {
1507     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1508     return FALSE;
1509   }
1510 no_format:
1511   {
1512     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1513     return FALSE;
1514   }
1515 }
1516
1517 /* perform the seek.
1518  *
1519  * We set all segment_indexes in the streams to unknown and
1520  * adjust the time_position to the desired position. this is enough
1521  * to trigger a segment switch in the streaming thread to start
1522  * streaming from the desired position.
1523  *
1524  * Keyframe seeking is a little more complicated when dealing with
1525  * segments. Ideally we want to move to the previous keyframe in
1526  * the segment but there might not be a keyframe in the segment. In
1527  * fact, none of the segments could contain a keyframe. We take a
1528  * practical approach: seek to the previous keyframe in the segment,
1529  * if there is none, seek to the beginning of the segment.
1530  *
1531  * Called with STREAM_LOCK
1532  */
1533 static gboolean
1534 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1535     guint32 seqnum, GstSeekFlags flags)
1536 {
1537   gint64 desired_offset;
1538   gint n;
1539
1540   desired_offset = segment->position;
1541
1542   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1543       GST_TIME_ARGS (desired_offset));
1544
1545   /* may not have enough fragmented info to do this adjustment,
1546    * and we can't scan (and probably should not) at this time with
1547    * possibly flushing upstream */
1548   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1549     gint64 min_offset;
1550     gboolean next, before, after;
1551
1552     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1553     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1554     next = after && !before;
1555     if (segment->rate < 0)
1556       next = !next;
1557
1558     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1559         NULL);
1560     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1561         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1562     desired_offset = min_offset;
1563   }
1564
1565   /* and set all streams to the final position */
1566   gst_flow_combiner_reset (qtdemux->flowcombiner);
1567   qtdemux->segment_seqnum = seqnum;
1568   for (n = 0; n < qtdemux->n_streams; n++) {
1569     QtDemuxStream *stream = qtdemux->streams[n];
1570
1571     stream->time_position = desired_offset;
1572     stream->accumulated_base = 0;
1573     stream->sample_index = -1;
1574     stream->offset_in_sample = 0;
1575     stream->segment_index = -1;
1576     stream->sent_eos = FALSE;
1577
1578     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1579       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1580   }
1581   segment->position = desired_offset;
1582   segment->time = desired_offset;
1583   if (segment->rate >= 0) {
1584     segment->start = desired_offset;
1585
1586     /* we stop at the end */
1587     if (segment->stop == -1)
1588       segment->stop = segment->duration;
1589   } else {
1590     segment->stop = desired_offset;
1591   }
1592
1593   if (qtdemux->fragmented)
1594     qtdemux->fragmented_seek_pending = TRUE;
1595
1596   return TRUE;
1597 }
1598
1599 /* do a seek in pull based mode */
1600 static gboolean
1601 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1602 {
1603   gdouble rate;
1604   GstFormat format;
1605   GstSeekFlags flags;
1606   GstSeekType cur_type, stop_type;
1607   gint64 cur, stop;
1608   gboolean flush;
1609   gboolean update;
1610   GstSegment seeksegment;
1611   guint32 seqnum = 0;
1612   GstEvent *flush_event;
1613
1614   if (event) {
1615     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1616
1617     gst_event_parse_seek (event, &rate, &format, &flags,
1618         &cur_type, &cur, &stop_type, &stop);
1619     seqnum = gst_event_get_seqnum (event);
1620
1621     /* we have to have a format as the segment format. Try to convert
1622      * if not. */
1623     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1624             stop_type, &stop))
1625       goto no_format;
1626
1627     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1628   } else {
1629     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1630     flags = 0;
1631   }
1632
1633   flush = flags & GST_SEEK_FLAG_FLUSH;
1634
1635   /* stop streaming, either by flushing or by pausing the task */
1636   if (flush) {
1637     flush_event = gst_event_new_flush_start ();
1638     if (seqnum)
1639       gst_event_set_seqnum (flush_event, seqnum);
1640     /* unlock upstream pull_range */
1641     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1642     /* make sure out loop function exits */
1643     gst_qtdemux_push_event (qtdemux, flush_event);
1644   } else {
1645     /* non flushing seek, pause the task */
1646     gst_pad_pause_task (qtdemux->sinkpad);
1647   }
1648
1649   /* wait for streaming to finish */
1650   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1651
1652   /* copy segment, we need this because we still need the old
1653    * segment when we close the current segment. */
1654   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1655
1656   if (event) {
1657     /* configure the segment with the seek variables */
1658     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1659     gst_segment_do_seek (&seeksegment, rate, format, flags,
1660         cur_type, cur, stop_type, stop, &update);
1661   }
1662
1663   /* now do the seek, this actually never returns FALSE */
1664   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1665
1666   /* prepare for streaming again */
1667   if (flush) {
1668     flush_event = gst_event_new_flush_stop (TRUE);
1669     if (seqnum)
1670       gst_event_set_seqnum (flush_event, seqnum);
1671
1672     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1673     gst_qtdemux_push_event (qtdemux, flush_event);
1674   }
1675
1676   /* commit the new segment */
1677   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1678
1679   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1680     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1681         qtdemux->segment.format, qtdemux->segment.position);
1682     if (seqnum)
1683       gst_message_set_seqnum (msg, seqnum);
1684     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1685   }
1686
1687   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1688   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1689       qtdemux->sinkpad, NULL);
1690
1691   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1692
1693   return TRUE;
1694
1695   /* ERRORS */
1696 no_format:
1697   {
1698     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1699     return FALSE;
1700   }
1701 }
1702
1703 static gboolean
1704 qtdemux_ensure_index (GstQTDemux * qtdemux)
1705 {
1706   guint i;
1707
1708   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1709
1710   /* Build complete index */
1711   for (i = 0; i < qtdemux->n_streams; i++) {
1712     QtDemuxStream *stream = qtdemux->streams[i];
1713
1714     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1715       goto parse_error;
1716   }
1717   return TRUE;
1718
1719   /* ERRORS */
1720 parse_error:
1721   {
1722     GST_LOG_OBJECT (qtdemux,
1723         "Building complete index of stream %u for seeking failed!", i);
1724     return FALSE;
1725   }
1726 }
1727
1728 static gboolean
1729 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1730     GstEvent * event)
1731 {
1732   gboolean res = TRUE;
1733   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1734
1735   switch (GST_EVENT_TYPE (event)) {
1736     case GST_EVENT_SEEK:
1737     {
1738 #ifndef GST_DISABLE_GST_DEBUG
1739       GstClockTime ts = gst_util_get_timestamp ();
1740 #endif
1741       guint32 seqnum = gst_event_get_seqnum (event);
1742
1743       if (seqnum == qtdemux->segment_seqnum) {
1744         GST_LOG_OBJECT (pad,
1745             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1746         gst_event_unref (event);
1747         return TRUE;
1748       }
1749
1750       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1751         /* seek should be handled by upstream, we might need to re-download fragments */
1752         GST_DEBUG_OBJECT (qtdemux,
1753             "let upstream handle seek for fragmented playback");
1754         goto upstream;
1755       }
1756
1757       /* Build complete index for seeking;
1758        * if not a fragmented file at least */
1759       if (!qtdemux->fragmented)
1760         if (!qtdemux_ensure_index (qtdemux))
1761           goto index_failed;
1762 #ifndef GST_DISABLE_GST_DEBUG
1763       ts = gst_util_get_timestamp () - ts;
1764       GST_INFO_OBJECT (qtdemux,
1765           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1766 #endif
1767     }
1768       if (qtdemux->pullbased) {
1769         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1770       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1771         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1772         res = TRUE;
1773       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1774           && !qtdemux->fragmented) {
1775         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1776       } else {
1777         GST_DEBUG_OBJECT (qtdemux,
1778             "ignoring seek in push mode in current state");
1779         res = FALSE;
1780       }
1781       gst_event_unref (event);
1782       break;
1783     default:
1784     upstream:
1785       res = gst_pad_event_default (pad, parent, event);
1786       break;
1787   }
1788
1789 done:
1790   return res;
1791
1792   /* ERRORS */
1793 index_failed:
1794   {
1795     GST_ERROR_OBJECT (qtdemux, "Index failed");
1796     gst_event_unref (event);
1797     res = FALSE;
1798     goto done;
1799   }
1800 }
1801
1802 /* stream/index return sample that is min/max w.r.t. byte position,
1803  * time is min/max w.r.t. time of samples,
1804  * the latter need not be time of the former sample */
1805 static void
1806 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1807     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1808 {
1809   gint i, n, index;
1810   gint64 time, min_time;
1811   QtDemuxStream *stream;
1812
1813   min_time = -1;
1814   stream = NULL;
1815   index = -1;
1816
1817   for (n = 0; n < qtdemux->n_streams; ++n) {
1818     QtDemuxStream *str;
1819     gint inc;
1820     gboolean set_sample;
1821
1822     str = qtdemux->streams[n];
1823     set_sample = !set;
1824
1825     if (fw) {
1826       i = 0;
1827       inc = 1;
1828     } else {
1829       i = str->n_samples - 1;
1830       inc = -1;
1831     }
1832
1833     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1834       if (str->samples[i].size == 0)
1835         continue;
1836
1837       if (fw && (str->samples[i].offset < byte_pos))
1838         continue;
1839
1840       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1841         continue;
1842
1843       /* move stream to first available sample */
1844       if (set) {
1845         gst_qtdemux_move_stream (qtdemux, str, i);
1846         set_sample = TRUE;
1847       }
1848
1849       /* avoid index from sparse streams since they might be far away */
1850       if (!str->sparse) {
1851         /* determine min/max time */
1852         time = QTSAMPLE_PTS (str, &str->samples[i]);
1853         if (min_time == -1 || (!fw && time > min_time) ||
1854             (fw && time < min_time)) {
1855           min_time = time;
1856         }
1857
1858         /* determine stream with leading sample, to get its position */
1859         if (!stream ||
1860             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1861             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1862           stream = str;
1863           index = i;
1864         }
1865       }
1866       break;
1867     }
1868
1869     /* no sample for this stream, mark eos */
1870     if (!set_sample)
1871       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1872   }
1873
1874   if (_time)
1875     *_time = min_time;
1876   if (_stream)
1877     *_stream = stream;
1878   if (_index)
1879     *_index = index;
1880 }
1881
1882 static QtDemuxStream *
1883 _create_stream (void)
1884 {
1885   QtDemuxStream *stream;
1886
1887   stream = g_new0 (QtDemuxStream, 1);
1888   /* new streams always need a discont */
1889   stream->discont = TRUE;
1890   /* we enable clipping for raw audio/video streams */
1891   stream->need_clip = FALSE;
1892   stream->need_process = FALSE;
1893   stream->segment_index = -1;
1894   stream->time_position = 0;
1895   stream->sample_index = -1;
1896   stream->offset_in_sample = 0;
1897   stream->new_stream = TRUE;
1898   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1899   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1900   stream->protected = FALSE;
1901   stream->protection_scheme_type = 0;
1902   stream->protection_scheme_version = 0;
1903   stream->protection_scheme_info = NULL;
1904   stream->n_samples_moof = 0;
1905   stream->duration_moof = 0;
1906   stream->duration_last_moof = 0;
1907   stream->alignment = 1;
1908   stream->stream_tags = gst_tag_list_new_empty ();
1909   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1910   g_queue_init (&stream->protection_scheme_event_queue);
1911   return stream;
1912 }
1913
1914 static gboolean
1915 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1916 {
1917   GstStructure *structure;
1918   const gchar *variant;
1919   const GstCaps *mediacaps = NULL;
1920
1921   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1922
1923   structure = gst_caps_get_structure (caps, 0);
1924   variant = gst_structure_get_string (structure, "variant");
1925
1926   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1927     QtDemuxStream *stream;
1928     const GValue *value;
1929
1930     demux->fragmented = TRUE;
1931     demux->mss_mode = TRUE;
1932
1933     if (demux->n_streams > 1) {
1934       /* can't do this, we can only renegotiate for another mss format */
1935       return FALSE;
1936     }
1937
1938     value = gst_structure_get_value (structure, "media-caps");
1939     /* create stream */
1940     if (value) {
1941       const GValue *timescale_v;
1942
1943       /* TODO update when stream changes during playback */
1944
1945       if (demux->n_streams == 0) {
1946         stream = _create_stream ();
1947         demux->streams[demux->n_streams] = stream;
1948         demux->n_streams = 1;
1949       } else {
1950         stream = demux->streams[0];
1951       }
1952
1953       timescale_v = gst_structure_get_value (structure, "timescale");
1954       if (timescale_v) {
1955         stream->timescale = g_value_get_uint64 (timescale_v);
1956       } else {
1957         /* default mss timescale */
1958         stream->timescale = 10000000;
1959       }
1960       demux->timescale = stream->timescale;
1961
1962       mediacaps = gst_value_get_caps (value);
1963       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1964         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1965             mediacaps);
1966         stream->new_caps = TRUE;
1967       }
1968       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1969       structure = gst_caps_get_structure (mediacaps, 0);
1970       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1971         stream->subtype = FOURCC_vide;
1972
1973         gst_structure_get_int (structure, "width", &stream->width);
1974         gst_structure_get_int (structure, "height", &stream->height);
1975         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1976             &stream->fps_d);
1977       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1978         gint rate = 0;
1979         stream->subtype = FOURCC_soun;
1980         gst_structure_get_int (structure, "channels", &stream->n_channels);
1981         gst_structure_get_int (structure, "rate", &rate);
1982         stream->rate = rate;
1983       }
1984     }
1985     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1986   } else {
1987     demux->mss_mode = FALSE;
1988   }
1989
1990   return TRUE;
1991 }
1992
1993 static void
1994 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1995 {
1996   gint n;
1997
1998   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1999   gst_pad_stop_task (qtdemux->sinkpad);
2000
2001   if (hard || qtdemux->upstream_format_is_time) {
2002     qtdemux->state = QTDEMUX_STATE_INITIAL;
2003     qtdemux->neededbytes = 16;
2004     qtdemux->todrop = 0;
2005     qtdemux->pullbased = FALSE;
2006     qtdemux->posted_redirect = FALSE;
2007     qtdemux->first_mdat = -1;
2008     qtdemux->header_size = 0;
2009     qtdemux->mdatoffset = -1;
2010     qtdemux->restoredata_offset = -1;
2011     if (qtdemux->mdatbuffer)
2012       gst_buffer_unref (qtdemux->mdatbuffer);
2013     if (qtdemux->restoredata_buffer)
2014       gst_buffer_unref (qtdemux->restoredata_buffer);
2015     qtdemux->mdatbuffer = NULL;
2016     qtdemux->restoredata_buffer = NULL;
2017     qtdemux->mdatleft = 0;
2018     qtdemux->mdatsize = 0;
2019     if (qtdemux->comp_brands)
2020       gst_buffer_unref (qtdemux->comp_brands);
2021     qtdemux->comp_brands = NULL;
2022     qtdemux->last_moov_offset = -1;
2023     if (qtdemux->moov_node_compressed) {
2024       g_node_destroy (qtdemux->moov_node_compressed);
2025       if (qtdemux->moov_node)
2026         g_free (qtdemux->moov_node->data);
2027     }
2028     qtdemux->moov_node_compressed = NULL;
2029     if (qtdemux->moov_node)
2030       g_node_destroy (qtdemux->moov_node);
2031     qtdemux->moov_node = NULL;
2032     if (qtdemux->tag_list)
2033       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2034     qtdemux->tag_list = gst_tag_list_new_empty ();
2035     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2036 #if 0
2037     if (qtdemux->element_index)
2038       gst_object_unref (qtdemux->element_index);
2039     qtdemux->element_index = NULL;
2040 #endif
2041     qtdemux->major_brand = 0;
2042     if (qtdemux->pending_newsegment)
2043       gst_event_unref (qtdemux->pending_newsegment);
2044     qtdemux->pending_newsegment = NULL;
2045     qtdemux->upstream_format_is_time = FALSE;
2046     qtdemux->upstream_seekable = FALSE;
2047     qtdemux->upstream_size = 0;
2048
2049     qtdemux->fragment_start = -1;
2050     qtdemux->fragment_start_offset = -1;
2051     qtdemux->duration = 0;
2052     qtdemux->moof_offset = 0;
2053     qtdemux->chapters_track_id = 0;
2054     qtdemux->have_group_id = FALSE;
2055     qtdemux->group_id = G_MAXUINT;
2056
2057     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2058         NULL);
2059     g_queue_clear (&qtdemux->protection_event_queue);
2060   }
2061   qtdemux->offset = 0;
2062   gst_adapter_clear (qtdemux->adapter);
2063   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2064   qtdemux->segment_seqnum = 0;
2065
2066   if (hard) {
2067     for (n = 0; n < qtdemux->n_streams; n++) {
2068       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2069       qtdemux->streams[n] = NULL;
2070     }
2071     qtdemux->n_streams = 0;
2072     qtdemux->n_video_streams = 0;
2073     qtdemux->n_audio_streams = 0;
2074     qtdemux->n_sub_streams = 0;
2075     qtdemux->exposed = FALSE;
2076     qtdemux->fragmented = FALSE;
2077     qtdemux->mss_mode = FALSE;
2078     gst_caps_replace (&qtdemux->media_caps, NULL);
2079     qtdemux->timescale = 0;
2080     qtdemux->got_moov = FALSE;
2081     if (qtdemux->protection_system_ids) {
2082       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2083       qtdemux->protection_system_ids = NULL;
2084     }
2085   } else if (qtdemux->mss_mode) {
2086     gst_flow_combiner_reset (qtdemux->flowcombiner);
2087     for (n = 0; n < qtdemux->n_streams; n++)
2088       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2089   } else {
2090     gst_flow_combiner_reset (qtdemux->flowcombiner);
2091     for (n = 0; n < qtdemux->n_streams; n++) {
2092       qtdemux->streams[n]->sent_eos = FALSE;
2093       qtdemux->streams[n]->time_position = 0;
2094       qtdemux->streams[n]->accumulated_base = 0;
2095     }
2096     if (!qtdemux->pending_newsegment) {
2097       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2098       if (qtdemux->segment_seqnum)
2099         gst_event_set_seqnum (qtdemux->pending_newsegment,
2100             qtdemux->segment_seqnum);
2101     }
2102   }
2103 }
2104
2105
2106 /* Maps the @segment to the qt edts internal segments and pushes
2107  * the correspnding segment event.
2108  *
2109  * If it ends up being at a empty segment, a gap will be pushed and the next
2110  * edts segment will be activated in sequence.
2111  *
2112  * To be used in push-mode only */
2113 static void
2114 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2115 {
2116   gint n, i;
2117
2118   for (n = 0; n < qtdemux->n_streams; n++) {
2119     QtDemuxStream *stream = qtdemux->streams[n];
2120
2121     stream->time_position = segment->start;
2122
2123     /* in push mode we should be guaranteed that we will have empty segments
2124      * at the beginning and then one segment after, other scenarios are not
2125      * supported and are discarded when parsing the edts */
2126     for (i = 0; i < stream->n_segments; i++) {
2127       if (stream->segments[i].stop_time > segment->start) {
2128         gst_qtdemux_activate_segment (qtdemux, stream, i,
2129             stream->time_position);
2130         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2131           /* push the empty segment and move to the next one */
2132           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2133               stream->time_position);
2134           continue;
2135         }
2136
2137         g_assert (i == stream->n_segments - 1);
2138       }
2139     }
2140   }
2141 }
2142
2143 static gboolean
2144 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2145     GstEvent * event)
2146 {
2147   GstQTDemux *demux = GST_QTDEMUX (parent);
2148   gboolean res = TRUE;
2149
2150   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2151
2152   switch (GST_EVENT_TYPE (event)) {
2153     case GST_EVENT_SEGMENT:
2154     {
2155       gint64 offset = 0;
2156       QtDemuxStream *stream;
2157       gint idx;
2158       GstSegment segment;
2159
2160       /* some debug output */
2161       gst_event_copy_segment (event, &segment);
2162       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2163           &segment);
2164
2165       /* erase any previously set segment */
2166       gst_event_replace (&demux->pending_newsegment, NULL);
2167
2168       if (segment.format == GST_FORMAT_TIME) {
2169         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2170         gst_event_replace (&demux->pending_newsegment, event);
2171         demux->upstream_format_is_time = TRUE;
2172       } else {
2173         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2174             "not in time format");
2175
2176         /* chain will send initial newsegment after pads have been added */
2177         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2178           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2179           goto exit;
2180         }
2181       }
2182
2183       /* check if this matches a time seek we received previously
2184        * FIXME for backwards compatibility reasons we use the
2185        * seek_offset here to compare. In the future we might want to
2186        * change this to use the seqnum as it uniquely should identify
2187        * the segment that corresponds to the seek. */
2188       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2189           ", received segment offset %" G_GINT64_FORMAT,
2190           demux->seek_offset, segment.start);
2191       if (segment.format == GST_FORMAT_BYTES
2192           && demux->seek_offset == segment.start) {
2193         GST_OBJECT_LOCK (demux);
2194         offset = segment.start;
2195
2196         segment.format = GST_FORMAT_TIME;
2197         segment.start = demux->push_seek_start;
2198         segment.stop = demux->push_seek_stop;
2199         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2200             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2201             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2202         GST_OBJECT_UNLOCK (demux);
2203       }
2204
2205       /* we only expect a BYTE segment, e.g. following a seek */
2206       if (segment.format == GST_FORMAT_BYTES) {
2207         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2208           offset = segment.start;
2209
2210           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2211               NULL, (gint64 *) & segment.start);
2212           if ((gint64) segment.start < 0)
2213             segment.start = 0;
2214         }
2215         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2216           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2217               NULL, (gint64 *) & segment.stop);
2218           /* keyframe seeking should already arrange for start >= stop,
2219            * but make sure in other rare cases */
2220           segment.stop = MAX (segment.stop, segment.start);
2221         }
2222       } else if (segment.format == GST_FORMAT_TIME) {
2223         /* push all data on the adapter before starting this
2224          * new segment */
2225         gst_qtdemux_process_adapter (demux, TRUE);
2226       } else {
2227         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2228         goto exit;
2229       }
2230
2231       /* We shouldn't modify upstream driven TIME FORMAT segment */
2232       if (!demux->upstream_format_is_time) {
2233         /* accept upstream's notion of segment and distribute along */
2234         segment.format = GST_FORMAT_TIME;
2235         segment.position = segment.time = segment.start;
2236         segment.duration = demux->segment.duration;
2237         segment.base = gst_segment_to_running_time (&demux->segment,
2238             GST_FORMAT_TIME, demux->segment.position);
2239       }
2240
2241       gst_segment_copy_into (&segment, &demux->segment);
2242       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2243
2244       /* map segment to internal qt segments and push on each stream */
2245       if (demux->n_streams) {
2246         if (demux->fragmented) {
2247           GstEvent *segment_event = gst_event_new_segment (&segment);
2248
2249           gst_event_replace (&demux->pending_newsegment, NULL);
2250           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2251           gst_qtdemux_push_event (demux, segment_event);
2252         } else {
2253           gst_event_replace (&demux->pending_newsegment, NULL);
2254           gst_qtdemux_map_and_push_segments (demux, &segment);
2255         }
2256       }
2257
2258       /* clear leftover in current segment, if any */
2259       gst_adapter_clear (demux->adapter);
2260
2261       /* set up streaming thread */
2262       demux->offset = offset;
2263       if (demux->upstream_format_is_time) {
2264         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2265             "set values to restart reading from a new atom");
2266         demux->neededbytes = 16;
2267         demux->todrop = 0;
2268       } else {
2269         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2270             NULL);
2271         if (stream) {
2272           demux->todrop = stream->samples[idx].offset - offset;
2273           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2274         } else {
2275           /* set up for EOS */
2276           demux->neededbytes = -1;
2277           demux->todrop = 0;
2278         }
2279       }
2280     exit:
2281       gst_event_unref (event);
2282       res = TRUE;
2283       goto drop;
2284     }
2285     case GST_EVENT_FLUSH_START:
2286     {
2287       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2288         gst_event_unref (event);
2289         goto drop;
2290       }
2291       break;
2292     }
2293     case GST_EVENT_FLUSH_STOP:
2294     {
2295       guint64 dur;
2296
2297       dur = demux->segment.duration;
2298       gst_qtdemux_reset (demux, FALSE);
2299       demux->segment.duration = dur;
2300
2301       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2302         gst_event_unref (event);
2303         goto drop;
2304       }
2305       break;
2306     }
2307     case GST_EVENT_EOS:
2308       /* If we are in push mode, and get an EOS before we've seen any streams,
2309        * then error out - we have nowhere to send the EOS */
2310       if (!demux->pullbased) {
2311         gint i;
2312         gboolean has_valid_stream = FALSE;
2313         for (i = 0; i < demux->n_streams; i++) {
2314           if (demux->streams[i]->pad != NULL) {
2315             has_valid_stream = TRUE;
2316             break;
2317           }
2318         }
2319         if (!has_valid_stream)
2320           gst_qtdemux_post_no_playable_stream_error (demux);
2321         else {
2322           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2323               (guint) gst_adapter_available (demux->adapter));
2324           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2325             res = FALSE;
2326           }
2327         }
2328       }
2329       break;
2330     case GST_EVENT_CAPS:{
2331       GstCaps *caps = NULL;
2332
2333       gst_event_parse_caps (event, &caps);
2334       gst_qtdemux_setcaps (demux, caps);
2335       res = TRUE;
2336       gst_event_unref (event);
2337       goto drop;
2338     }
2339     case GST_EVENT_PROTECTION:
2340     {
2341       const gchar *system_id = NULL;
2342
2343       gst_event_parse_protection (event, &system_id, NULL, NULL);
2344       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2345           system_id);
2346       gst_qtdemux_append_protection_system_id (demux, system_id);
2347       /* save the event for later, for source pads that have not been created */
2348       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2349       /* send it to all pads that already exist */
2350       gst_qtdemux_push_event (demux, event);
2351       res = TRUE;
2352       goto drop;
2353     }
2354     default:
2355       break;
2356   }
2357
2358   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2359
2360 drop:
2361   return res;
2362 }
2363
2364 #if 0
2365 static void
2366 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2367 {
2368   GstQTDemux *demux = GST_QTDEMUX (element);
2369
2370   GST_OBJECT_LOCK (demux);
2371   if (demux->element_index)
2372     gst_object_unref (demux->element_index);
2373   if (index) {
2374     demux->element_index = gst_object_ref (index);
2375   } else {
2376     demux->element_index = NULL;
2377   }
2378   GST_OBJECT_UNLOCK (demux);
2379   /* object lock might be taken again */
2380   if (index)
2381     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2382   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2383       demux->element_index, demux->index_id);
2384 }
2385
2386 static GstIndex *
2387 gst_qtdemux_get_index (GstElement * element)
2388 {
2389   GstIndex *result = NULL;
2390   GstQTDemux *demux = GST_QTDEMUX (element);
2391
2392   GST_OBJECT_LOCK (demux);
2393   if (demux->element_index)
2394     result = gst_object_ref (demux->element_index);
2395   GST_OBJECT_UNLOCK (demux);
2396
2397   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2398
2399   return result;
2400 }
2401 #endif
2402
2403 static void
2404 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2405 {
2406   g_free ((gpointer) stream->stco.data);
2407   stream->stco.data = NULL;
2408   g_free ((gpointer) stream->stsz.data);
2409   stream->stsz.data = NULL;
2410   g_free ((gpointer) stream->stsc.data);
2411   stream->stsc.data = NULL;
2412   g_free ((gpointer) stream->stts.data);
2413   stream->stts.data = NULL;
2414   g_free ((gpointer) stream->stss.data);
2415   stream->stss.data = NULL;
2416   g_free ((gpointer) stream->stps.data);
2417   stream->stps.data = NULL;
2418   g_free ((gpointer) stream->ctts.data);
2419   stream->ctts.data = NULL;
2420 }
2421
2422 static void
2423 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2424     QtDemuxStream * stream)
2425 {
2426   g_free (stream->segments);
2427   stream->segments = NULL;
2428   stream->segment_index = -1;
2429   stream->accumulated_base = 0;
2430 }
2431
2432 static void
2433 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2434     QtDemuxStream * stream)
2435 {
2436   g_free (stream->samples);
2437   stream->samples = NULL;
2438   gst_qtdemux_stbl_free (stream);
2439
2440   /* fragments */
2441   g_free (stream->ra_entries);
2442   stream->ra_entries = NULL;
2443   stream->n_ra_entries = 0;
2444
2445   stream->sample_index = -1;
2446   stream->stbl_index = -1;
2447   stream->n_samples = 0;
2448   stream->time_position = 0;
2449
2450   stream->n_samples_moof = 0;
2451   stream->duration_moof = 0;
2452   stream->duration_last_moof = 0;
2453 }
2454
2455 static void
2456 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2457 {
2458   if (stream->allocator)
2459     gst_object_unref (stream->allocator);
2460   while (stream->buffers) {
2461     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2462     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2463   }
2464   if (stream->rgb8_palette) {
2465     gst_memory_unref (stream->rgb8_palette);
2466     stream->rgb8_palette = NULL;
2467   }
2468
2469   gst_tag_list_unref (stream->stream_tags);
2470   stream->stream_tags = gst_tag_list_new_empty ();
2471   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2472   g_free (stream->redirect_uri);
2473   stream->redirect_uri = NULL;
2474   stream->sent_eos = FALSE;
2475   stream->sparse = FALSE;
2476   stream->protected = FALSE;
2477   if (stream->protection_scheme_info) {
2478     if (stream->protection_scheme_type == FOURCC_cenc) {
2479       QtDemuxCencSampleSetInfo *info =
2480           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2481       if (info->default_properties)
2482         gst_structure_free (info->default_properties);
2483       if (info->crypto_info)
2484         g_ptr_array_free (info->crypto_info, TRUE);
2485     }
2486     g_free (stream->protection_scheme_info);
2487     stream->protection_scheme_info = NULL;
2488   }
2489   stream->protection_scheme_type = 0;
2490   stream->protection_scheme_version = 0;
2491   g_queue_foreach (&stream->protection_scheme_event_queue,
2492       (GFunc) gst_event_unref, NULL);
2493   g_queue_clear (&stream->protection_scheme_event_queue);
2494   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2495   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2496 }
2497
2498 static void
2499 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2500 {
2501   gst_qtdemux_stream_clear (qtdemux, stream);
2502   if (stream->caps)
2503     gst_caps_unref (stream->caps);
2504   stream->caps = NULL;
2505   gst_tag_list_unref (stream->stream_tags);
2506   if (stream->pad) {
2507     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2508     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2509   }
2510   g_free (stream);
2511 }
2512
2513 static void
2514 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2515 {
2516   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2517
2518   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2519   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2520   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2521   qtdemux->n_streams--;
2522 }
2523
2524 static GstStateChangeReturn
2525 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2526 {
2527   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2528   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2529
2530   switch (transition) {
2531     case GST_STATE_CHANGE_PAUSED_TO_READY:
2532       break;
2533     default:
2534       break;
2535   }
2536
2537   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2538
2539   switch (transition) {
2540     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2541       gst_qtdemux_reset (qtdemux, TRUE);
2542       break;
2543     }
2544     default:
2545       break;
2546   }
2547
2548   return result;
2549 }
2550
2551 static void
2552 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2553 {
2554   /* counts as header data */
2555   qtdemux->header_size += length;
2556
2557   /* only consider at least a sufficiently complete ftyp atom */
2558   if (length >= 20) {
2559     GstBuffer *buf;
2560
2561     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2562     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2563         GST_FOURCC_ARGS (qtdemux->major_brand));
2564     if (qtdemux->comp_brands)
2565       gst_buffer_unref (qtdemux->comp_brands);
2566     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2567     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2568   }
2569 }
2570
2571 static void
2572 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2573     GstTagList * xmptaglist)
2574 {
2575   /* Strip out bogus fields */
2576   if (xmptaglist) {
2577     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2578       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2579       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2580     } else {
2581       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2582     }
2583
2584     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2585
2586     /* prioritize native tags using _KEEP mode */
2587     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2588     gst_tag_list_unref (xmptaglist);
2589   }
2590 }
2591
2592 static void
2593 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2594     guint offset)
2595 {
2596   GstByteReader br;
2597   guint8 version;
2598   guint32 flags = 0;
2599   guint i;
2600   guint8 iv_size = 8;
2601   QtDemuxStream *stream;
2602   GstStructure *structure;
2603   QtDemuxCencSampleSetInfo *ss_info = NULL;
2604   const gchar *system_id;
2605   gboolean uses_sub_sample_encryption = FALSE;
2606
2607   if (qtdemux->n_streams == 0)
2608     return;
2609
2610   stream = qtdemux->streams[0];
2611
2612   structure = gst_caps_get_structure (stream->caps, 0);
2613   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2614     GST_WARNING_OBJECT (qtdemux,
2615         "Attempting PIFF box parsing on an unencrypted stream.");
2616     return;
2617   }
2618
2619   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2620       G_TYPE_STRING, &system_id, NULL);
2621   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2622
2623   stream->protected = TRUE;
2624   stream->protection_scheme_type = FOURCC_cenc;
2625
2626   if (!stream->protection_scheme_info)
2627     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2628
2629   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2630
2631   if (ss_info->default_properties)
2632     gst_structure_free (ss_info->default_properties);
2633
2634   ss_info->default_properties =
2635       gst_structure_new ("application/x-cenc",
2636       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2637
2638   if (ss_info->crypto_info) {
2639     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2640     g_ptr_array_free (ss_info->crypto_info, TRUE);
2641     ss_info->crypto_info = NULL;
2642   }
2643
2644   /* skip UUID */
2645   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2646
2647   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2648     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2649     return;
2650   }
2651
2652   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2653     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2654     return;
2655   }
2656
2657   if ((flags & 0x000001)) {
2658     guint32 algorithm_id = 0;
2659     const guint8 *kid;
2660     GstBuffer *kid_buf;
2661     gboolean is_encrypted = TRUE;
2662
2663     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2664       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2665       return;
2666     }
2667
2668     algorithm_id >>= 8;
2669     if (algorithm_id == 0) {
2670       is_encrypted = FALSE;
2671     } else if (algorithm_id == 1) {
2672       /* FIXME: maybe store this in properties? */
2673       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2674     } else if (algorithm_id == 2) {
2675       /* FIXME: maybe store this in properties? */
2676       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2677     }
2678
2679     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2680       return;
2681
2682     if (!gst_byte_reader_get_data (&br, 16, &kid))
2683       return;
2684
2685     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2686     gst_buffer_fill (kid_buf, 0, kid, 16);
2687     if (ss_info->default_properties)
2688       gst_structure_free (ss_info->default_properties);
2689     ss_info->default_properties =
2690         gst_structure_new ("application/x-cenc",
2691         "iv_size", G_TYPE_UINT, iv_size,
2692         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2693         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2694     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2695         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2696     gst_buffer_unref (kid_buf);
2697   } else if ((flags & 0x000002)) {
2698     uses_sub_sample_encryption = TRUE;
2699   }
2700
2701   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2702     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2703     return;
2704   }
2705
2706   ss_info->crypto_info =
2707       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2708       (GDestroyNotify) qtdemux_gst_structure_free);
2709
2710   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2711     GstStructure *properties;
2712     guint8 *data;
2713     GstBuffer *buf;
2714
2715     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2716     if (properties == NULL) {
2717       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2718       return;
2719     }
2720
2721     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2722       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2723       gst_structure_free (properties);
2724       return;
2725     }
2726     buf = gst_buffer_new_wrapped (data, iv_size);
2727     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2728     gst_buffer_unref (buf);
2729
2730     if (uses_sub_sample_encryption) {
2731       guint16 n_subsamples;
2732
2733       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2734           || n_subsamples == 0) {
2735         GST_ERROR_OBJECT (qtdemux,
2736             "failed to get subsample count for sample %u", i);
2737         gst_structure_free (properties);
2738         return;
2739       }
2740       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2741       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2742         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2743             i);
2744         gst_structure_free (properties);
2745         return;
2746       }
2747       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2748       gst_structure_set (properties,
2749           "subsample_count", G_TYPE_UINT, n_subsamples,
2750           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2751       gst_buffer_unref (buf);
2752     } else {
2753       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2754     }
2755
2756     g_ptr_array_add (ss_info->crypto_info, properties);
2757   }
2758 }
2759
2760 static void
2761 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2762 {
2763   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2764     0x97, 0xA9, 0x42, 0xE8,
2765     0x9C, 0x71, 0x99, 0x94,
2766     0x91, 0xE3, 0xAF, 0xAC
2767   };
2768   static const guint8 playready_uuid[] = {
2769     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2770     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2771   };
2772
2773   static const guint8 piff_sample_encryption_uuid[] = {
2774     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2775     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2776   };
2777
2778   guint offset;
2779
2780   /* counts as header data */
2781   qtdemux->header_size += length;
2782
2783   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2784
2785   if (length <= offset + 16) {
2786     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2787     return;
2788   }
2789
2790   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2791     GstBuffer *buf;
2792     GstTagList *taglist;
2793
2794     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2795         length - offset - 16, NULL);
2796     taglist = gst_tag_list_from_xmp_buffer (buf);
2797     gst_buffer_unref (buf);
2798
2799     /* make sure we have a usable taglist */
2800     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2801
2802     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2803
2804   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2805     int len;
2806     const gunichar2 *s_utf16;
2807     char *contents;
2808
2809     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2810     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2811     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2812     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2813
2814     g_free (contents);
2815
2816     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2817         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2818         (NULL));
2819   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2820     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2821   } else {
2822     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2823         GST_READ_UINT32_LE (buffer + offset),
2824         GST_READ_UINT32_LE (buffer + offset + 4),
2825         GST_READ_UINT32_LE (buffer + offset + 8),
2826         GST_READ_UINT32_LE (buffer + offset + 12));
2827   }
2828 }
2829
2830 static void
2831 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2832 {
2833   GstSidxParser sidx_parser;
2834   GstIsoffParserResult res;
2835   guint consumed;
2836
2837   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2838
2839   res =
2840       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2841       &consumed);
2842   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2843   if (res == GST_ISOFF_QT_PARSER_DONE) {
2844     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2845   }
2846   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2847 }
2848
2849 /* caller verifies at least 8 bytes in buf */
2850 static void
2851 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2852     guint64 * plength, guint32 * pfourcc)
2853 {
2854   guint64 length;
2855   guint32 fourcc;
2856
2857   length = QT_UINT32 (data);
2858   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2859   fourcc = QT_FOURCC (data + 4);
2860   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2861
2862   if (length == 0) {
2863     length = G_MAXUINT64;
2864   } else if (length == 1 && size >= 16) {
2865     /* this means we have an extended size, which is the 64 bit value of
2866      * the next 8 bytes */
2867     length = QT_UINT64 (data + 8);
2868     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2869   }
2870
2871   if (plength)
2872     *plength = length;
2873   if (pfourcc)
2874     *pfourcc = fourcc;
2875 }
2876
2877 static gboolean
2878 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2879 {
2880   guint32 version = 0;
2881   GstClockTime duration = 0;
2882
2883   if (!gst_byte_reader_get_uint32_be (br, &version))
2884     goto failed;
2885
2886   version >>= 24;
2887   if (version == 1) {
2888     if (!gst_byte_reader_get_uint64_be (br, &duration))
2889       goto failed;
2890   } else {
2891     guint32 dur = 0;
2892
2893     if (!gst_byte_reader_get_uint32_be (br, &dur))
2894       goto failed;
2895     duration = dur;
2896   }
2897
2898   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2899   qtdemux->duration = duration;
2900
2901   return TRUE;
2902
2903 failed:
2904   {
2905     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2906     return FALSE;
2907   }
2908 }
2909
2910 static gboolean
2911 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2912     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2913 {
2914   if (!stream->parsed_trex && qtdemux->moov_node) {
2915     GNode *mvex, *trex;
2916     GstByteReader trex_data;
2917
2918     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2919     if (mvex) {
2920       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2921           &trex_data);
2922       while (trex) {
2923         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2924
2925         /* skip version/flags */
2926         if (!gst_byte_reader_skip (&trex_data, 4))
2927           goto next;
2928         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2929           goto next;
2930         if (id != stream->track_id)
2931           goto next;
2932         /* sample description index; ignore */
2933         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2934           goto next;
2935         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2936           goto next;
2937         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2938           goto next;
2939         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2940           goto next;
2941
2942         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2943             "duration %d,  size %d, flags 0x%x", stream->track_id,
2944             dur, size, flags);
2945
2946         stream->parsed_trex = TRUE;
2947         stream->def_sample_duration = dur;
2948         stream->def_sample_size = size;
2949         stream->def_sample_flags = flags;
2950
2951       next:
2952         /* iterate all siblings */
2953         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2954             &trex_data);
2955       }
2956     }
2957   }
2958
2959   *ds_duration = stream->def_sample_duration;
2960   *ds_size = stream->def_sample_size;
2961   *ds_flags = stream->def_sample_flags;
2962
2963   /* even then, above values are better than random ... */
2964   if (G_UNLIKELY (!stream->parsed_trex)) {
2965     GST_WARNING_OBJECT (qtdemux,
2966         "failed to find fragment defaults for stream %d", stream->track_id);
2967     return FALSE;
2968   }
2969
2970   return TRUE;
2971 }
2972
2973 /* This method should be called whenever a more accurate duration might
2974  * have been found. It will update all relevant variables if/where needed
2975  */
2976 static void
2977 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2978 {
2979   guint i;
2980   guint64 movdur;
2981   GstClockTime prevdur;
2982
2983   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2984
2985   if (movdur > qtdemux->duration) {
2986     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2987     GST_DEBUG_OBJECT (qtdemux,
2988         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2989         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2990     qtdemux->duration = movdur;
2991     GST_DEBUG_OBJECT (qtdemux,
2992         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2993         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2994         GST_TIME_ARGS (qtdemux->segment.stop));
2995     if (qtdemux->segment.duration == prevdur) {
2996       /* If the current segment has duration/stop identical to previous duration
2997        * update them also (because they were set at that point in time with
2998        * the wrong duration */
2999       /* We convert the value *from* the timescale version to avoid rounding errors */
3000       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3001       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3002       qtdemux->segment.duration = fixeddur;
3003       qtdemux->segment.stop = fixeddur;
3004     }
3005   }
3006   for (i = 0; i < qtdemux->n_streams; i++) {
3007     QtDemuxStream *stream = qtdemux->streams[i];
3008     if (stream) {
3009       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3010       if (movdur > stream->duration) {
3011         GST_DEBUG_OBJECT (qtdemux,
3012             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3013             GST_TIME_ARGS (duration));
3014         stream->duration = movdur;
3015         if (stream->dummy_segment) {
3016           /* Update all dummy values to new duration */
3017           stream->segments[0].stop_time = duration;
3018           stream->segments[0].duration = duration;
3019           stream->segments[0].media_stop = duration;
3020
3021           /* let downstream know we possibly have a new stop time */
3022           if (stream->segment_index != -1) {
3023             GstClockTime pos;
3024
3025             if (qtdemux->segment.rate >= 0) {
3026               pos = stream->segment.start;
3027             } else {
3028               pos = stream->segment.stop;
3029             }
3030
3031             gst_qtdemux_stream_update_segment (qtdemux, stream,
3032                 stream->segment_index, pos, NULL, NULL);
3033           }
3034         }
3035       }
3036     }
3037   }
3038 }
3039
3040 static gboolean
3041 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3042     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3043     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3044     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3045     gboolean has_tfdt)
3046 {
3047   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3048   guint64 timestamp;
3049   gint32 data_offset = 0;
3050   guint32 flags = 0, first_flags = 0, samples_count = 0;
3051   gint i;
3052   guint8 *data;
3053   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3054   QtDemuxSample *sample;
3055   gboolean ismv = FALSE;
3056   gint64 initial_offset;
3057
3058   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3059       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3060       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3061       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3062
3063   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3064     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3065     return TRUE;
3066   }
3067
3068   /* presence of stss or not can't really tell us much,
3069    * and flags and so on tend to be marginally reliable in these files */
3070   if (stream->subtype == FOURCC_soun) {
3071     GST_DEBUG_OBJECT (qtdemux,
3072         "sound track in fragmented file; marking all keyframes");
3073     stream->all_keyframe = TRUE;
3074   }
3075
3076   if (!gst_byte_reader_skip (trun, 1) ||
3077       !gst_byte_reader_get_uint24_be (trun, &flags))
3078     goto fail;
3079
3080   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3081     goto fail;
3082
3083   if (flags & TR_DATA_OFFSET) {
3084     /* note this is really signed */
3085     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3086       goto fail;
3087     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3088     /* default base offset = first byte of moof */
3089     if (*base_offset == -1) {
3090       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3091       *base_offset = moof_offset;
3092     }
3093     *running_offset = *base_offset + data_offset;
3094   } else {
3095     /* if no offset at all, that would mean data starts at moof start,
3096      * which is a bit wrong and is ismv crappy way, so compensate
3097      * assuming data is in mdat following moof */
3098     if (*base_offset == -1) {
3099       *base_offset = moof_offset + moof_length + 8;
3100       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3101       ismv = TRUE;
3102     }
3103     if (*running_offset == -1)
3104       *running_offset = *base_offset;
3105   }
3106
3107   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3108       *running_offset);
3109   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3110       data_offset, flags, samples_count);
3111
3112   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3113     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3114       GST_DEBUG_OBJECT (qtdemux,
3115           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3116       flags ^= TR_FIRST_SAMPLE_FLAGS;
3117     } else {
3118       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3119         goto fail;
3120       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3121     }
3122   }
3123
3124   /* FIXME ? spec says other bits should also be checked to determine
3125    * entry size (and prefix size for that matter) */
3126   entry_size = 0;
3127   dur_offset = size_offset = 0;
3128   if (flags & TR_SAMPLE_DURATION) {
3129     GST_LOG_OBJECT (qtdemux, "entry duration present");
3130     dur_offset = entry_size;
3131     entry_size += 4;
3132   }
3133   if (flags & TR_SAMPLE_SIZE) {
3134     GST_LOG_OBJECT (qtdemux, "entry size present");
3135     size_offset = entry_size;
3136     entry_size += 4;
3137   }
3138   if (flags & TR_SAMPLE_FLAGS) {
3139     GST_LOG_OBJECT (qtdemux, "entry flags present");
3140     flags_offset = entry_size;
3141     entry_size += 4;
3142   }
3143   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3144     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3145     ct_offset = entry_size;
3146     entry_size += 4;
3147   }
3148
3149   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3150     goto fail;
3151   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3152
3153   if (stream->n_samples + samples_count >=
3154       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3155     goto index_too_big;
3156
3157   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3158       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3159       (stream->n_samples + samples_count) *
3160       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3161
3162   /* create a new array of samples if it's the first sample parsed */
3163   if (stream->n_samples == 0) {
3164     g_assert (stream->samples == NULL);
3165     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3166     /* or try to reallocate it with space enough to insert the new samples */
3167   } else
3168     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3169         stream->n_samples + samples_count);
3170   if (stream->samples == NULL)
3171     goto out_of_memory;
3172
3173   if (qtdemux->fragment_start != -1) {
3174     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3175     qtdemux->fragment_start = -1;
3176   } else {
3177     if (stream->n_samples == 0) {
3178       if (decode_ts > 0) {
3179         timestamp = decode_ts;
3180       } else if (stream->pending_seek != NULL) {
3181         /* if we don't have a timestamp from a tfdt box, we'll use the one
3182          * from the mfra seek table */
3183         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3184             GST_TIME_ARGS (stream->pending_seek->ts));
3185
3186         /* FIXME: this is not fully correct, the timestamp refers to the random
3187          * access sample refered to in the tfra entry, which may not necessarily
3188          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3189         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3190       } else {
3191         timestamp = 0;
3192       }
3193
3194       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3195       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3196           GST_TIME_ARGS (gst_ts));
3197     } else {
3198       /* subsequent fragments extend stream */
3199       timestamp =
3200           stream->samples[stream->n_samples - 1].timestamp +
3201           stream->samples[stream->n_samples - 1].duration;
3202
3203       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3204        * difference (1 sec.) between decode_ts and timestamp, prefer the
3205        * former */
3206       if (has_tfdt && !qtdemux->upstream_format_is_time
3207           && ABSDIFF (decode_ts, timestamp) >
3208           MAX (stream->duration_last_moof / 2,
3209               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3210         GST_INFO_OBJECT (qtdemux,
3211             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3212             ") are significantly different (more than %" GST_TIME_FORMAT
3213             "), using decode_ts",
3214             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3215             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3216             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3217                     MAX (stream->duration_last_moof / 2,
3218                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3219         timestamp = decode_ts;
3220       }
3221
3222       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3223       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3224           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3225     }
3226   }
3227
3228   initial_offset = *running_offset;
3229
3230   sample = stream->samples + stream->n_samples;
3231   for (i = 0; i < samples_count; i++) {
3232     guint32 dur, size, sflags, ct;
3233
3234     /* first read sample data */
3235     if (flags & TR_SAMPLE_DURATION) {
3236       dur = QT_UINT32 (data + dur_offset);
3237     } else {
3238       dur = d_sample_duration;
3239     }
3240     if (flags & TR_SAMPLE_SIZE) {
3241       size = QT_UINT32 (data + size_offset);
3242     } else {
3243       size = d_sample_size;
3244     }
3245     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3246       if (i == 0) {
3247         sflags = first_flags;
3248       } else {
3249         sflags = d_sample_flags;
3250       }
3251     } else if (flags & TR_SAMPLE_FLAGS) {
3252       sflags = QT_UINT32 (data + flags_offset);
3253     } else {
3254       sflags = d_sample_flags;
3255     }
3256     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3257       ct = QT_UINT32 (data + ct_offset);
3258     } else {
3259       ct = 0;
3260     }
3261     data += entry_size;
3262
3263     /* fill the sample information */
3264     sample->offset = *running_offset;
3265     sample->pts_offset = ct;
3266     sample->size = size;
3267     sample->timestamp = timestamp;
3268     sample->duration = dur;
3269     /* sample-is-difference-sample */
3270     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3271      * now idea how it relates to bitfield other than massive LE/BE confusion */
3272     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3273     *running_offset += size;
3274     timestamp += dur;
3275     stream->duration_moof += dur;
3276     sample++;
3277   }
3278
3279   /* Update total duration if needed */
3280   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3281
3282   /* Pre-emptively figure out size of mdat based on trun information.
3283    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3284    * size, else we will still be able to use this when dealing with gap'ed
3285    * input */
3286   qtdemux->mdatleft = *running_offset - initial_offset;
3287   qtdemux->mdatoffset = initial_offset;
3288   qtdemux->mdatsize = qtdemux->mdatleft;
3289
3290   stream->n_samples += samples_count;
3291   stream->n_samples_moof += samples_count;
3292
3293   if (stream->pending_seek != NULL)
3294     stream->pending_seek = NULL;
3295
3296   return TRUE;
3297
3298 fail:
3299   {
3300     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3301     return FALSE;
3302   }
3303 out_of_memory:
3304   {
3305     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3306         stream->n_samples);
3307     return FALSE;
3308   }
3309 index_too_big:
3310   {
3311     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3312         "be larger than %uMB (broken file?)", stream->n_samples,
3313         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3314     return FALSE;
3315   }
3316 }
3317
3318 /* find stream with @id */
3319 static inline QtDemuxStream *
3320 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3321 {
3322   QtDemuxStream *stream;
3323   gint i;
3324
3325   /* check */
3326   if (G_UNLIKELY (!id)) {
3327     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3328     return NULL;
3329   }
3330
3331   /* try to get it fast and simple */
3332   if (G_LIKELY (id <= qtdemux->n_streams)) {
3333     stream = qtdemux->streams[id - 1];
3334     if (G_LIKELY (stream->track_id == id))
3335       return stream;
3336   }
3337
3338   /* linear search otherwise */
3339   for (i = 0; i < qtdemux->n_streams; i++) {
3340     stream = qtdemux->streams[i];
3341     if (stream->track_id == id)
3342       return stream;
3343   }
3344   if (qtdemux->mss_mode) {
3345     /* mss should have only 1 stream anyway */
3346     return qtdemux->streams[0];
3347   }
3348
3349   return NULL;
3350 }
3351
3352 static gboolean
3353 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3354     guint32 * fragment_number)
3355 {
3356   if (!gst_byte_reader_skip (mfhd, 4))
3357     goto fail;
3358   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3359     goto fail;
3360   return TRUE;
3361 fail:
3362   {
3363     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3364     return FALSE;
3365   }
3366 }
3367
3368 static gboolean
3369 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3370     QtDemuxStream ** stream, guint32 * default_sample_duration,
3371     guint32 * default_sample_size, guint32 * default_sample_flags,
3372     gint64 * base_offset)
3373 {
3374   guint32 flags = 0;
3375   guint32 track_id = 0;
3376
3377   if (!gst_byte_reader_skip (tfhd, 1) ||
3378       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3379     goto invalid_track;
3380
3381   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3382     goto invalid_track;
3383
3384   *stream = qtdemux_find_stream (qtdemux, track_id);
3385   if (G_UNLIKELY (!*stream))
3386     goto unknown_stream;
3387
3388   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3389     *base_offset = qtdemux->moof_offset;
3390
3391   if (flags & TF_BASE_DATA_OFFSET)
3392     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3393       goto invalid_track;
3394
3395   /* obtain stream defaults */
3396   qtdemux_parse_trex (qtdemux, *stream,
3397       default_sample_duration, default_sample_size, default_sample_flags);
3398
3399   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3400   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3401     if (!gst_byte_reader_skip (tfhd, 4))
3402       goto invalid_track;
3403
3404   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3405     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3406       goto invalid_track;
3407
3408   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3409     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3410       goto invalid_track;
3411
3412   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3413     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3414       goto invalid_track;
3415
3416   return TRUE;
3417
3418 invalid_track:
3419   {
3420     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3421     return FALSE;
3422   }
3423 unknown_stream:
3424   {
3425     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3426     return TRUE;
3427   }
3428 }
3429
3430 static gboolean
3431 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3432     guint64 * decode_time)
3433 {
3434   guint32 version = 0;
3435
3436   if (!gst_byte_reader_get_uint32_be (br, &version))
3437     return FALSE;
3438
3439   version >>= 24;
3440   if (version == 1) {
3441     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3442       goto failed;
3443   } else {
3444     guint32 dec_time = 0;
3445     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3446       goto failed;
3447     *decode_time = dec_time;
3448   }
3449
3450   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3451       *decode_time);
3452
3453   return TRUE;
3454
3455 failed:
3456   {
3457     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3458     return FALSE;
3459   }
3460 }
3461
3462 /* Returns a pointer to a GstStructure containing the properties of
3463  * the stream sample identified by @sample_index. The caller must unref
3464  * the returned object after use. Returns NULL if unsuccessful. */
3465 static GstStructure *
3466 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3467     QtDemuxStream * stream, guint sample_index)
3468 {
3469   QtDemuxCencSampleSetInfo *info = NULL;
3470
3471   g_return_val_if_fail (stream != NULL, NULL);
3472   g_return_val_if_fail (stream->protected, NULL);
3473   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3474
3475   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3476
3477   /* Currently, cenc properties for groups of samples are not supported, so
3478    * simply return a copy of the default sample properties */
3479   return gst_structure_copy (info->default_properties);
3480 }
3481
3482 /* Parses the sizes of sample auxiliary information contained within a stream,
3483  * as given in a saiz box. Returns array of sample_count guint8 size values,
3484  * or NULL on failure */
3485 static guint8 *
3486 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3487     GstByteReader * br, guint32 * sample_count)
3488 {
3489   guint32 flags = 0;
3490   guint8 *info_sizes;
3491   guint8 default_info_size;
3492
3493   g_return_val_if_fail (qtdemux != NULL, NULL);
3494   g_return_val_if_fail (stream != NULL, NULL);
3495   g_return_val_if_fail (br != NULL, NULL);
3496   g_return_val_if_fail (sample_count != NULL, NULL);
3497
3498   if (!gst_byte_reader_get_uint32_be (br, &flags))
3499     return NULL;
3500
3501   if (flags & 0x1) {
3502     /* aux_info_type and aux_info_type_parameter are ignored */
3503     if (!gst_byte_reader_skip (br, 8))
3504       return NULL;
3505   }
3506
3507   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3508     return NULL;
3509   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3510
3511   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3512     return NULL;
3513   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3514
3515
3516   if (default_info_size == 0) {
3517     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3518       return NULL;
3519     }
3520   } else {
3521     info_sizes = g_new (guint8, *sample_count);
3522     memset (info_sizes, default_info_size, *sample_count);
3523   }
3524
3525   return info_sizes;
3526 }
3527
3528 /* Parses the offset of sample auxiliary information contained within a stream,
3529  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3530 static gboolean
3531 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3532     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3533     guint64 * offset)
3534 {
3535   guint8 version = 0;
3536   guint32 flags = 0;
3537   guint32 aux_info_type = 0;
3538   guint32 aux_info_type_parameter = 0;
3539   guint32 entry_count;
3540   guint32 off_32;
3541   guint64 off_64;
3542   const guint8 *aux_info_type_data = NULL;
3543
3544   g_return_val_if_fail (qtdemux != NULL, FALSE);
3545   g_return_val_if_fail (stream != NULL, FALSE);
3546   g_return_val_if_fail (br != NULL, FALSE);
3547   g_return_val_if_fail (offset != NULL, FALSE);
3548
3549   if (!gst_byte_reader_get_uint8 (br, &version))
3550     return FALSE;
3551
3552   if (!gst_byte_reader_get_uint24_be (br, &flags))
3553     return FALSE;
3554
3555   if (flags & 0x1) {
3556
3557     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3558       return FALSE;
3559     aux_info_type = QT_FOURCC (aux_info_type_data);
3560
3561     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3562       return FALSE;
3563   } else if (stream->protected) {
3564     aux_info_type = stream->protection_scheme_type;
3565   } else {
3566     aux_info_type = stream->fourcc;
3567   }
3568
3569   if (info_type)
3570     *info_type = aux_info_type;
3571   if (info_type_parameter)
3572     *info_type_parameter = aux_info_type_parameter;
3573
3574   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3575       "aux_info_type_parameter:  %#06x",
3576       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3577
3578   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3579     return FALSE;
3580
3581   if (entry_count != 1) {
3582     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3583     return FALSE;
3584   }
3585
3586   if (version == 0) {
3587     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3588       return FALSE;
3589     *offset = (guint64) off_32;
3590   } else {
3591     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3592       return FALSE;
3593     *offset = off_64;
3594   }
3595
3596   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3597   return TRUE;
3598 }
3599
3600 static void
3601 qtdemux_gst_structure_free (GstStructure * gststructure)
3602 {
3603   if (gststructure) {
3604     gst_structure_free (gststructure);
3605   }
3606 }
3607
3608 /* Parses auxiliary information relating to samples protected using Common
3609  * Encryption (cenc); the format of this information is defined in
3610  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3611 static gboolean
3612 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3613     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3614 {
3615   QtDemuxCencSampleSetInfo *ss_info = NULL;
3616   guint8 size;
3617   gint i;
3618   GPtrArray *old_crypto_info = NULL;
3619   guint old_entries = 0;
3620
3621   g_return_val_if_fail (qtdemux != NULL, FALSE);
3622   g_return_val_if_fail (stream != NULL, FALSE);
3623   g_return_val_if_fail (br != NULL, FALSE);
3624   g_return_val_if_fail (stream->protected, FALSE);
3625   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3626
3627   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3628
3629   if (ss_info->crypto_info) {
3630     old_crypto_info = ss_info->crypto_info;
3631     /* Count number of non-null entries remaining at the tail end */
3632     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3633       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3634         break;
3635       old_entries++;
3636     }
3637   }
3638
3639   ss_info->crypto_info =
3640       g_ptr_array_new_full (sample_count + old_entries,
3641       (GDestroyNotify) qtdemux_gst_structure_free);
3642
3643   /* We preserve old entries because we parse the next moof in advance
3644    * of consuming all samples from the previous moof, and otherwise
3645    * we'd discard the corresponding crypto info for the samples
3646    * from the previous fragment. */
3647   if (old_entries) {
3648     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3649         old_entries);
3650     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3651       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3652               i));
3653       g_ptr_array_index (old_crypto_info, i) = NULL;
3654     }
3655   }
3656
3657   if (old_crypto_info) {
3658     /* Everything now belongs to the new array */
3659     g_ptr_array_free (old_crypto_info, TRUE);
3660   }
3661
3662   for (i = 0; i < sample_count; ++i) {
3663     GstStructure *properties;
3664     guint16 n_subsamples = 0;
3665     guint8 *data;
3666     guint iv_size;
3667     GstBuffer *buf;
3668
3669     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3670     if (properties == NULL) {
3671       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3672       return FALSE;
3673     }
3674     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3675       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3676       gst_structure_free (properties);
3677       return FALSE;
3678     }
3679     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3680       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3681       gst_structure_free (properties);
3682       return FALSE;
3683     }
3684     buf = gst_buffer_new_wrapped (data, iv_size);
3685     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3686     gst_buffer_unref (buf);
3687     size = info_sizes[i];
3688     if (size > iv_size) {
3689       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3690           || !(n_subsamples > 0)) {
3691         gst_structure_free (properties);
3692         GST_ERROR_OBJECT (qtdemux,
3693             "failed to get subsample count for sample %u", i);
3694         return FALSE;
3695       }
3696       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3697       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3698         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3699             i);
3700         gst_structure_free (properties);
3701         return FALSE;
3702       }
3703       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3704       if (!buf) {
3705         gst_structure_free (properties);
3706         return FALSE;
3707       }
3708       gst_structure_set (properties,
3709           "subsample_count", G_TYPE_UINT, n_subsamples,
3710           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3711       gst_buffer_unref (buf);
3712     } else {
3713       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3714     }
3715     g_ptr_array_add (ss_info->crypto_info, properties);
3716   }
3717   return TRUE;
3718 }
3719
3720 /* Converts a UUID in raw byte form to a string representation, as defined in
3721  * RFC 4122. The caller takes ownership of the returned string and is
3722  * responsible for freeing it after use. */
3723 static gchar *
3724 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3725 {
3726   const guint8 *uuid = (const guint8 *) uuid_bytes;
3727
3728   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3729       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3730       uuid[0], uuid[1], uuid[2], uuid[3],
3731       uuid[4], uuid[5], uuid[6], uuid[7],
3732       uuid[8], uuid[9], uuid[10], uuid[11],
3733       uuid[12], uuid[13], uuid[14], uuid[15]);
3734 }
3735
3736 /* Parses a Protection System Specific Header box (pssh), as defined in the
3737  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3738  * information needed by a specific content protection system in order to
3739  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3740  * otherwise. */
3741 static gboolean
3742 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3743 {
3744   gchar *sysid_string;
3745   guint32 pssh_size = QT_UINT32 (node->data);
3746   GstBuffer *pssh = NULL;
3747   GstEvent *event = NULL;
3748   guint32 parent_box_type;
3749   gint i;
3750
3751   if (G_UNLIKELY (pssh_size < 32U)) {
3752     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3753     return FALSE;
3754   }
3755
3756   sysid_string =
3757       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3758
3759   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3760
3761   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3762   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3763       gst_buffer_get_size (pssh));
3764
3765   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3766
3767   /* Push an event containing the pssh box onto the queues of all streams. */
3768   event = gst_event_new_protection (sysid_string, pssh,
3769       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3770   for (i = 0; i < qtdemux->n_streams; ++i) {
3771     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3772         gst_event_ref (event));
3773   }
3774   g_free (sysid_string);
3775   gst_event_unref (event);
3776   gst_buffer_unref (pssh);
3777   return TRUE;
3778 }
3779
3780 static gboolean
3781 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3782     guint64 moof_offset, QtDemuxStream * stream)
3783 {
3784   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3785   GNode *uuid_node;
3786   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3787   GNode *saiz_node, *saio_node, *pssh_node;
3788   GstByteReader saiz_data, saio_data;
3789   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3790   gint64 base_offset, running_offset;
3791   guint32 frag_num;
3792
3793   /* NOTE @stream ignored */
3794
3795   moof_node = g_node_new ((guint8 *) buffer);
3796   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3797   qtdemux_node_dump (qtdemux, moof_node);
3798
3799   /* Get fragment number from mfhd and check it's valid */
3800   mfhd_node =
3801       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3802   if (mfhd_node == NULL)
3803     goto missing_mfhd;
3804   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3805     goto fail;
3806   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3807
3808   /* unknown base_offset to start with */
3809   base_offset = running_offset = -1;
3810   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3811   while (traf_node) {
3812     guint64 decode_time = 0;
3813
3814     /* Fragment Header node */
3815     tfhd_node =
3816         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3817         &tfhd_data);
3818     if (!tfhd_node)
3819       goto missing_tfhd;
3820     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3821             &ds_size, &ds_flags, &base_offset))
3822       goto missing_tfhd;
3823
3824     /* The following code assumes at most a single set of sample auxiliary
3825      * data in the fragment (consisting of a saiz box and a corresponding saio
3826      * box); in theory, however, there could be multiple sets of sample
3827      * auxiliary data in a fragment. */
3828     saiz_node =
3829         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3830         &saiz_data);
3831     if (saiz_node) {
3832       guint32 info_type = 0;
3833       guint64 offset = 0;
3834       guint32 info_type_parameter = 0;
3835
3836       g_free (qtdemux->cenc_aux_info_sizes);
3837
3838       qtdemux->cenc_aux_info_sizes =
3839           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3840           &qtdemux->cenc_aux_sample_count);
3841       if (qtdemux->cenc_aux_info_sizes == NULL) {
3842         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3843         goto fail;
3844       }
3845       saio_node =
3846           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3847           &saio_data);
3848       if (!saio_node) {
3849         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3850         g_free (qtdemux->cenc_aux_info_sizes);
3851         qtdemux->cenc_aux_info_sizes = NULL;
3852         goto fail;
3853       }
3854
3855       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3856                   &info_type, &info_type_parameter, &offset))) {
3857         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3858         g_free (qtdemux->cenc_aux_info_sizes);
3859         qtdemux->cenc_aux_info_sizes = NULL;
3860         goto fail;
3861       }
3862       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3863         offset += (guint64) (base_offset - qtdemux->moof_offset);
3864       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3865         GstByteReader br;
3866         if (offset > length) {
3867           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3868           qtdemux->cenc_aux_info_offset = offset;
3869         } else {
3870           gst_byte_reader_init (&br, buffer + offset, length - offset);
3871           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3872                   qtdemux->cenc_aux_info_sizes,
3873                   qtdemux->cenc_aux_sample_count)) {
3874             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3875             g_free (qtdemux->cenc_aux_info_sizes);
3876             qtdemux->cenc_aux_info_sizes = NULL;
3877             goto fail;
3878           }
3879         }
3880       }
3881     }
3882
3883     tfdt_node =
3884         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3885         &tfdt_data);
3886     if (tfdt_node) {
3887       /* We'll use decode_time to interpolate timestamps
3888        * in case the input timestamps are missing */
3889       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3890
3891       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3892           " (%" GST_TIME_FORMAT ")", decode_time,
3893           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3894
3895       /* Discard the fragment buffer timestamp info to avoid using it.
3896        * Rely on tfdt instead as it is more accurate than the timestamp
3897        * that is fetched from a manifest/playlist and is usually
3898        * less accurate. */
3899       qtdemux->fragment_start = -1;
3900     }
3901
3902     if (G_UNLIKELY (!stream)) {
3903       /* we lost track of offset, we'll need to regain it,
3904        * but can delay complaining until later or avoid doing so altogether */
3905       base_offset = -2;
3906       goto next;
3907     }
3908     if (G_UNLIKELY (base_offset < -1))
3909       goto lost_offset;
3910
3911     if (qtdemux->upstream_format_is_time)
3912       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3913
3914     /* initialise moof sample data */
3915     stream->n_samples_moof = 0;
3916     stream->duration_last_moof = stream->duration_moof;
3917     stream->duration_moof = 0;
3918
3919     /* Track Run node */
3920     trun_node =
3921         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3922         &trun_data);
3923     while (trun_node) {
3924       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3925           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3926           &running_offset, decode_time, (tfdt_node != NULL));
3927       /* iterate all siblings */
3928       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3929           &trun_data);
3930     }
3931
3932     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3933     if (uuid_node) {
3934       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3935       guint32 box_length = QT_UINT32 (uuid_buffer);
3936
3937       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3938     }
3939
3940     /* if no new base_offset provided for next traf,
3941      * base is end of current traf */
3942     base_offset = running_offset;
3943     running_offset = -1;
3944
3945     if (stream->n_samples_moof && stream->duration_moof)
3946       stream->new_caps = TRUE;
3947
3948   next:
3949     /* iterate all siblings */
3950     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3951   }
3952
3953   /* parse any protection system info */
3954   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3955   while (pssh_node) {
3956     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3957     qtdemux_parse_pssh (qtdemux, pssh_node);
3958     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3959   }
3960
3961   g_node_destroy (moof_node);
3962   return TRUE;
3963
3964 missing_tfhd:
3965   {
3966     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3967     goto fail;
3968   }
3969 missing_mfhd:
3970   {
3971     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3972     goto fail;
3973   }
3974 lost_offset:
3975   {
3976     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3977     goto fail;
3978   }
3979 fail:
3980   {
3981     g_node_destroy (moof_node);
3982     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3983         (_("This file is corrupt and cannot be played.")), (NULL));
3984     return FALSE;
3985   }
3986 }
3987
3988 #if 0
3989 /* might be used if some day we actually use mfra & co
3990  * for random access to fragments,
3991  * but that will require quite some modifications and much less relying
3992  * on a sample array */
3993 #endif
3994
3995 static gboolean
3996 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3997 {
3998   QtDemuxStream *stream;
3999   guint32 ver_flags, track_id, len, num_entries, i;
4000   guint value_size, traf_size, trun_size, sample_size;
4001   guint64 time = 0, moof_offset = 0;
4002 #if 0
4003   GstBuffer *buf = NULL;
4004   GstFlowReturn ret;
4005 #endif
4006   GstByteReader tfra;
4007
4008   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4009
4010   if (!gst_byte_reader_skip (&tfra, 8))
4011     return FALSE;
4012
4013   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4014     return FALSE;
4015
4016   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4017       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4018       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4019     return FALSE;
4020
4021   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4022
4023   stream = qtdemux_find_stream (qtdemux, track_id);
4024   if (stream == NULL)
4025     goto unknown_trackid;
4026
4027   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4028   sample_size = (len & 3) + 1;
4029   trun_size = ((len & 12) >> 2) + 1;
4030   traf_size = ((len & 48) >> 4) + 1;
4031
4032   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4033       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4034
4035   if (num_entries == 0)
4036     goto no_samples;
4037
4038   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4039           value_size + value_size + traf_size + trun_size + sample_size))
4040     goto corrupt_file;
4041
4042   g_free (stream->ra_entries);
4043   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4044   stream->n_ra_entries = num_entries;
4045
4046   for (i = 0; i < num_entries; i++) {
4047     qt_atom_parser_get_offset (&tfra, value_size, &time);
4048     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4049     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4050     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4051     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4052
4053     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4054
4055     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4056         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4057
4058     stream->ra_entries[i].ts = time;
4059     stream->ra_entries[i].moof_offset = moof_offset;
4060
4061     /* don't want to go through the entire file and read all moofs at startup */
4062 #if 0
4063     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4064     if (ret != GST_FLOW_OK)
4065       goto corrupt_file;
4066     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4067         moof_offset, stream);
4068     gst_buffer_unref (buf);
4069 #endif
4070   }
4071
4072   check_update_duration (qtdemux, time);
4073
4074   return TRUE;
4075
4076 /* ERRORS */
4077 unknown_trackid:
4078   {
4079     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4080     return FALSE;
4081   }
4082 corrupt_file:
4083   {
4084     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4085     return FALSE;
4086   }
4087 no_samples:
4088   {
4089     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4090     return FALSE;
4091   }
4092 }
4093
4094 static gboolean
4095 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4096 {
4097   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4098   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4099   GstBuffer *mfro = NULL, *mfra = NULL;
4100   GstFlowReturn flow;
4101   gboolean ret = FALSE;
4102   GNode *mfra_node, *tfra_node;
4103   guint64 mfra_offset = 0;
4104   guint32 fourcc, mfra_size;
4105   gint64 len;
4106
4107   /* query upstream size in bytes */
4108   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4109     goto size_query_failed;
4110
4111   /* mfro box should be at the very end of the file */
4112   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4113   if (flow != GST_FLOW_OK)
4114     goto exit;
4115
4116   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4117
4118   fourcc = QT_FOURCC (mfro_map.data + 4);
4119   if (fourcc != FOURCC_mfro)
4120     goto exit;
4121
4122   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4123   if (mfro_map.size < 16)
4124     goto invalid_mfro_size;
4125
4126   mfra_size = QT_UINT32 (mfro_map.data + 12);
4127   if (mfra_size >= len)
4128     goto invalid_mfra_size;
4129
4130   mfra_offset = len - mfra_size;
4131
4132   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4133       mfra_offset, mfra_size);
4134
4135   /* now get and parse mfra box */
4136   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4137   if (flow != GST_FLOW_OK)
4138     goto broken_file;
4139
4140   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4141
4142   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4143   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4144
4145   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4146
4147   while (tfra_node) {
4148     qtdemux_parse_tfra (qtdemux, tfra_node);
4149     /* iterate all siblings */
4150     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4151   }
4152   g_node_destroy (mfra_node);
4153
4154   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4155   ret = TRUE;
4156
4157 exit:
4158
4159   if (mfro) {
4160     if (mfro_map.memory != NULL)
4161       gst_buffer_unmap (mfro, &mfro_map);
4162     gst_buffer_unref (mfro);
4163   }
4164   if (mfra) {
4165     if (mfra_map.memory != NULL)
4166       gst_buffer_unmap (mfra, &mfra_map);
4167     gst_buffer_unref (mfra);
4168   }
4169   return ret;
4170
4171 /* ERRORS */
4172 size_query_failed:
4173   {
4174     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4175     goto exit;
4176   }
4177 invalid_mfro_size:
4178   {
4179     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4180     goto exit;
4181   }
4182 invalid_mfra_size:
4183   {
4184     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4185     goto exit;
4186   }
4187 broken_file:
4188   {
4189     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4190     goto exit;
4191   }
4192 }
4193
4194 static guint64
4195 add_offset (guint64 offset, guint64 advance)
4196 {
4197   /* Avoid 64-bit overflow by clamping */
4198   if (offset > G_MAXUINT64 - advance)
4199     return G_MAXUINT64;
4200   return offset + advance;
4201 }
4202
4203 static GstFlowReturn
4204 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4205 {
4206   guint64 length = 0;
4207   guint32 fourcc = 0;
4208   GstBuffer *buf = NULL;
4209   GstFlowReturn ret = GST_FLOW_OK;
4210   guint64 cur_offset = qtdemux->offset;
4211   GstMapInfo map;
4212
4213   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4214   if (G_UNLIKELY (ret != GST_FLOW_OK))
4215     goto beach;
4216   gst_buffer_map (buf, &map, GST_MAP_READ);
4217   if (G_LIKELY (map.size >= 8))
4218     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4219   gst_buffer_unmap (buf, &map);
4220   gst_buffer_unref (buf);
4221
4222   /* maybe we already got most we needed, so only consider this eof */
4223   if (G_UNLIKELY (length == 0)) {
4224     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4225         (_("Invalid atom size.")),
4226         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4227             GST_FOURCC_ARGS (fourcc)));
4228     ret = GST_FLOW_EOS;
4229     goto beach;
4230   }
4231
4232   switch (fourcc) {
4233     case FOURCC_moof:
4234       /* record for later parsing when needed */
4235       if (!qtdemux->moof_offset) {
4236         qtdemux->moof_offset = qtdemux->offset;
4237       }
4238       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4239         /* FIXME */
4240       } else {
4241         qtdemux->offset += length;      /* skip moof and keep going */
4242       }
4243       if (qtdemux->got_moov) {
4244         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4245         ret = GST_FLOW_EOS;
4246         goto beach;
4247       }
4248       break;
4249     case FOURCC_mdat:
4250     case FOURCC_free:
4251     case FOURCC_wide:
4252     case FOURCC_PICT:
4253     case FOURCC_pnot:
4254     {
4255       GST_LOG_OBJECT (qtdemux,
4256           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4257           GST_FOURCC_ARGS (fourcc), cur_offset);
4258       qtdemux->offset = add_offset (qtdemux->offset, length);
4259       break;
4260     }
4261     case FOURCC_moov:
4262     {
4263       GstBuffer *moov = NULL;
4264
4265       if (qtdemux->got_moov) {
4266         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4267         qtdemux->offset = add_offset (qtdemux->offset, length);
4268         goto beach;
4269       }
4270
4271       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4272       if (ret != GST_FLOW_OK)
4273         goto beach;
4274       gst_buffer_map (moov, &map, GST_MAP_READ);
4275
4276       if (length != map.size) {
4277         /* Some files have a 'moov' atom at the end of the file which contains
4278          * a terminal 'free' atom where the body of the atom is missing.
4279          * Check for, and permit, this special case.
4280          */
4281         if (map.size >= 8) {
4282           guint8 *final_data = map.data + (map.size - 8);
4283           guint32 final_length = QT_UINT32 (final_data);
4284           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4285
4286           if (final_fourcc == FOURCC_free
4287               && map.size + final_length - 8 == length) {
4288             /* Ok, we've found that special case. Allocate a new buffer with
4289              * that free atom actually present. */
4290             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4291             gst_buffer_fill (newmoov, 0, map.data, map.size);
4292             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4293             gst_buffer_unmap (moov, &map);
4294             gst_buffer_unref (moov);
4295             moov = newmoov;
4296             gst_buffer_map (moov, &map, GST_MAP_READ);
4297           }
4298         }
4299       }
4300
4301       if (length != map.size) {
4302         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4303             (_("This file is incomplete and cannot be played.")),
4304             ("We got less than expected (received %" G_GSIZE_FORMAT
4305                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4306                 (guint) length, cur_offset));
4307         gst_buffer_unmap (moov, &map);
4308         gst_buffer_unref (moov);
4309         ret = GST_FLOW_ERROR;
4310         goto beach;
4311       }
4312       qtdemux->offset += length;
4313
4314       qtdemux_parse_moov (qtdemux, map.data, length);
4315       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4316
4317       qtdemux_parse_tree (qtdemux);
4318       if (qtdemux->moov_node_compressed) {
4319         g_node_destroy (qtdemux->moov_node_compressed);
4320         g_free (qtdemux->moov_node->data);
4321       }
4322       qtdemux->moov_node_compressed = NULL;
4323       g_node_destroy (qtdemux->moov_node);
4324       qtdemux->moov_node = NULL;
4325       gst_buffer_unmap (moov, &map);
4326       gst_buffer_unref (moov);
4327       qtdemux->got_moov = TRUE;
4328
4329       break;
4330     }
4331     case FOURCC_ftyp:
4332     {
4333       GstBuffer *ftyp = NULL;
4334
4335       /* extract major brand; might come in handy for ISO vs QT issues */
4336       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4337       if (ret != GST_FLOW_OK)
4338         goto beach;
4339       qtdemux->offset += length;
4340       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4341       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4342       gst_buffer_unmap (ftyp, &map);
4343       gst_buffer_unref (ftyp);
4344       break;
4345     }
4346     case FOURCC_uuid:
4347     {
4348       GstBuffer *uuid = NULL;
4349
4350       /* uuid are extension atoms */
4351       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4352       if (ret != GST_FLOW_OK)
4353         goto beach;
4354       qtdemux->offset += length;
4355       gst_buffer_map (uuid, &map, GST_MAP_READ);
4356       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4357       gst_buffer_unmap (uuid, &map);
4358       gst_buffer_unref (uuid);
4359       break;
4360     }
4361     case FOURCC_sidx:
4362     {
4363       GstBuffer *sidx = NULL;
4364       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4365       if (ret != GST_FLOW_OK)
4366         goto beach;
4367       qtdemux->offset += length;
4368       gst_buffer_map (sidx, &map, GST_MAP_READ);
4369       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4370       gst_buffer_unmap (sidx, &map);
4371       gst_buffer_unref (sidx);
4372       break;
4373     }
4374     default:
4375     {
4376       GstBuffer *unknown = NULL;
4377
4378       GST_LOG_OBJECT (qtdemux,
4379           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4380           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4381           cur_offset);
4382       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4383       if (ret != GST_FLOW_OK)
4384         goto beach;
4385       gst_buffer_map (unknown, &map, GST_MAP_READ);
4386       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4387       gst_buffer_unmap (unknown, &map);
4388       gst_buffer_unref (unknown);
4389       qtdemux->offset += length;
4390       break;
4391     }
4392   }
4393
4394 beach:
4395   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4396     /* digested all data, show what we have */
4397     qtdemux_prepare_streams (qtdemux);
4398     ret = qtdemux_expose_streams (qtdemux);
4399
4400     qtdemux->state = QTDEMUX_STATE_MOVIE;
4401     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4402         qtdemux->state);
4403     return ret;
4404   }
4405   return ret;
4406 }
4407
4408 /* Seeks to the previous keyframe of the indexed stream and
4409  * aligns other streams with respect to the keyframe timestamp
4410  * of indexed stream. Only called in case of Reverse Playback
4411  */
4412 static GstFlowReturn
4413 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4414 {
4415   guint8 n = 0;
4416   guint32 seg_idx = 0, k_index = 0;
4417   guint32 ref_seg_idx, ref_k_index;
4418   GstClockTime k_pos = 0, last_stop = 0;
4419   QtDemuxSegment *seg = NULL;
4420   QtDemuxStream *ref_str = NULL;
4421   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4422   guint64 target_ts;
4423
4424   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4425    * and finally align all the other streams on that timestamp with their
4426    * respective keyframes */
4427   for (n = 0; n < qtdemux->n_streams; n++) {
4428     QtDemuxStream *str = qtdemux->streams[n];
4429
4430     /* No candidate yet, take the first stream */
4431     if (!ref_str) {
4432       ref_str = str;
4433       continue;
4434     }
4435
4436     /* So that stream has a segment, we prefer video streams */
4437     if (str->subtype == FOURCC_vide) {
4438       ref_str = str;
4439       break;
4440     }
4441   }
4442
4443   if (G_UNLIKELY (!ref_str)) {
4444     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4445     goto eos;
4446   }
4447
4448   if (G_UNLIKELY (!ref_str->from_sample)) {
4449     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4450     goto eos;
4451   }
4452
4453   /* So that stream has been playing from from_sample to to_sample. We will
4454    * get the timestamp of the previous sample and search for a keyframe before
4455    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4456   if (ref_str->subtype == FOURCC_vide) {
4457     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4458         ref_str->from_sample - 1, FALSE);
4459   } else {
4460     if (ref_str->from_sample >= 10)
4461       k_index = ref_str->from_sample - 10;
4462     else
4463       k_index = 0;
4464   }
4465
4466   target_ts =
4467       ref_str->samples[k_index].timestamp +
4468       ref_str->samples[k_index].pts_offset;
4469
4470   /* get current segment for that stream */
4471   seg = &ref_str->segments[ref_str->segment_index];
4472   /* Use segment start in original timescale for comparisons */
4473   seg_media_start_mov = seg->trak_media_start;
4474
4475   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4476       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4477       k_index, target_ts, seg_media_start_mov,
4478       GST_TIME_ARGS (seg->media_start));
4479
4480   /* Crawl back through segments to find the one containing this I frame */
4481   while (target_ts < seg_media_start_mov) {
4482     GST_DEBUG_OBJECT (qtdemux,
4483         "keyframe position (sample %u) is out of segment %u " " target %"
4484         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4485         ref_str->segment_index, target_ts, seg_media_start_mov);
4486
4487     if (G_UNLIKELY (!ref_str->segment_index)) {
4488       /* Reached first segment, let's consider it's EOS */
4489       goto eos;
4490     }
4491     ref_str->segment_index--;
4492     seg = &ref_str->segments[ref_str->segment_index];
4493     /* Use segment start in original timescale for comparisons */
4494     seg_media_start_mov = seg->trak_media_start;
4495   }
4496   /* Calculate time position of the keyframe and where we should stop */
4497   k_pos =
4498       QTSTREAMTIME_TO_GSTTIME (ref_str,
4499       target_ts - seg->trak_media_start) + seg->time;
4500   last_stop =
4501       QTSTREAMTIME_TO_GSTTIME (ref_str,
4502       ref_str->samples[ref_str->from_sample].timestamp -
4503       seg->trak_media_start) + seg->time;
4504
4505   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4506       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4507       k_index, GST_TIME_ARGS (k_pos));
4508
4509   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4510   qtdemux->segment.position = last_stop;
4511   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4512       GST_TIME_ARGS (last_stop));
4513
4514   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4515     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4516     goto eos;
4517   }
4518
4519   ref_seg_idx = ref_str->segment_index;
4520   ref_k_index = k_index;
4521
4522   /* Align them all on this */
4523   for (n = 0; n < qtdemux->n_streams; n++) {
4524     guint32 index = 0;
4525     GstClockTime seg_time = 0;
4526     QtDemuxStream *str = qtdemux->streams[n];
4527
4528     /* aligning reference stream again might lead to backing up to yet another
4529      * keyframe (due to timestamp rounding issues),
4530      * potentially putting more load on downstream; so let's try to avoid */
4531     if (str == ref_str) {
4532       seg_idx = ref_seg_idx;
4533       seg = &str->segments[seg_idx];
4534       k_index = ref_k_index;
4535       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4536           "sample at index %d", n, ref_str->segment_index, k_index);
4537     } else {
4538       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4539       GST_DEBUG_OBJECT (qtdemux,
4540           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4541           seg_idx, GST_TIME_ARGS (k_pos));
4542
4543       /* get segment and time in the segment */
4544       seg = &str->segments[seg_idx];
4545       seg_time = k_pos - seg->time;
4546
4547       /* get the media time in the segment.
4548        * No adjustment for empty "filler" segments */
4549       if (seg->media_start != GST_CLOCK_TIME_NONE)
4550         seg_time += seg->media_start;
4551
4552       /* get the index of the sample with media time */
4553       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4554       GST_DEBUG_OBJECT (qtdemux,
4555           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4556           GST_TIME_ARGS (seg_time), index);
4557
4558       /* find previous keyframe */
4559       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4560     }
4561
4562     /* Remember until where we want to go */
4563     str->to_sample = str->from_sample - 1;
4564     /* Define our time position */
4565     target_ts =
4566         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4567     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4568     if (seg->media_start != GST_CLOCK_TIME_NONE)
4569       str->time_position -= seg->media_start;
4570
4571     /* Now seek back in time */
4572     gst_qtdemux_move_stream (qtdemux, str, k_index);
4573     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4574         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4575         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4576   }
4577
4578   return GST_FLOW_OK;
4579
4580 eos:
4581   return GST_FLOW_EOS;
4582 }
4583
4584 /*
4585  * Gets the current qt segment start, stop and position for the
4586  * given time offset. This is used in update_segment()
4587  */
4588 static void
4589 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4590     QtDemuxStream * stream, GstClockTime offset,
4591     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4592 {
4593   GstClockTime seg_time;
4594   GstClockTime start, stop, time;
4595   QtDemuxSegment *segment;
4596
4597   segment = &stream->segments[stream->segment_index];
4598
4599   /* get time in this segment */
4600   seg_time = (offset - segment->time) * segment->rate;
4601
4602   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4603       GST_TIME_ARGS (seg_time));
4604
4605   if (G_UNLIKELY (seg_time > segment->duration)) {
4606     GST_LOG_OBJECT (stream->pad,
4607         "seg_time > segment->duration %" GST_TIME_FORMAT,
4608         GST_TIME_ARGS (segment->duration));
4609     seg_time = segment->duration;
4610   }
4611
4612   /* qtdemux->segment.stop is in outside-time-realm, whereas
4613    * segment->media_stop is in track-time-realm.
4614    *
4615    * In order to compare the two, we need to bring segment.stop
4616    * into the track-time-realm
4617    *
4618    * FIXME - does this comment still hold? Don't see any conversion here */
4619
4620   stop = qtdemux->segment.stop;
4621   if (stop == GST_CLOCK_TIME_NONE)
4622     stop = qtdemux->segment.duration;
4623   if (stop == GST_CLOCK_TIME_NONE)
4624     stop = segment->media_stop;
4625   else
4626     stop =
4627         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4628
4629   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4630     start = segment->time + seg_time;
4631     time = offset;
4632     stop = start - seg_time + segment->duration;
4633   } else if (qtdemux->segment.rate >= 0) {
4634     start = MIN (segment->media_start + seg_time, stop);
4635     time = offset;
4636   } else {
4637     if (segment->media_start >= qtdemux->segment.start) {
4638       time = segment->time;
4639     } else {
4640       time = segment->time + (qtdemux->segment.start - segment->media_start);
4641     }
4642
4643     start = MAX (segment->media_start, qtdemux->segment.start);
4644     stop = MIN (segment->media_start + seg_time, stop);
4645   }
4646
4647   *_start = start;
4648   *_stop = stop;
4649   *_time = time;
4650 }
4651
4652 /*
4653  * Updates the qt segment used for the stream and pushes a new segment event
4654  * downstream on this stream's pad.
4655  */
4656 static gboolean
4657 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4658     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4659     GstClockTime * _stop)
4660 {
4661   QtDemuxSegment *segment;
4662   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4663   gdouble rate;
4664   GstEvent *event;
4665
4666   /* update the current segment */
4667   stream->segment_index = seg_idx;
4668
4669   /* get the segment */
4670   segment = &stream->segments[seg_idx];
4671
4672   if (G_UNLIKELY (offset < segment->time)) {
4673     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4674         GST_TIME_ARGS (segment->time));
4675     return FALSE;
4676   }
4677
4678   /* segment lies beyond total indicated duration */
4679   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4680           segment->time > qtdemux->segment.duration)) {
4681     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4682         " < segment->time %" GST_TIME_FORMAT,
4683         GST_TIME_ARGS (qtdemux->segment.duration),
4684         GST_TIME_ARGS (segment->time));
4685     return FALSE;
4686   }
4687
4688   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4689       &start, &stop, &time);
4690
4691   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4692       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4693       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4694
4695   /* combine global rate with that of the segment */
4696   rate = segment->rate * qtdemux->segment.rate;
4697
4698   /* Copy flags from main segment */
4699   stream->segment.flags = qtdemux->segment.flags;
4700
4701   /* update the segment values used for clipping */
4702   stream->segment.offset = qtdemux->segment.offset;
4703   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4704   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4705   stream->segment.rate = rate;
4706   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4707       stream->cslg_shift);
4708   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4709       stream->cslg_shift);
4710   stream->segment.time = time;
4711   stream->segment.position = stream->segment.start;
4712
4713   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4714       &stream->segment);
4715
4716   /* now prepare and send the segment */
4717   if (stream->pad) {
4718     event = gst_event_new_segment (&stream->segment);
4719     if (qtdemux->segment_seqnum) {
4720       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4721     }
4722     gst_pad_push_event (stream->pad, event);
4723     /* assume we can send more data now */
4724     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4725     /* clear to send tags on this pad now */
4726     gst_qtdemux_push_tags (qtdemux, stream);
4727   }
4728
4729   if (_start)
4730     *_start = start;
4731   if (_stop)
4732     *_stop = stop;
4733
4734   return TRUE;
4735 }
4736
4737 /* activate the given segment number @seg_idx of @stream at time @offset.
4738  * @offset is an absolute global position over all the segments.
4739  *
4740  * This will push out a NEWSEGMENT event with the right values and
4741  * position the stream index to the first decodable sample before
4742  * @offset.
4743  */
4744 static gboolean
4745 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4746     guint32 seg_idx, GstClockTime offset)
4747 {
4748   QtDemuxSegment *segment;
4749   guint32 index, kf_index;
4750   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4751
4752   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4753       seg_idx, GST_TIME_ARGS (offset));
4754
4755   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4756           &start, &stop))
4757     return FALSE;
4758
4759   segment = &stream->segments[stream->segment_index];
4760
4761   /* in the fragmented case, we pick a fragment that starts before our
4762    * desired position and rely on downstream to wait for a keyframe
4763    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4764    * tfra entries tells us which trun/sample the key unit is in, but we don't
4765    * make use of this additional information at the moment) */
4766   if (qtdemux->fragmented) {
4767     stream->to_sample = G_MAXUINT32;
4768     return TRUE;
4769   }
4770
4771   /* We don't need to look for a sample in push-based */
4772   if (!qtdemux->pullbased)
4773     return TRUE;
4774
4775   /* and move to the keyframe before the indicated media time of the
4776    * segment */
4777   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4778     if (qtdemux->segment.rate >= 0) {
4779       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4780       stream->to_sample = G_MAXUINT32;
4781       GST_DEBUG_OBJECT (stream->pad,
4782           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4783           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4784           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4785     } else {
4786       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4787       stream->to_sample = index;
4788       GST_DEBUG_OBJECT (stream->pad,
4789           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4790           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4791           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4792     }
4793   } else {
4794     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4795         "this is an empty segment");
4796     return TRUE;
4797   }
4798
4799   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4800    * encountered an error and printed a message so we return appropriately */
4801   if (index == -1)
4802     return FALSE;
4803
4804   /* we're at the right spot */
4805   if (index == stream->sample_index) {
4806     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4807     return TRUE;
4808   }
4809
4810   /* find keyframe of the target index */
4811   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4812
4813 /* *INDENT-OFF* */
4814 /* indent does stupid stuff with stream->samples[].timestamp */
4815
4816   /* if we move forwards, we don't have to go back to the previous
4817    * keyframe since we already sent that. We can also just jump to
4818    * the keyframe right before the target index if there is one. */
4819   if (index > stream->sample_index) {
4820     /* moving forwards check if we move past a keyframe */
4821     if (kf_index > stream->sample_index) {
4822       GST_DEBUG_OBJECT (stream->pad,
4823            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4824            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4825            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4826       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4827     } else {
4828       GST_DEBUG_OBJECT (stream->pad,
4829           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4830           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4831           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4832     }
4833   } else {
4834     GST_DEBUG_OBJECT (stream->pad,
4835         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4836         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4837         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4838     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4839   }
4840
4841 /* *INDENT-ON* */
4842
4843   return TRUE;
4844 }
4845
4846 /* prepare to get the current sample of @stream, getting essential values.
4847  *
4848  * This function will also prepare and send the segment when needed.
4849  *
4850  * Return FALSE if the stream is EOS.
4851  *
4852  * PULL-BASED
4853  */
4854 static gboolean
4855 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4856     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4857     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4858     gboolean * keyframe)
4859 {
4860   QtDemuxSample *sample;
4861   GstClockTime time_position;
4862   guint32 seg_idx;
4863
4864   g_return_val_if_fail (stream != NULL, FALSE);
4865
4866   time_position = stream->time_position;
4867   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4868     goto eos;
4869
4870   seg_idx = stream->segment_index;
4871   if (G_UNLIKELY (seg_idx == -1)) {
4872     /* find segment corresponding to time_position if we are looking
4873      * for a segment. */
4874     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4875   }
4876
4877   /* different segment, activate it, sample_index will be set. */
4878   if (G_UNLIKELY (stream->segment_index != seg_idx))
4879     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4880
4881   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4882                   segment_index]))) {
4883     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4884
4885     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4886         " prepare empty sample");
4887
4888     *empty = TRUE;
4889     *pts = *dts = time_position;
4890     *duration = seg->duration - (time_position - seg->time);
4891
4892     return TRUE;
4893   }
4894
4895   *empty = FALSE;
4896
4897   if (stream->sample_index == -1)
4898     stream->sample_index = 0;
4899
4900   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4901       stream->sample_index, stream->n_samples);
4902
4903   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4904     if (!qtdemux->fragmented)
4905       goto eos;
4906
4907     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4908     do {
4909       GstFlowReturn flow;
4910
4911       GST_OBJECT_LOCK (qtdemux);
4912       flow = qtdemux_add_fragmented_samples (qtdemux);
4913       GST_OBJECT_UNLOCK (qtdemux);
4914
4915       if (flow != GST_FLOW_OK)
4916         goto eos;
4917     }
4918     while (stream->sample_index >= stream->n_samples);
4919   }
4920
4921   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4922     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4923         stream->sample_index);
4924     return FALSE;
4925   }
4926
4927   /* now get the info for the sample we're at */
4928   sample = &stream->samples[stream->sample_index];
4929
4930   *dts = QTSAMPLE_DTS (stream, sample);
4931   *pts = QTSAMPLE_PTS (stream, sample);
4932   *offset = sample->offset;
4933   *size = sample->size;
4934   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4935   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4936
4937   return TRUE;
4938
4939   /* special cases */
4940 eos:
4941   {
4942     stream->time_position = GST_CLOCK_TIME_NONE;
4943     return FALSE;
4944   }
4945 }
4946
4947 /* move to the next sample in @stream.
4948  *
4949  * Moves to the next segment when needed.
4950  */
4951 static void
4952 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4953 {
4954   QtDemuxSample *sample;
4955   QtDemuxSegment *segment;
4956
4957   /* get current segment */
4958   segment = &stream->segments[stream->segment_index];
4959
4960   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4961     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4962     goto next_segment;
4963   }
4964
4965   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4966     /* Mark the stream as EOS */
4967     GST_DEBUG_OBJECT (qtdemux,
4968         "reached max allowed sample %u, mark EOS", stream->to_sample);
4969     stream->time_position = GST_CLOCK_TIME_NONE;
4970     return;
4971   }
4972
4973   /* move to next sample */
4974   stream->sample_index++;
4975   stream->offset_in_sample = 0;
4976
4977   /* reached the last sample, we need the next segment */
4978   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4979     goto next_segment;
4980
4981   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4982     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4983         stream->sample_index);
4984     return;
4985   }
4986
4987   /* get next sample */
4988   sample = &stream->samples[stream->sample_index];
4989
4990   /* see if we are past the segment */
4991   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4992     goto next_segment;
4993
4994   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4995     /* inside the segment, update time_position, looks very familiar to
4996      * GStreamer segments, doesn't it? */
4997     stream->time_position =
4998         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4999   } else {
5000     /* not yet in segment, time does not yet increment. This means
5001      * that we are still prerolling keyframes to the decoder so it can
5002      * decode the first sample of the segment. */
5003     stream->time_position = segment->time;
5004   }
5005   return;
5006
5007   /* move to the next segment */
5008 next_segment:
5009   {
5010     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5011
5012     if (stream->segment_index == stream->n_segments - 1) {
5013       /* are we at the end of the last segment, we're EOS */
5014       stream->time_position = GST_CLOCK_TIME_NONE;
5015     } else {
5016       /* else we're only at the end of the current segment */
5017       stream->time_position = segment->stop_time;
5018     }
5019     /* make sure we select a new segment */
5020
5021     /* accumulate previous segments */
5022     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5023       stream->accumulated_base +=
5024           (stream->segment.stop -
5025           stream->segment.start) / ABS (stream->segment.rate);
5026
5027     stream->segment_index = -1;
5028   }
5029 }
5030
5031 static void
5032 gst_qtdemux_sync_streams (GstQTDemux * demux)
5033 {
5034   gint i;
5035
5036   if (demux->n_streams <= 1)
5037     return;
5038
5039   for (i = 0; i < demux->n_streams; i++) {
5040     QtDemuxStream *stream;
5041     GstClockTime end_time;
5042
5043     stream = demux->streams[i];
5044
5045     if (!stream->pad)
5046       continue;
5047
5048     /* TODO advance time on subtitle streams here, if any some day */
5049
5050     /* some clips/trailers may have unbalanced streams at the end,
5051      * so send EOS on shorter stream to prevent stalling others */
5052
5053     /* do not mess with EOS if SEGMENT seeking */
5054     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5055       continue;
5056
5057     if (demux->pullbased) {
5058       /* loop mode is sample time based */
5059       if (!STREAM_IS_EOS (stream))
5060         continue;
5061     } else {
5062       /* push mode is byte position based */
5063       if (stream->n_samples &&
5064           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5065         continue;
5066     }
5067
5068     if (stream->sent_eos)
5069       continue;
5070
5071     /* only act if some gap */
5072     end_time = stream->segments[stream->n_segments - 1].stop_time;
5073     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5074         ", stream end: %" GST_TIME_FORMAT,
5075         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5076     if (GST_CLOCK_TIME_IS_VALID (end_time)
5077         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5078       GstEvent *event;
5079
5080       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5081           GST_PAD_NAME (stream->pad));
5082       stream->sent_eos = TRUE;
5083       event = gst_event_new_eos ();
5084       if (demux->segment_seqnum)
5085         gst_event_set_seqnum (event, demux->segment_seqnum);
5086       gst_pad_push_event (stream->pad, event);
5087     }
5088   }
5089 }
5090
5091 /* EOS and NOT_LINKED need to be combined. This means that we return:
5092  *
5093  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5094  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5095  */
5096 static GstFlowReturn
5097 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5098     GstFlowReturn ret)
5099 {
5100   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5101
5102   if (stream->pad)
5103     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5104         ret);
5105   else
5106     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5107
5108   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5109   return ret;
5110 }
5111
5112 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5113  * completely clipped
5114  *
5115  * Should be used only with raw buffers */
5116 static GstBuffer *
5117 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5118     GstBuffer * buf)
5119 {
5120   guint64 start, stop, cstart, cstop, diff;
5121   GstClockTime pts, duration;
5122   gsize size, osize;
5123   gint num_rate, denom_rate;
5124   gint frame_size;
5125   gboolean clip_data;
5126   guint offset;
5127
5128   osize = size = gst_buffer_get_size (buf);
5129   offset = 0;
5130
5131   /* depending on the type, setup the clip parameters */
5132   if (stream->subtype == FOURCC_soun) {
5133     frame_size = stream->bytes_per_frame;
5134     num_rate = GST_SECOND;
5135     denom_rate = (gint) stream->rate;
5136     clip_data = TRUE;
5137   } else if (stream->subtype == FOURCC_vide) {
5138     frame_size = size;
5139     num_rate = stream->fps_n;
5140     denom_rate = stream->fps_d;
5141     clip_data = FALSE;
5142   } else
5143     goto wrong_type;
5144
5145   if (frame_size <= 0)
5146     goto bad_frame_size;
5147
5148   /* we can only clip if we have a valid pts */
5149   pts = GST_BUFFER_PTS (buf);
5150   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5151     goto no_pts;
5152
5153   duration = GST_BUFFER_DURATION (buf);
5154
5155   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5156     duration =
5157         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5158   }
5159
5160   start = pts;
5161   stop = start + duration;
5162
5163   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5164               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5165     goto clipped;
5166
5167   /* see if some clipping happened */
5168   diff = cstart - start;
5169   if (diff > 0) {
5170     pts += diff;
5171     duration -= diff;
5172
5173     if (clip_data) {
5174       /* bring clipped time to samples and to bytes */
5175       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5176       diff *= frame_size;
5177
5178       GST_DEBUG_OBJECT (qtdemux,
5179           "clipping start to %" GST_TIME_FORMAT " %"
5180           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5181
5182       offset = diff;
5183       size -= diff;
5184     }
5185   }
5186   diff = stop - cstop;
5187   if (diff > 0) {
5188     duration -= diff;
5189
5190     if (clip_data) {
5191       /* bring clipped time to samples and then to bytes */
5192       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5193       diff *= frame_size;
5194       GST_DEBUG_OBJECT (qtdemux,
5195           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5196           " bytes", GST_TIME_ARGS (cstop), diff);
5197       size -= diff;
5198     }
5199   }
5200
5201   if (offset != 0 || size != osize)
5202     gst_buffer_resize (buf, offset, size);
5203
5204   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5205   GST_BUFFER_PTS (buf) = pts;
5206   GST_BUFFER_DURATION (buf) = duration;
5207
5208   return buf;
5209
5210   /* dropped buffer */
5211 wrong_type:
5212   {
5213     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5214     return buf;
5215   }
5216 bad_frame_size:
5217   {
5218     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5219     return buf;
5220   }
5221 no_pts:
5222   {
5223     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5224     return buf;
5225   }
5226 clipped:
5227   {
5228     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5229     gst_buffer_unref (buf);
5230     return NULL;
5231   }
5232 }
5233
5234 static GstBuffer *
5235 gst_qtdemux_align_buffer (GstQTDemux * demux,
5236     GstBuffer * buffer, gsize alignment)
5237 {
5238   GstMapInfo map;
5239
5240   gst_buffer_map (buffer, &map, GST_MAP_READ);
5241
5242   if (map.size < sizeof (guintptr)) {
5243     gst_buffer_unmap (buffer, &map);
5244     return buffer;
5245   }
5246
5247   if (((guintptr) map.data) & (alignment - 1)) {
5248     GstBuffer *new_buffer;
5249     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5250
5251     new_buffer = gst_buffer_new_allocate (NULL,
5252         gst_buffer_get_size (buffer), &params);
5253
5254     /* Copy data "by hand", so ensure alignment is kept: */
5255     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5256
5257     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5258     GST_DEBUG_OBJECT (demux,
5259         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5260         alignment);
5261
5262     gst_buffer_unmap (buffer, &map);
5263     gst_buffer_unref (buffer);
5264
5265     return new_buffer;
5266   }
5267
5268   gst_buffer_unmap (buffer, &map);
5269   return buffer;
5270 }
5271
5272 /* the input buffer metadata must be writable,
5273  * but time/duration etc not yet set and need not be preserved */
5274 static GstBuffer *
5275 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5276     GstBuffer * buf)
5277 {
5278   GstMapInfo map;
5279   guint nsize = 0;
5280   gchar *str;
5281
5282   /* not many cases for now */
5283   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5284     /* send a one time dvd clut event */
5285     if (stream->pending_event && stream->pad)
5286       gst_pad_push_event (stream->pad, stream->pending_event);
5287     stream->pending_event = NULL;
5288   }
5289
5290   if (G_UNLIKELY (stream->subtype != FOURCC_text
5291           && stream->subtype != FOURCC_sbtl &&
5292           stream->subtype != FOURCC_subp)) {
5293     return buf;
5294   }
5295
5296   gst_buffer_map (buf, &map, GST_MAP_READ);
5297
5298   /* empty buffer is sent to terminate previous subtitle */
5299   if (map.size <= 2) {
5300     gst_buffer_unmap (buf, &map);
5301     gst_buffer_unref (buf);
5302     return NULL;
5303   }
5304   if (stream->subtype == FOURCC_subp) {
5305     /* That's all the processing needed for subpictures */
5306     gst_buffer_unmap (buf, &map);
5307     return buf;
5308   }
5309
5310   nsize = GST_READ_UINT16_BE (map.data);
5311   nsize = MIN (nsize, map.size - 2);
5312
5313   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5314       nsize, map.size);
5315
5316   /* takes care of UTF-8 validation or UTF-16 recognition,
5317    * no other encoding expected */
5318   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5319   gst_buffer_unmap (buf, &map);
5320   if (str) {
5321     gst_buffer_unref (buf);
5322     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5323   } else {
5324     /* this should not really happen unless the subtitle is corrupted */
5325     gst_buffer_unref (buf);
5326     buf = NULL;
5327   }
5328
5329   /* FIXME ? convert optional subsequent style info to markup */
5330
5331   return buf;
5332 }
5333
5334 /* Sets a buffer's attributes properly and pushes it downstream.
5335  * Also checks for additional actions and custom processing that may
5336  * need to be done first.
5337  */
5338 static GstFlowReturn
5339 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5340     QtDemuxStream * stream, GstBuffer * buf,
5341     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5342     gboolean keyframe, GstClockTime position, guint64 byte_position)
5343 {
5344   GstFlowReturn ret = GST_FLOW_OK;
5345
5346   /* offset the timestamps according to the edit list */
5347
5348   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5349     gchar *url;
5350     GstMapInfo map;
5351
5352     gst_buffer_map (buf, &map, GST_MAP_READ);
5353     url = g_strndup ((gchar *) map.data, map.size);
5354     gst_buffer_unmap (buf, &map);
5355     if (url != NULL && strlen (url) != 0) {
5356       /* we have RTSP redirect now */
5357       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5358           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5359               gst_structure_new ("redirect",
5360                   "new-location", G_TYPE_STRING, url, NULL)));
5361       qtdemux->posted_redirect = TRUE;
5362     } else {
5363       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5364           "posting");
5365     }
5366     g_free (url);
5367   }
5368
5369   /* position reporting */
5370   if (qtdemux->segment.rate >= 0) {
5371     qtdemux->segment.position = position;
5372     gst_qtdemux_sync_streams (qtdemux);
5373   }
5374
5375   if (G_UNLIKELY (!stream->pad)) {
5376     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5377     gst_buffer_unref (buf);
5378     goto exit;
5379   }
5380
5381   /* send out pending buffers */
5382   while (stream->buffers) {
5383     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5384
5385     if (G_UNLIKELY (stream->discont)) {
5386       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5387       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5388       stream->discont = FALSE;
5389     } else {
5390       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5391     }
5392
5393     if (stream->alignment > 1)
5394       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5395     gst_pad_push (stream->pad, buffer);
5396
5397     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5398   }
5399
5400   /* we're going to modify the metadata */
5401   buf = gst_buffer_make_writable (buf);
5402
5403   if (G_UNLIKELY (stream->need_process))
5404     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5405
5406   if (!buf) {
5407     goto exit;
5408   }
5409
5410   GST_BUFFER_DTS (buf) = dts;
5411   GST_BUFFER_PTS (buf) = pts;
5412   GST_BUFFER_DURATION (buf) = duration;
5413   GST_BUFFER_OFFSET (buf) = -1;
5414   GST_BUFFER_OFFSET_END (buf) = -1;
5415
5416   if (G_UNLIKELY (stream->rgb8_palette))
5417     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5418
5419   if (G_UNLIKELY (stream->padding)) {
5420     gst_buffer_resize (buf, stream->padding, -1);
5421   }
5422 #if 0
5423   if (G_UNLIKELY (qtdemux->element_index)) {
5424     GstClockTime stream_time;
5425
5426     stream_time =
5427         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5428         timestamp);
5429     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5430       GST_LOG_OBJECT (qtdemux,
5431           "adding association %" GST_TIME_FORMAT "-> %"
5432           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5433       gst_index_add_association (qtdemux->element_index,
5434           qtdemux->index_id,
5435           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5436           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5437           GST_FORMAT_BYTES, byte_position, NULL);
5438     }
5439   }
5440 #endif
5441
5442   if (stream->need_clip)
5443     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5444
5445   if (G_UNLIKELY (buf == NULL))
5446     goto exit;
5447
5448   if (G_UNLIKELY (stream->discont)) {
5449     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5450     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5451     stream->discont = FALSE;
5452   } else {
5453     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5454   }
5455
5456   if (!keyframe) {
5457     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5458     stream->on_keyframe = FALSE;
5459   } else {
5460     stream->on_keyframe = TRUE;
5461   }
5462
5463
5464   GST_LOG_OBJECT (qtdemux,
5465       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5466       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5467       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5468       GST_PAD_NAME (stream->pad));
5469
5470   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5471     GstStructure *crypto_info;
5472     QtDemuxCencSampleSetInfo *info =
5473         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5474     gint index;
5475     GstEvent *event;
5476
5477     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5478       gst_pad_push_event (stream->pad, event);
5479     }
5480
5481     if (info->crypto_info == NULL) {
5482       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5483       gst_buffer_unref (buf);
5484       goto exit;
5485     }
5486
5487     /* The end of the crypto_info array matches our n_samples position,
5488      * so count backward from there */
5489     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5490     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5491       /* steal structure from array */
5492       crypto_info = g_ptr_array_index (info->crypto_info, index);
5493       g_ptr_array_index (info->crypto_info, index) = NULL;
5494       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5495           info->crypto_info->len);
5496       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5497         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5498     } else {
5499       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5500           index, stream->sample_index);
5501     }
5502   }
5503
5504   if (stream->alignment > 1)
5505     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5506
5507   ret = gst_pad_push (stream->pad, buf);
5508
5509   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5510     /* mark position in stream, we'll need this to know when to send GAP event */
5511     stream->segment.position = pts + duration;
5512   }
5513
5514 exit:
5515   return ret;
5516 }
5517
5518 static const QtDemuxRandomAccessEntry *
5519 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5520     GstClockTime pos, gboolean after)
5521 {
5522   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5523   guint n_entries = stream->n_ra_entries;
5524   guint i;
5525
5526   /* we assume the table is sorted */
5527   for (i = 0; i < n_entries; ++i) {
5528     if (entries[i].ts > pos)
5529       break;
5530   }
5531
5532   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5533    * probably okay to assume that the index lists the very first fragment */
5534   if (i == 0)
5535     return &entries[0];
5536
5537   if (after)
5538     return &entries[i];
5539   else
5540     return &entries[i - 1];
5541 }
5542
5543 static gboolean
5544 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5545 {
5546   const QtDemuxRandomAccessEntry *best_entry = NULL;
5547   guint i;
5548
5549   GST_OBJECT_LOCK (qtdemux);
5550
5551   g_assert (qtdemux->n_streams > 0);
5552
5553   for (i = 0; i < qtdemux->n_streams; i++) {
5554     const QtDemuxRandomAccessEntry *entry;
5555     QtDemuxStream *stream;
5556     gboolean is_audio_or_video;
5557
5558     stream = qtdemux->streams[i];
5559
5560     g_free (stream->samples);
5561     stream->samples = NULL;
5562     stream->n_samples = 0;
5563     stream->stbl_index = -1;    /* no samples have yet been parsed */
5564     stream->sample_index = -1;
5565
5566     if (stream->protection_scheme_info) {
5567       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5568       if (stream->protection_scheme_type == FOURCC_cenc) {
5569         QtDemuxCencSampleSetInfo *info =
5570             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5571         if (info->crypto_info) {
5572           g_ptr_array_free (info->crypto_info, TRUE);
5573           info->crypto_info = NULL;
5574         }
5575       }
5576     }
5577
5578     if (stream->ra_entries == NULL)
5579       continue;
5580
5581     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5582       is_audio_or_video = TRUE;
5583     else
5584       is_audio_or_video = FALSE;
5585
5586     entry =
5587         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5588         stream->time_position, !is_audio_or_video);
5589
5590     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5591         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5592
5593     stream->pending_seek = entry;
5594
5595     /* decide position to jump to just based on audio/video tracks, not subs */
5596     if (!is_audio_or_video)
5597       continue;
5598
5599     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5600       best_entry = entry;
5601   }
5602
5603   if (best_entry == NULL) {
5604     GST_OBJECT_UNLOCK (qtdemux);
5605     return FALSE;
5606   }
5607
5608   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5609       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5610       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5611       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5612
5613   qtdemux->moof_offset = best_entry->moof_offset;
5614
5615   qtdemux_add_fragmented_samples (qtdemux);
5616
5617   GST_OBJECT_UNLOCK (qtdemux);
5618   return TRUE;
5619 }
5620
5621 static GstFlowReturn
5622 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5623 {
5624   GstFlowReturn ret = GST_FLOW_OK;
5625   GstBuffer *buf = NULL;
5626   QtDemuxStream *stream;
5627   GstClockTime min_time;
5628   guint64 offset = 0;
5629   GstClockTime dts = GST_CLOCK_TIME_NONE;
5630   GstClockTime pts = GST_CLOCK_TIME_NONE;
5631   GstClockTime duration = 0;
5632   gboolean keyframe = FALSE;
5633   guint sample_size = 0;
5634   gboolean empty = 0;
5635   guint size;
5636   gint index;
5637   gint i;
5638
5639   gst_qtdemux_push_pending_newsegment (qtdemux);
5640
5641   if (qtdemux->fragmented_seek_pending) {
5642     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5643     gst_qtdemux_do_fragmented_seek (qtdemux);
5644     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5645     qtdemux->fragmented_seek_pending = FALSE;
5646   }
5647
5648   /* Figure out the next stream sample to output, min_time is expressed in
5649    * global time and runs over the edit list segments. */
5650   min_time = G_MAXUINT64;
5651   index = -1;
5652   for (i = 0; i < qtdemux->n_streams; i++) {
5653     GstClockTime position;
5654
5655     stream = qtdemux->streams[i];
5656     position = stream->time_position;
5657
5658     /* position of -1 is EOS */
5659     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5660       min_time = position;
5661       index = i;
5662     }
5663   }
5664   /* all are EOS */
5665   if (G_UNLIKELY (index == -1)) {
5666     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5667     goto eos;
5668   }
5669
5670   /* check for segment end */
5671   if (G_UNLIKELY (qtdemux->segment.stop != -1
5672           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5673               || (qtdemux->segment.rate < 0
5674                   && qtdemux->segment.start > min_time))
5675           && qtdemux->streams[index]->on_keyframe)) {
5676     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5677     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5678     goto eos_stream;
5679   }
5680
5681   /* gap events for subtitle streams */
5682   for (i = 0; i < qtdemux->n_streams; i++) {
5683     stream = qtdemux->streams[i];
5684     if (stream->pad && (stream->subtype == FOURCC_subp
5685             || stream->subtype == FOURCC_text
5686             || stream->subtype == FOURCC_sbtl)) {
5687       /* send one second gap events until the stream catches up */
5688       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5689       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5690           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5691           stream->segment.position + GST_SECOND < min_time) {
5692         GstEvent *gap =
5693             gst_event_new_gap (stream->segment.position, GST_SECOND);
5694         gst_pad_push_event (stream->pad, gap);
5695         stream->segment.position += GST_SECOND;
5696       }
5697     }
5698   }
5699
5700   stream = qtdemux->streams[index];
5701   if (stream->new_caps) {
5702     gst_qtdemux_configure_stream (qtdemux, stream);
5703     qtdemux_do_allocation (qtdemux, stream);
5704   }
5705
5706   /* fetch info for the current sample of this stream */
5707   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5708               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5709     goto eos_stream;
5710
5711   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5712   if (G_UNLIKELY (qtdemux->
5713           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5714     if (stream->subtype == FOURCC_vide && !keyframe) {
5715       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5716       goto next;
5717     }
5718   }
5719
5720   GST_DEBUG_OBJECT (qtdemux,
5721       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5722       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5723       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5724       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5725
5726   if (G_UNLIKELY (empty)) {
5727     /* empty segment, push a gap and move to the next one */
5728     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5729     stream->segment.position = pts + duration;
5730     goto next;
5731   }
5732
5733   /* hmm, empty sample, skip and move to next sample */
5734   if (G_UNLIKELY (sample_size <= 0))
5735     goto next;
5736
5737   /* last pushed sample was out of boundary, goto next sample */
5738   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5739     goto next;
5740
5741   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5742     size = sample_size;
5743   } else {
5744     GST_DEBUG_OBJECT (qtdemux,
5745         "size %d larger than stream max_buffer_size %d, trimming",
5746         sample_size, stream->max_buffer_size);
5747     size =
5748         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5749   }
5750
5751   if (qtdemux->cenc_aux_info_offset > 0) {
5752     GstMapInfo map;
5753     GstByteReader br;
5754     GstBuffer *aux_info = NULL;
5755
5756     /* pull the data stored before the sample */
5757     ret =
5758         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5759         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5760     if (G_UNLIKELY (ret != GST_FLOW_OK))
5761       goto beach;
5762     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5763     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5764     gst_byte_reader_init (&br, map.data + 8, map.size);
5765     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5766             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5767       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5768       gst_buffer_unmap (aux_info, &map);
5769       gst_buffer_unref (aux_info);
5770       ret = GST_FLOW_ERROR;
5771       goto beach;
5772     }
5773     gst_buffer_unmap (aux_info, &map);
5774     gst_buffer_unref (aux_info);
5775   }
5776
5777   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5778       offset);
5779
5780   if (stream->use_allocator) {
5781     /* if we have a per-stream allocator, use it */
5782     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5783   }
5784
5785   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5786       size, &buf);
5787   if (G_UNLIKELY (ret != GST_FLOW_OK))
5788     goto beach;
5789
5790   if (size != sample_size) {
5791     pts += gst_util_uint64_scale_int (GST_SECOND,
5792         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5793     dts += gst_util_uint64_scale_int (GST_SECOND,
5794         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5795     duration = gst_util_uint64_scale_int (GST_SECOND,
5796         size / stream->bytes_per_frame, stream->timescale);
5797   }
5798
5799   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5800       dts, pts, duration, keyframe, min_time, offset);
5801
5802   if (size != sample_size) {
5803     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5804     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5805
5806     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5807         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5808     if (time_position >= segment->media_start) {
5809       /* inside the segment, update time_position, looks very familiar to
5810        * GStreamer segments, doesn't it? */
5811       stream->time_position = (time_position - segment->media_start) +
5812           segment->time;
5813     } else {
5814       /* not yet in segment, time does not yet increment. This means
5815        * that we are still prerolling keyframes to the decoder so it can
5816        * decode the first sample of the segment. */
5817       stream->time_position = segment->time;
5818     }
5819   }
5820
5821   /* combine flows */
5822   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5823   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5824    * we have no more data for the pad to push */
5825   if (ret == GST_FLOW_EOS)
5826     ret = GST_FLOW_OK;
5827
5828   stream->offset_in_sample += size;
5829   if (stream->offset_in_sample >= sample_size) {
5830     gst_qtdemux_advance_sample (qtdemux, stream);
5831   }
5832   goto beach;
5833
5834 next:
5835   gst_qtdemux_advance_sample (qtdemux, stream);
5836
5837 beach:
5838   return ret;
5839
5840   /* special cases */
5841 eos:
5842   {
5843     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5844     ret = GST_FLOW_EOS;
5845     goto beach;
5846   }
5847 eos_stream:
5848   {
5849     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5850     /* EOS will be raised if all are EOS */
5851     ret = GST_FLOW_OK;
5852     goto beach;
5853   }
5854 }
5855
5856 static void
5857 gst_qtdemux_loop (GstPad * pad)
5858 {
5859   GstQTDemux *qtdemux;
5860   guint64 cur_offset;
5861   GstFlowReturn ret;
5862
5863   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5864
5865   cur_offset = qtdemux->offset;
5866   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5867       cur_offset, qt_demux_state_string (qtdemux->state));
5868
5869   switch (qtdemux->state) {
5870     case QTDEMUX_STATE_INITIAL:
5871     case QTDEMUX_STATE_HEADER:
5872       ret = gst_qtdemux_loop_state_header (qtdemux);
5873       break;
5874     case QTDEMUX_STATE_MOVIE:
5875       ret = gst_qtdemux_loop_state_movie (qtdemux);
5876       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5877         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5878       }
5879       break;
5880     default:
5881       /* ouch */
5882       goto invalid_state;
5883   }
5884
5885   /* if something went wrong, pause */
5886   if (ret != GST_FLOW_OK)
5887     goto pause;
5888
5889 done:
5890   gst_object_unref (qtdemux);
5891   return;
5892
5893   /* ERRORS */
5894 invalid_state:
5895   {
5896     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5897         (NULL), ("streaming stopped, invalid state"));
5898     gst_pad_pause_task (pad);
5899     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5900     goto done;
5901   }
5902 pause:
5903   {
5904     const gchar *reason = gst_flow_get_name (ret);
5905
5906     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5907
5908     gst_pad_pause_task (pad);
5909
5910     /* fatal errors need special actions */
5911     /* check EOS */
5912     if (ret == GST_FLOW_EOS) {
5913       if (qtdemux->n_streams == 0) {
5914         /* we have no streams, post an error */
5915         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5916       }
5917       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5918         gint64 stop;
5919
5920         if ((stop = qtdemux->segment.stop) == -1)
5921           stop = qtdemux->segment.duration;
5922
5923         if (qtdemux->segment.rate >= 0) {
5924           GstMessage *message;
5925           GstEvent *event;
5926
5927           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5928           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5929               GST_FORMAT_TIME, stop);
5930           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5931           if (qtdemux->segment_seqnum) {
5932             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5933             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5934           }
5935           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5936           gst_qtdemux_push_event (qtdemux, event);
5937         } else {
5938           GstMessage *message;
5939           GstEvent *event;
5940
5941           /*  For Reverse Playback */
5942           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5943           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5944               GST_FORMAT_TIME, qtdemux->segment.start);
5945           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5946               qtdemux->segment.start);
5947           if (qtdemux->segment_seqnum) {
5948             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5949             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5950           }
5951           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5952           gst_qtdemux_push_event (qtdemux, event);
5953         }
5954       } else {
5955         GstEvent *event;
5956
5957         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5958         event = gst_event_new_eos ();
5959         if (qtdemux->segment_seqnum)
5960           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5961         gst_qtdemux_push_event (qtdemux, event);
5962       }
5963     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5964       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
5965       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5966     }
5967     goto done;
5968   }
5969 }
5970
5971 /*
5972  * has_next_entry
5973  *
5974  * Returns if there are samples to be played.
5975  */
5976 static gboolean
5977 has_next_entry (GstQTDemux * demux)
5978 {
5979   QtDemuxStream *stream;
5980   int i;
5981
5982   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5983
5984   for (i = 0; i < demux->n_streams; i++) {
5985     stream = demux->streams[i];
5986
5987     if (stream->sample_index == -1) {
5988       stream->sample_index = 0;
5989       stream->offset_in_sample = 0;
5990     }
5991
5992     if (stream->sample_index >= stream->n_samples) {
5993       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5994       continue;
5995     }
5996     GST_DEBUG_OBJECT (demux, "Found a sample");
5997     return TRUE;
5998   }
5999
6000   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6001   return FALSE;
6002 }
6003
6004 /*
6005  * next_entry_size
6006  *
6007  * Returns the size of the first entry at the current offset.
6008  * If -1, there are none (which means EOS or empty file).
6009  */
6010 static guint64
6011 next_entry_size (GstQTDemux * demux)
6012 {
6013   QtDemuxStream *stream;
6014   int i;
6015   int smallidx = -1;
6016   guint64 smalloffs = (guint64) - 1;
6017   QtDemuxSample *sample;
6018
6019   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6020       demux->offset);
6021
6022   for (i = 0; i < demux->n_streams; i++) {
6023     stream = demux->streams[i];
6024
6025     if (stream->sample_index == -1) {
6026       stream->sample_index = 0;
6027       stream->offset_in_sample = 0;
6028     }
6029
6030     if (stream->sample_index >= stream->n_samples) {
6031       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6032       continue;
6033     }
6034
6035     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6036       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6037           stream->sample_index);
6038       return -1;
6039     }
6040
6041     sample = &stream->samples[stream->sample_index];
6042
6043     GST_LOG_OBJECT (demux,
6044         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6045         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6046         sample->offset, sample->size);
6047
6048     if (((smalloffs == -1)
6049             || (sample->offset < smalloffs)) && (sample->size)) {
6050       smallidx = i;
6051       smalloffs = sample->offset;
6052     }
6053   }
6054
6055   GST_LOG_OBJECT (demux,
6056       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6057       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6058
6059   if (smallidx == -1)
6060     return -1;
6061
6062   stream = demux->streams[smallidx];
6063   sample = &stream->samples[stream->sample_index];
6064
6065   if (sample->offset >= demux->offset) {
6066     demux->todrop = sample->offset - demux->offset;
6067     return sample->size + demux->todrop;
6068   }
6069
6070   GST_DEBUG_OBJECT (demux,
6071       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6072   return -1;
6073 }
6074
6075 static void
6076 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6077 {
6078   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6079
6080   gst_element_post_message (GST_ELEMENT_CAST (demux),
6081       gst_message_new_element (GST_OBJECT_CAST (demux),
6082           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6083 }
6084
6085 static gboolean
6086 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6087 {
6088   GstEvent *event;
6089   gboolean res = 0;
6090
6091   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6092
6093   event =
6094       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6095       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6096       GST_SEEK_TYPE_NONE, -1);
6097
6098   /* store seqnum to drop flush events, they don't need to reach downstream */
6099   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6100   res = gst_pad_push_event (demux->sinkpad, event);
6101   demux->offset_seek_seqnum = 0;
6102
6103   return res;
6104 }
6105
6106 /* check for seekable upstream, above and beyond a mere query */
6107 static void
6108 gst_qtdemux_check_seekability (GstQTDemux * demux)
6109 {
6110   GstQuery *query;
6111   gboolean seekable = FALSE;
6112   gint64 start = -1, stop = -1;
6113
6114   if (demux->upstream_size)
6115     return;
6116
6117   if (demux->upstream_format_is_time)
6118     return;
6119
6120   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6121   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6122     GST_DEBUG_OBJECT (demux, "seeking query failed");
6123     goto done;
6124   }
6125
6126   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6127
6128   /* try harder to query upstream size if we didn't get it the first time */
6129   if (seekable && stop == -1) {
6130     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6131     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6132   }
6133
6134   /* if upstream doesn't know the size, it's likely that it's not seekable in
6135    * practice even if it technically may be seekable */
6136   if (seekable && (start != 0 || stop <= start)) {
6137     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6138     seekable = FALSE;
6139   }
6140
6141 done:
6142   gst_query_unref (query);
6143
6144   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6145       G_GUINT64_FORMAT ")", seekable, start, stop);
6146   demux->upstream_seekable = seekable;
6147   demux->upstream_size = seekable ? stop : -1;
6148 }
6149
6150 static void
6151 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6152 {
6153   g_return_if_fail (bytes <= demux->todrop);
6154
6155   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6156   gst_adapter_flush (demux->adapter, bytes);
6157   demux->neededbytes -= bytes;
6158   demux->offset += bytes;
6159   demux->todrop -= bytes;
6160 }
6161
6162 static void
6163 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6164 {
6165   if (G_UNLIKELY (demux->pending_newsegment)) {
6166     gint i;
6167
6168     gst_qtdemux_push_pending_newsegment (demux);
6169     /* clear to send tags on all streams */
6170     for (i = 0; i < demux->n_streams; i++) {
6171       QtDemuxStream *stream;
6172       stream = demux->streams[i];
6173       gst_qtdemux_push_tags (demux, stream);
6174       if (stream->sparse) {
6175         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6176         gst_pad_push_event (stream->pad,
6177             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6178       }
6179     }
6180   }
6181 }
6182
6183 static void
6184 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6185     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6186 {
6187   GstClockTime ts, dur;
6188   GstEvent *gap;
6189
6190   ts = pos;
6191   dur =
6192       stream->segments[segment_index].duration - (pos -
6193       stream->segments[segment_index].time);
6194   gap = gst_event_new_gap (ts, dur);
6195   stream->time_position += dur;
6196
6197   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6198       "segment: %" GST_PTR_FORMAT, gap);
6199   gst_pad_push_event (stream->pad, gap);
6200 }
6201
6202 static void
6203 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6204     QtDemuxStream * stream)
6205 {
6206   gint i;
6207
6208   /* Push any initial gap segments before proceeding to the
6209    * 'real' data */
6210   for (i = 0; i < stream->n_segments; i++) {
6211     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6212
6213     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6214       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6215           stream->time_position);
6216     } else {
6217       /* Only support empty segment at the beginning followed by
6218        * one non-empty segment, this was checked when parsing the
6219        * edts atom, arriving here is unexpected */
6220       g_assert (i + 1 == stream->n_segments);
6221       break;
6222     }
6223   }
6224 }
6225
6226 static GstFlowReturn
6227 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6228 {
6229   GstQTDemux *demux;
6230
6231   demux = GST_QTDEMUX (parent);
6232
6233   GST_DEBUG_OBJECT (demux,
6234       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6235       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6236       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6237       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6238       gst_buffer_get_size (inbuf), demux->offset);
6239
6240   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6241     gboolean is_gap_input = FALSE;
6242     gint i;
6243
6244     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6245
6246     for (i = 0; i < demux->n_streams; i++) {
6247       demux->streams[i]->discont = TRUE;
6248     }
6249
6250     /* Check if we can land back on our feet in the case where upstream is
6251      * handling the seeking/pushing of samples with gaps in between (like
6252      * in the case of trick-mode DASH for example) */
6253     if (demux->upstream_format_is_time
6254         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6255       gint i;
6256       for (i = 0; i < demux->n_streams; i++) {
6257         guint32 res;
6258         GST_LOG_OBJECT (demux,
6259             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6260             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6261         res =
6262             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6263             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6264         if (res != -1) {
6265           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6266           GST_LOG_OBJECT (demux,
6267               "Checking if sample %d from stream %d is valid (offset:%"
6268               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6269               sample->offset, sample->size);
6270           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6271             GST_LOG_OBJECT (demux,
6272                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6273                 res);
6274             is_gap_input = TRUE;
6275             /* We can go back to standard playback mode */
6276             demux->state = QTDEMUX_STATE_MOVIE;
6277             /* Remember which sample this stream is at */
6278             demux->streams[i]->sample_index = res;
6279             /* Finally update all push-based values to the expected values */
6280             demux->neededbytes = demux->streams[i]->samples[res].size;
6281             demux->offset = GST_BUFFER_OFFSET (inbuf);
6282             demux->mdatleft =
6283                 demux->mdatsize - demux->offset + demux->mdatoffset;
6284             demux->todrop = 0;
6285           }
6286         }
6287       }
6288       if (!is_gap_input) {
6289         /* Reset state if it's a real discont */
6290         demux->neededbytes = 16;
6291         demux->state = QTDEMUX_STATE_INITIAL;
6292         demux->offset = GST_BUFFER_OFFSET (inbuf);
6293       }
6294     }
6295     /* Reverse fragmented playback, need to flush all we have before
6296      * consuming a new fragment.
6297      * The samples array have the timestamps calculated by accumulating the
6298      * durations but this won't work for reverse playback of fragments as
6299      * the timestamps of a subsequent fragment should be smaller than the
6300      * previously received one. */
6301     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6302       gst_qtdemux_process_adapter (demux, TRUE);
6303       for (i = 0; i < demux->n_streams; i++)
6304         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6305     }
6306   }
6307
6308   gst_adapter_push (demux->adapter, inbuf);
6309
6310   GST_DEBUG_OBJECT (demux,
6311       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6312       demux->neededbytes, gst_adapter_available (demux->adapter));
6313
6314   return gst_qtdemux_process_adapter (demux, FALSE);
6315 }
6316
6317 static GstFlowReturn
6318 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6319 {
6320   GstFlowReturn ret = GST_FLOW_OK;
6321
6322   /* we never really mean to buffer that much */
6323   if (demux->neededbytes == -1) {
6324     goto eos;
6325   }
6326
6327   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6328       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6329
6330 #ifndef GST_DISABLE_GST_DEBUG
6331     {
6332       guint64 discont_offset, distance_from_discont;
6333
6334       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6335       distance_from_discont =
6336           gst_adapter_distance_from_discont (demux->adapter);
6337
6338       GST_DEBUG_OBJECT (demux,
6339           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6340           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6341           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6342           demux->offset, discont_offset, distance_from_discont);
6343     }
6344 #endif
6345
6346     switch (demux->state) {
6347       case QTDEMUX_STATE_INITIAL:{
6348         const guint8 *data;
6349         guint32 fourcc;
6350         guint64 size;
6351
6352         gst_qtdemux_check_seekability (demux);
6353
6354         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6355
6356         /* get fourcc/length, set neededbytes */
6357         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6358             &size, &fourcc);
6359         gst_adapter_unmap (demux->adapter);
6360         data = NULL;
6361         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6362             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6363         if (size == 0) {
6364           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6365               (_("This file is invalid and cannot be played.")),
6366               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6367                   GST_FOURCC_ARGS (fourcc)));
6368           ret = GST_FLOW_ERROR;
6369           break;
6370         }
6371         if (fourcc == FOURCC_mdat) {
6372           gint next_entry = next_entry_size (demux);
6373           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6374             /* we have the headers, start playback */
6375             demux->state = QTDEMUX_STATE_MOVIE;
6376             demux->neededbytes = next_entry;
6377             demux->mdatleft = size;
6378             demux->mdatsize = demux->mdatleft;
6379           } else {
6380             /* no headers yet, try to get them */
6381             guint bs;
6382             gboolean res;
6383             guint64 old, target;
6384
6385           buffer_data:
6386             old = demux->offset;
6387             target = old + size;
6388
6389             /* try to jump over the atom with a seek */
6390             /* only bother if it seems worth doing so,
6391              * and avoids possible upstream/server problems */
6392             if (demux->upstream_seekable &&
6393                 demux->upstream_size > 4 * (1 << 20)) {
6394               res = qtdemux_seek_offset (demux, target);
6395             } else {
6396               GST_DEBUG_OBJECT (demux, "skipping seek");
6397               res = FALSE;
6398             }
6399
6400             if (res) {
6401               GST_DEBUG_OBJECT (demux, "seek success");
6402               /* remember the offset fo the first mdat so we can seek back to it
6403                * after we have the headers */
6404               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6405                 demux->first_mdat = old;
6406                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6407                     demux->first_mdat);
6408               }
6409               /* seek worked, continue reading */
6410               demux->offset = target;
6411               demux->neededbytes = 16;
6412               demux->state = QTDEMUX_STATE_INITIAL;
6413             } else {
6414               /* seek failed, need to buffer */
6415               demux->offset = old;
6416               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6417               /* there may be multiple mdat (or alike) buffers */
6418               /* sanity check */
6419               if (demux->mdatbuffer)
6420                 bs = gst_buffer_get_size (demux->mdatbuffer);
6421               else
6422                 bs = 0;
6423               if (size + bs > 10 * (1 << 20))
6424                 goto no_moov;
6425               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6426               demux->neededbytes = size;
6427               if (!demux->mdatbuffer)
6428                 demux->mdatoffset = demux->offset;
6429             }
6430           }
6431         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6432           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6433               (_("This file is invalid and cannot be played.")),
6434               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6435                   GST_FOURCC_ARGS (fourcc), size));
6436           ret = GST_FLOW_ERROR;
6437           break;
6438         } else {
6439           /* this means we already started buffering and still no moov header,
6440            * let's continue buffering everything till we get moov */
6441           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6442                   || fourcc == FOURCC_moof))
6443             goto buffer_data;
6444           demux->neededbytes = size;
6445           demux->state = QTDEMUX_STATE_HEADER;
6446         }
6447         break;
6448       }
6449       case QTDEMUX_STATE_HEADER:{
6450         const guint8 *data;
6451         guint32 fourcc;
6452
6453         GST_DEBUG_OBJECT (demux, "In header");
6454
6455         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6456
6457         /* parse the header */
6458         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6459             &fourcc);
6460         if (fourcc == FOURCC_moov) {
6461           gint n;
6462
6463           /* in usual fragmented setup we could try to scan for more
6464            * and end up at the the moov (after mdat) again */
6465           if (demux->got_moov && demux->n_streams > 0 &&
6466               (!demux->fragmented
6467                   || demux->last_moov_offset == demux->offset)) {
6468             GST_DEBUG_OBJECT (demux,
6469                 "Skipping moov atom as we have (this) one already");
6470           } else {
6471             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6472
6473             if (demux->got_moov && demux->fragmented) {
6474               GST_DEBUG_OBJECT (demux,
6475                   "Got a second moov, clean up data from old one");
6476               if (demux->moov_node_compressed) {
6477                 g_node_destroy (demux->moov_node_compressed);
6478                 if (demux->moov_node)
6479                   g_free (demux->moov_node->data);
6480               }
6481               demux->moov_node_compressed = NULL;
6482               if (demux->moov_node)
6483                 g_node_destroy (demux->moov_node);
6484               demux->moov_node = NULL;
6485             } else {
6486               /* prepare newsegment to send when streaming actually starts */
6487               if (!demux->pending_newsegment) {
6488                 demux->pending_newsegment =
6489                     gst_event_new_segment (&demux->segment);
6490                 if (demux->segment_seqnum)
6491                   gst_event_set_seqnum (demux->pending_newsegment,
6492                       demux->segment_seqnum);
6493               }
6494             }
6495
6496             demux->last_moov_offset = demux->offset;
6497
6498             qtdemux_parse_moov (demux, data, demux->neededbytes);
6499             qtdemux_node_dump (demux, demux->moov_node);
6500             qtdemux_parse_tree (demux);
6501             qtdemux_prepare_streams (demux);
6502             if (!demux->got_moov)
6503               qtdemux_expose_streams (demux);
6504             else {
6505
6506               for (n = 0; n < demux->n_streams; n++) {
6507                 QtDemuxStream *stream = demux->streams[n];
6508
6509                 gst_qtdemux_configure_stream (demux, stream);
6510               }
6511             }
6512
6513             demux->got_moov = TRUE;
6514             gst_qtdemux_check_send_pending_segment (demux);
6515
6516             /* fragmented streams headers shouldn't contain edts atoms */
6517             if (!demux->fragmented) {
6518               for (n = 0; n < demux->n_streams; n++) {
6519                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6520                     demux->streams[n]);
6521               }
6522             }
6523
6524             if (demux->moov_node_compressed) {
6525               g_node_destroy (demux->moov_node_compressed);
6526               g_free (demux->moov_node->data);
6527             }
6528             demux->moov_node_compressed = NULL;
6529             g_node_destroy (demux->moov_node);
6530             demux->moov_node = NULL;
6531             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6532           }
6533         } else if (fourcc == FOURCC_moof) {
6534           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6535             guint64 dist = 0;
6536             GstClockTime prev_pts;
6537             guint64 prev_offset;
6538             guint64 adapter_discont_offset, adapter_discont_dist;
6539
6540             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6541
6542             /*
6543              * The timestamp of the moof buffer is relevant as some scenarios
6544              * won't have the initial timestamp in the atoms. Whenever a new
6545              * buffer has started, we get that buffer's PTS and use it as a base
6546              * timestamp for the trun entries.
6547              *
6548              * To keep track of the current buffer timestamp and starting point
6549              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6550              * from the beggining of the buffer, with the distance and demux->offset
6551              * we know if it is still the same buffer or not.
6552              */
6553             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6554             prev_offset = demux->offset - dist;
6555             if (demux->fragment_start_offset == -1
6556                 || prev_offset > demux->fragment_start_offset) {
6557               demux->fragment_start_offset = prev_offset;
6558               demux->fragment_start = prev_pts;
6559               GST_DEBUG_OBJECT (demux,
6560                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6561                   GST_TIME_FORMAT, demux->fragment_start_offset,
6562                   GST_TIME_ARGS (demux->fragment_start));
6563             }
6564
6565             /* We can't use prev_offset() here because this would require
6566              * upstream to set consistent and correct offsets on all buffers
6567              * since the discont. Nothing ever did that in the past and we
6568              * would break backwards compatibility here then.
6569              * Instead take the offset we had at the last discont and count
6570              * the bytes from there. This works with old code as there would
6571              * be no discont between moov and moof, and also works with
6572              * adaptivedemux which correctly sets offset and will set the
6573              * DISCONT flag accordingly when needed.
6574              *
6575              * We also only do this for upstream TIME segments as otherwise
6576              * there are potential backwards compatibility problems with
6577              * seeking in PUSH mode and upstream providing inconsistent
6578              * timestamps. */
6579             adapter_discont_offset =
6580                 gst_adapter_offset_at_discont (demux->adapter);
6581             adapter_discont_dist =
6582                 gst_adapter_distance_from_discont (demux->adapter);
6583
6584             GST_DEBUG_OBJECT (demux,
6585                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6586                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6587                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6588
6589             if (demux->upstream_format_is_time) {
6590               demux->moof_offset = adapter_discont_offset;
6591               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6592                 demux->moof_offset += adapter_discont_dist;
6593               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6594                 demux->moof_offset = demux->offset;
6595             } else {
6596               demux->moof_offset = demux->offset;
6597             }
6598
6599             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6600                     demux->moof_offset, NULL)) {
6601               gst_adapter_unmap (demux->adapter);
6602               ret = GST_FLOW_ERROR;
6603               goto done;
6604             }
6605             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6606             if (demux->mss_mode && !demux->exposed) {
6607               if (!demux->pending_newsegment) {
6608                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6609                 demux->pending_newsegment =
6610                     gst_event_new_segment (&demux->segment);
6611                 if (demux->segment_seqnum)
6612                   gst_event_set_seqnum (demux->pending_newsegment,
6613                       demux->segment_seqnum);
6614               }
6615               qtdemux_expose_streams (demux);
6616             }
6617           } else {
6618             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6619           }
6620         } else if (fourcc == FOURCC_ftyp) {
6621           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6622           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6623         } else if (fourcc == FOURCC_uuid) {
6624           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6625           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6626         } else if (fourcc == FOURCC_sidx) {
6627           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6628           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6629         } else {
6630           switch (fourcc) {
6631             case FOURCC_styp:
6632               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6633                * FALLTHROUGH */
6634             case FOURCC_free:
6635               /* [free] is a padding atom */
6636               GST_DEBUG_OBJECT (demux,
6637                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6638                   GST_FOURCC_ARGS (fourcc));
6639               break;
6640             default:
6641               GST_WARNING_OBJECT (demux,
6642                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6643                   GST_FOURCC_ARGS (fourcc));
6644               /* Let's jump that one and go back to initial state */
6645               break;
6646           }
6647         }
6648         gst_adapter_unmap (demux->adapter);
6649         data = NULL;
6650
6651         if (demux->mdatbuffer && demux->n_streams) {
6652           gsize remaining_data_size = 0;
6653
6654           /* the mdat was before the header */
6655           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6656               demux->n_streams, demux->mdatbuffer);
6657           /* restore our adapter/offset view of things with upstream;
6658            * put preceding buffered data ahead of current moov data.
6659            * This should also handle evil mdat, moov, mdat cases and alike */
6660           gst_adapter_flush (demux->adapter, demux->neededbytes);
6661
6662           /* Store any remaining data after the mdat for later usage */
6663           remaining_data_size = gst_adapter_available (demux->adapter);
6664           if (remaining_data_size > 0) {
6665             g_assert (demux->restoredata_buffer == NULL);
6666             demux->restoredata_buffer =
6667                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6668             demux->restoredata_offset = demux->offset + demux->neededbytes;
6669             GST_DEBUG_OBJECT (demux,
6670                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6671                 G_GUINT64_FORMAT, remaining_data_size,
6672                 demux->restoredata_offset);
6673           }
6674
6675           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6676           demux->mdatbuffer = NULL;
6677           demux->offset = demux->mdatoffset;
6678           demux->neededbytes = next_entry_size (demux);
6679           demux->state = QTDEMUX_STATE_MOVIE;
6680           demux->mdatleft = gst_adapter_available (demux->adapter);
6681           demux->mdatsize = demux->mdatleft;
6682         } else {
6683           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6684           gst_adapter_flush (demux->adapter, demux->neededbytes);
6685
6686           /* only go back to the mdat if there are samples to play */
6687           if (demux->got_moov && demux->first_mdat != -1
6688               && has_next_entry (demux)) {
6689             gboolean res;
6690
6691             /* we need to seek back */
6692             res = qtdemux_seek_offset (demux, demux->first_mdat);
6693             if (res) {
6694               demux->offset = demux->first_mdat;
6695             } else {
6696               GST_DEBUG_OBJECT (demux, "Seek back failed");
6697             }
6698           } else {
6699             demux->offset += demux->neededbytes;
6700           }
6701           demux->neededbytes = 16;
6702           demux->state = QTDEMUX_STATE_INITIAL;
6703         }
6704
6705         break;
6706       }
6707       case QTDEMUX_STATE_BUFFER_MDAT:{
6708         GstBuffer *buf;
6709         guint8 fourcc[4];
6710
6711         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6712             demux->offset);
6713         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6714         gst_buffer_extract (buf, 0, fourcc, 4);
6715         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6716             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6717         if (demux->mdatbuffer)
6718           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6719         else
6720           demux->mdatbuffer = buf;
6721         demux->offset += demux->neededbytes;
6722         demux->neededbytes = 16;
6723         demux->state = QTDEMUX_STATE_INITIAL;
6724         gst_qtdemux_post_progress (demux, 1, 1);
6725
6726         break;
6727       }
6728       case QTDEMUX_STATE_MOVIE:{
6729         QtDemuxStream *stream = NULL;
6730         QtDemuxSample *sample;
6731         int i = -1;
6732         GstClockTime dts, pts, duration;
6733         gboolean keyframe;
6734
6735         GST_DEBUG_OBJECT (demux,
6736             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6737
6738         if (demux->fragmented) {
6739           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6740               demux->mdatleft);
6741           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6742             /* if needed data starts within this atom,
6743              * then it should not exceed this atom */
6744             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6745               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6746                   (_("This file is invalid and cannot be played.")),
6747                   ("sample data crosses atom boundary"));
6748               ret = GST_FLOW_ERROR;
6749               break;
6750             }
6751             demux->mdatleft -= demux->neededbytes;
6752           } else {
6753             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6754             /* so we are dropping more than left in this atom */
6755             gst_qtdemux_drop_data (demux, demux->mdatleft);
6756             demux->mdatleft = 0;
6757
6758             /* need to resume atom parsing so we do not miss any other pieces */
6759             demux->state = QTDEMUX_STATE_INITIAL;
6760             demux->neededbytes = 16;
6761
6762             /* check if there was any stored post mdat data from previous buffers */
6763             if (demux->restoredata_buffer) {
6764               g_assert (gst_adapter_available (demux->adapter) == 0);
6765
6766               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6767               demux->restoredata_buffer = NULL;
6768               demux->offset = demux->restoredata_offset;
6769             }
6770
6771             break;
6772           }
6773         }
6774
6775         if (demux->todrop) {
6776           if (demux->cenc_aux_info_offset > 0) {
6777             GstByteReader br;
6778             const guint8 *data;
6779
6780             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6781             data = gst_adapter_map (demux->adapter, demux->todrop);
6782             gst_byte_reader_init (&br, data + 8, demux->todrop);
6783             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6784                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6785               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6786               ret = GST_FLOW_ERROR;
6787               gst_adapter_unmap (demux->adapter);
6788               g_free (demux->cenc_aux_info_sizes);
6789               demux->cenc_aux_info_sizes = NULL;
6790               goto done;
6791             }
6792             demux->cenc_aux_info_offset = 0;
6793             g_free (demux->cenc_aux_info_sizes);
6794             demux->cenc_aux_info_sizes = NULL;
6795             gst_adapter_unmap (demux->adapter);
6796           }
6797           gst_qtdemux_drop_data (demux, demux->todrop);
6798         }
6799
6800         /* first buffer? */
6801         /* initial newsegment sent here after having added pads,
6802          * possible others in sink_event */
6803         gst_qtdemux_check_send_pending_segment (demux);
6804
6805         /* Figure out which stream this packet belongs to */
6806         for (i = 0; i < demux->n_streams; i++) {
6807           stream = demux->streams[i];
6808           if (stream->sample_index >= stream->n_samples)
6809             continue;
6810           GST_LOG_OBJECT (demux,
6811               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6812               " / size:%d)", i, stream->sample_index,
6813               stream->samples[stream->sample_index].offset,
6814               stream->samples[stream->sample_index].size);
6815
6816           if (stream->samples[stream->sample_index].offset == demux->offset)
6817             break;
6818         }
6819
6820         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6821           goto unknown_stream;
6822
6823         if (stream->new_caps) {
6824           gst_qtdemux_configure_stream (demux, stream);
6825         }
6826
6827         /* Put data in a buffer, set timestamps, caps, ... */
6828         sample = &stream->samples[stream->sample_index];
6829
6830         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6831           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6832               GST_FOURCC_ARGS (stream->fourcc));
6833
6834           dts = QTSAMPLE_DTS (stream, sample);
6835           pts = QTSAMPLE_PTS (stream, sample);
6836           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6837           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6838
6839           /* check for segment end */
6840           if (G_UNLIKELY (demux->segment.stop != -1
6841                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6842             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6843             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6844
6845             /* skip this data, stream is EOS */
6846             gst_adapter_flush (demux->adapter, demux->neededbytes);
6847
6848             /* check if all streams are eos */
6849             ret = GST_FLOW_EOS;
6850             for (i = 0; i < demux->n_streams; i++) {
6851               if (!STREAM_IS_EOS (demux->streams[i])) {
6852                 ret = GST_FLOW_OK;
6853                 break;
6854               }
6855             }
6856
6857             if (ret == GST_FLOW_EOS) {
6858               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6859               goto eos;
6860             }
6861           } else {
6862             GstBuffer *outbuf;
6863
6864             outbuf =
6865                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6866
6867             /* FIXME: should either be an assert or a plain check */
6868             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6869
6870             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6871                 dts, pts, duration, keyframe, dts, demux->offset);
6872           }
6873
6874           /* combine flows */
6875           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6876         } else {
6877           /* skip this data, stream is EOS */
6878           gst_adapter_flush (demux->adapter, demux->neededbytes);
6879         }
6880
6881         stream->sample_index++;
6882         stream->offset_in_sample = 0;
6883
6884         /* update current offset and figure out size of next buffer */
6885         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6886             demux->offset, demux->neededbytes);
6887         demux->offset += demux->neededbytes;
6888         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6889             demux->offset);
6890
6891         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6892           if (demux->fragmented) {
6893             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6894             /* there may be more to follow, only finish this atom */
6895             demux->todrop = demux->mdatleft;
6896             demux->neededbytes = demux->todrop;
6897             break;
6898           }
6899           goto eos;
6900         }
6901         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
6902           goto non_ok_unlinked_flow;
6903         }
6904         break;
6905       }
6906       default:
6907         goto invalid_state;
6908     }
6909   }
6910
6911   /* when buffering movie data, at least show user something is happening */
6912   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6913       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6914     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6915         demux->neededbytes);
6916   }
6917 done:
6918
6919   return ret;
6920
6921   /* ERRORS */
6922 non_ok_unlinked_flow:
6923   {
6924     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6925         gst_flow_get_name (ret));
6926     return ret;
6927   }
6928 unknown_stream:
6929   {
6930     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6931     ret = GST_FLOW_ERROR;
6932     goto done;
6933   }
6934 eos:
6935   {
6936     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6937     ret = GST_FLOW_EOS;
6938     goto done;
6939   }
6940 invalid_state:
6941   {
6942     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6943         (NULL), ("qtdemuxer invalid state %d", demux->state));
6944     ret = GST_FLOW_ERROR;
6945     goto done;
6946   }
6947 no_moov:
6948   {
6949     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6950         (NULL), ("no 'moov' atom within the first 10 MB"));
6951     ret = GST_FLOW_ERROR;
6952     goto done;
6953   }
6954 }
6955
6956 static gboolean
6957 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6958 {
6959   GstQuery *query;
6960   gboolean pull_mode;
6961
6962   query = gst_query_new_scheduling ();
6963
6964   if (!gst_pad_peer_query (sinkpad, query)) {
6965     gst_query_unref (query);
6966     goto activate_push;
6967   }
6968
6969   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6970       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6971   gst_query_unref (query);
6972
6973   if (!pull_mode)
6974     goto activate_push;
6975
6976   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6977   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6978
6979 activate_push:
6980   {
6981     GST_DEBUG_OBJECT (sinkpad, "activating push");
6982     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6983   }
6984 }
6985
6986 static gboolean
6987 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6988     GstPadMode mode, gboolean active)
6989 {
6990   gboolean res;
6991   GstQTDemux *demux = GST_QTDEMUX (parent);
6992
6993   switch (mode) {
6994     case GST_PAD_MODE_PUSH:
6995       demux->pullbased = FALSE;
6996       res = TRUE;
6997       break;
6998     case GST_PAD_MODE_PULL:
6999       if (active) {
7000         demux->pullbased = TRUE;
7001         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7002             sinkpad, NULL);
7003       } else {
7004         res = gst_pad_stop_task (sinkpad);
7005       }
7006       break;
7007     default:
7008       res = FALSE;
7009       break;
7010   }
7011   return res;
7012 }
7013
7014 #ifdef HAVE_ZLIB
7015 static void *
7016 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7017 {
7018   guint8 *buffer;
7019   z_stream z;
7020   int ret;
7021
7022   memset (&z, 0, sizeof (z));
7023   z.zalloc = NULL;
7024   z.zfree = NULL;
7025   z.opaque = NULL;
7026
7027   if ((ret = inflateInit (&z)) != Z_OK) {
7028     GST_ERROR ("inflateInit() returned %d", ret);
7029     return NULL;
7030   }
7031
7032   z.next_in = z_buffer;
7033   z.avail_in = z_length;
7034
7035   buffer = (guint8 *) g_malloc (*length);
7036   z.avail_out = *length;
7037   z.next_out = (Bytef *) buffer;
7038   do {
7039     ret = inflate (&z, Z_NO_FLUSH);
7040     if (ret == Z_STREAM_END) {
7041       break;
7042     } else if (ret != Z_OK) {
7043       GST_WARNING ("inflate() returned %d", ret);
7044       break;
7045     }
7046
7047     *length += 4096;
7048     buffer = (guint8 *) g_realloc (buffer, *length);
7049     z.next_out = (Bytef *) (buffer + z.total_out);
7050     z.avail_out += 4096;
7051   } while (z.avail_in > 0);
7052
7053   if (ret != Z_STREAM_END) {
7054     g_free (buffer);
7055     buffer = NULL;
7056     *length = 0;
7057   } else {
7058     *length = z.total_out;
7059   }
7060
7061   inflateEnd (&z);
7062
7063   return buffer;
7064 }
7065 #endif /* HAVE_ZLIB */
7066
7067 static gboolean
7068 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7069 {
7070   GNode *cmov;
7071
7072   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7073
7074   /* counts as header data */
7075   qtdemux->header_size += length;
7076
7077   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7078   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7079
7080   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7081   if (cmov) {
7082     guint32 method;
7083     GNode *dcom;
7084     GNode *cmvd;
7085     guint32 dcom_len;
7086
7087     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7088     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7089     if (dcom == NULL || cmvd == NULL)
7090       goto invalid_compression;
7091
7092     dcom_len = QT_UINT32 (dcom->data);
7093     if (dcom_len < 12)
7094       goto invalid_compression;
7095
7096     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7097     switch (method) {
7098 #ifdef HAVE_ZLIB
7099       case FOURCC_zlib:{
7100         guint uncompressed_length;
7101         guint compressed_length;
7102         guint8 *buf;
7103         guint32 cmvd_len;
7104
7105         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7106         if (cmvd_len < 12)
7107           goto invalid_compression;
7108
7109         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7110         compressed_length = cmvd_len - 12;
7111         GST_LOG ("length = %u", uncompressed_length);
7112
7113         buf =
7114             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7115             compressed_length, &uncompressed_length);
7116
7117         if (buf) {
7118           qtdemux->moov_node_compressed = qtdemux->moov_node;
7119           qtdemux->moov_node = g_node_new (buf);
7120
7121           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7122               uncompressed_length);
7123         }
7124         break;
7125       }
7126 #endif /* HAVE_ZLIB */
7127       default:
7128         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7129             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7130         break;
7131     }
7132   }
7133   return TRUE;
7134
7135   /* ERRORS */
7136 invalid_compression:
7137   {
7138     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7139     return FALSE;
7140   }
7141 }
7142
7143 static gboolean
7144 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7145     const guint8 * end)
7146 {
7147   while (G_UNLIKELY (buf < end)) {
7148     GNode *child;
7149     guint32 len;
7150
7151     if (G_UNLIKELY (buf + 4 > end)) {
7152       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7153       break;
7154     }
7155     len = QT_UINT32 (buf);
7156     if (G_UNLIKELY (len == 0)) {
7157       GST_LOG_OBJECT (qtdemux, "empty container");
7158       break;
7159     }
7160     if (G_UNLIKELY (len < 8)) {
7161       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7162       break;
7163     }
7164     if (G_UNLIKELY (len > (end - buf))) {
7165       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7166           (gint) (end - buf));
7167       break;
7168     }
7169
7170     child = g_node_new ((guint8 *) buf);
7171     g_node_append (node, child);
7172     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7173     qtdemux_parse_node (qtdemux, child, buf, len);
7174
7175     buf += len;
7176   }
7177   return TRUE;
7178 }
7179
7180 static gboolean
7181 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7182     GNode * xdxt)
7183 {
7184   int len = QT_UINT32 (xdxt->data);
7185   guint8 *buf = xdxt->data;
7186   guint8 *end = buf + len;
7187   GstBuffer *buffer;
7188
7189   /* skip size and type */
7190   buf += 8;
7191   end -= 8;
7192
7193   while (buf < end) {
7194     gint size;
7195     guint32 type;
7196
7197     size = QT_UINT32 (buf);
7198     type = QT_FOURCC (buf + 4);
7199
7200     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7201
7202     if (buf + size > end || size <= 0)
7203       break;
7204
7205     buf += 8;
7206     size -= 8;
7207
7208     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7209         GST_FOURCC_ARGS (type));
7210
7211     switch (type) {
7212       case FOURCC_tCtH:
7213         buffer = gst_buffer_new_and_alloc (size);
7214         gst_buffer_fill (buffer, 0, buf, size);
7215         stream->buffers = g_slist_append (stream->buffers, buffer);
7216         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7217         break;
7218       case FOURCC_tCt_:
7219         buffer = gst_buffer_new_and_alloc (size);
7220         gst_buffer_fill (buffer, 0, buf, size);
7221         stream->buffers = g_slist_append (stream->buffers, buffer);
7222         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7223         break;
7224       case FOURCC_tCtC:
7225         buffer = gst_buffer_new_and_alloc (size);
7226         gst_buffer_fill (buffer, 0, buf, size);
7227         stream->buffers = g_slist_append (stream->buffers, buffer);
7228         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7229         break;
7230       default:
7231         GST_WARNING_OBJECT (qtdemux,
7232             "unknown theora cookie %" GST_FOURCC_FORMAT,
7233             GST_FOURCC_ARGS (type));
7234         break;
7235     }
7236     buf += size;
7237   }
7238   return TRUE;
7239 }
7240
7241 static gboolean
7242 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7243     guint length)
7244 {
7245   guint32 fourcc = 0;
7246   guint32 node_length = 0;
7247   const QtNodeType *type;
7248   const guint8 *end;
7249
7250   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7251
7252   if (G_UNLIKELY (length < 8))
7253     goto not_enough_data;
7254
7255   node_length = QT_UINT32 (buffer);
7256   fourcc = QT_FOURCC (buffer + 4);
7257
7258   /* ignore empty nodes */
7259   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7260     return TRUE;
7261
7262   type = qtdemux_type_get (fourcc);
7263
7264   end = buffer + length;
7265
7266   GST_LOG_OBJECT (qtdemux,
7267       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7268       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7269
7270   if (node_length > length)
7271     goto broken_atom_size;
7272
7273   if (type->flags & QT_FLAG_CONTAINER) {
7274     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7275   } else {
7276     switch (fourcc) {
7277       case FOURCC_stsd:
7278       {
7279         if (node_length < 20) {
7280           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7281           break;
7282         }
7283         GST_DEBUG_OBJECT (qtdemux,
7284             "parsing stsd (sample table, sample description) atom");
7285         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7286         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7287         break;
7288       }
7289       case FOURCC_mp4a:
7290       case FOURCC_alac:
7291       case FOURCC_fLaC:
7292       {
7293         guint32 version;
7294         guint32 offset;
7295         guint min_size;
7296
7297         /* also read alac (or whatever) in stead of mp4a in the following,
7298          * since a similar layout is used in other cases as well */
7299         if (fourcc == FOURCC_mp4a)
7300           min_size = 20;
7301         else if (fourcc == FOURCC_fLaC)
7302           min_size = 86;
7303         else
7304           min_size = 40;
7305
7306         /* There are two things we might encounter here: a true mp4a atom, and
7307            an mp4a entry in an stsd atom. The latter is what we're interested
7308            in, and it looks like an atom, but isn't really one. The true mp4a
7309            atom is short, so we detect it based on length here. */
7310         if (length < min_size) {
7311           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7312               GST_FOURCC_ARGS (fourcc));
7313           break;
7314         }
7315
7316         /* 'version' here is the sound sample description version. Types 0 and
7317            1 are documented in the QTFF reference, but type 2 is not: it's
7318            described in Apple header files instead (struct SoundDescriptionV2
7319            in Movies.h) */
7320         version = QT_UINT16 (buffer + 16);
7321
7322         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7323             GST_FOURCC_ARGS (fourcc), version);
7324
7325         /* parse any esds descriptors */
7326         switch (version) {
7327           case 0:
7328             offset = 0x24;
7329             break;
7330           case 1:
7331             offset = 0x34;
7332             break;
7333           case 2:
7334             offset = 0x48;
7335             break;
7336           default:
7337             GST_WARNING_OBJECT (qtdemux,
7338                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7339                 GST_FOURCC_ARGS (fourcc), version);
7340             offset = 0;
7341             break;
7342         }
7343         if (offset)
7344           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7345         break;
7346       }
7347       case FOURCC_mp4v:
7348       case FOURCC_MP4V:
7349       case FOURCC_fmp4:
7350       case FOURCC_FMP4:
7351       case FOURCC_apcs:
7352       case FOURCC_apch:
7353       case FOURCC_apcn:
7354       case FOURCC_apco:
7355       case FOURCC_ap4h:
7356       case FOURCC_xvid:
7357       case FOURCC_XVID:
7358       case FOURCC_H264:
7359       case FOURCC_avc1:
7360       case FOURCC_avc3:
7361       case FOURCC_H265:
7362       case FOURCC_hvc1:
7363       case FOURCC_hev1:
7364       case FOURCC_mjp2:
7365       case FOURCC_encv:
7366       {
7367         guint32 version;
7368         guint32 str_len;
7369
7370         /* codec_data is contained inside these atoms, which all have
7371          * the same format. */
7372         /* video sample description size is 86 bytes without extension.
7373          * node_length have to be bigger than 86 bytes because video sample
7374          * description can include extenstions such as esds, fiel, glbl, etc. */
7375         if (node_length < 86) {
7376           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7377               " sample description length too short (%u < 86)",
7378               GST_FOURCC_ARGS (fourcc), node_length);
7379           break;
7380         }
7381
7382         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7383             GST_FOURCC_ARGS (fourcc));
7384
7385         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7386          *              its data format.
7387          * revision level (2 bytes) : must be set to 0. */
7388         version = QT_UINT32 (buffer + 16);
7389         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7390
7391         /* compressor name : PASCAL string and informative purposes
7392          * first byte : the number of bytes to be displayed.
7393          *              it has to be less than 32 because it is reserved
7394          *              space of 32 bytes total including itself. */
7395         str_len = QT_UINT8 (buffer + 50);
7396         if (str_len < 32)
7397           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7398               (char *) buffer + 51);
7399         else
7400           GST_WARNING_OBJECT (qtdemux,
7401               "compressorname length too big (%u > 31)", str_len);
7402
7403         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7404             end - buffer);
7405         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7406         break;
7407       }
7408       case FOURCC_meta:
7409       {
7410         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7411         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7412         break;
7413       }
7414       case FOURCC_mp4s:
7415       {
7416         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7417         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7418         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7419         break;
7420       }
7421       case FOURCC_XiTh:
7422       {
7423         guint32 version;
7424         guint32 offset;
7425
7426         if (length < 16) {
7427           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7428               GST_FOURCC_ARGS (fourcc));
7429           break;
7430         }
7431
7432         version = QT_UINT32 (buffer + 12);
7433         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7434
7435         switch (version) {
7436           case 0x00000001:
7437             offset = 0x62;
7438             break;
7439           default:
7440             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7441             offset = 0;
7442             break;
7443         }
7444         if (offset) {
7445           if (length < offset) {
7446             GST_WARNING_OBJECT (qtdemux,
7447                 "skipping too small %" GST_FOURCC_FORMAT " box",
7448                 GST_FOURCC_ARGS (fourcc));
7449             break;
7450           }
7451           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7452         }
7453         break;
7454       }
7455       case FOURCC_in24:
7456       {
7457         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7458         break;
7459       }
7460       case FOURCC_uuid:
7461       {
7462         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7463         break;
7464       }
7465       case FOURCC_enca:
7466       {
7467         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7468         break;
7469       }
7470       default:
7471         if (!strcmp (type->name, "unknown"))
7472           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7473         break;
7474     }
7475   }
7476   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7477       GST_FOURCC_ARGS (fourcc));
7478   return TRUE;
7479
7480 /* ERRORS */
7481 not_enough_data:
7482   {
7483     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7484         (_("This file is corrupt and cannot be played.")),
7485         ("Not enough data for an atom header, got only %u bytes", length));
7486     return FALSE;
7487   }
7488 broken_atom_size:
7489   {
7490     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7491         (_("This file is corrupt and cannot be played.")),
7492         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7493             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7494             length));
7495     return FALSE;
7496   }
7497 }
7498
7499 static GNode *
7500 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7501 {
7502   GNode *child;
7503   guint8 *buffer;
7504   guint32 child_fourcc;
7505
7506   for (child = g_node_first_child (node); child;
7507       child = g_node_next_sibling (child)) {
7508     buffer = (guint8 *) child->data;
7509
7510     child_fourcc = QT_FOURCC (buffer + 4);
7511
7512     if (G_UNLIKELY (child_fourcc == fourcc)) {
7513       return child;
7514     }
7515   }
7516   return NULL;
7517 }
7518
7519 static GNode *
7520 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7521     GstByteReader * parser)
7522 {
7523   GNode *child;
7524   guint8 *buffer;
7525   guint32 child_fourcc, child_len;
7526
7527   for (child = g_node_first_child (node); child;
7528       child = g_node_next_sibling (child)) {
7529     buffer = (guint8 *) child->data;
7530
7531     child_len = QT_UINT32 (buffer);
7532     child_fourcc = QT_FOURCC (buffer + 4);
7533
7534     if (G_UNLIKELY (child_fourcc == fourcc)) {
7535       if (G_UNLIKELY (child_len < (4 + 4)))
7536         return NULL;
7537       /* FIXME: must verify if atom length < parent atom length */
7538       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7539       return child;
7540     }
7541   }
7542   return NULL;
7543 }
7544
7545 static GNode *
7546 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7547 {
7548   return g_node_nth_child (node, index);
7549 }
7550
7551 static GNode *
7552 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7553     GstByteReader * parser)
7554 {
7555   GNode *child;
7556   guint8 *buffer;
7557   guint32 child_fourcc, child_len;
7558
7559   for (child = g_node_next_sibling (node); child;
7560       child = g_node_next_sibling (child)) {
7561     buffer = (guint8 *) child->data;
7562
7563     child_fourcc = QT_FOURCC (buffer + 4);
7564
7565     if (child_fourcc == fourcc) {
7566       if (parser) {
7567         child_len = QT_UINT32 (buffer);
7568         if (G_UNLIKELY (child_len < (4 + 4)))
7569           return NULL;
7570         /* FIXME: must verify if atom length < parent atom length */
7571         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7572       }
7573       return child;
7574     }
7575   }
7576   return NULL;
7577 }
7578
7579 static GNode *
7580 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7581 {
7582   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7583 }
7584
7585 static void
7586 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7587 {
7588 /* FIXME: This can only reliably work if demuxers have a
7589  * separate streaming thread per srcpad. This should be
7590  * done in a demuxer base class, which integrates parts
7591  * of multiqueue
7592  *
7593  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7594  */
7595 #if 0
7596   GstQuery *query;
7597
7598   query = gst_query_new_allocation (stream->caps, FALSE);
7599
7600   if (!gst_pad_peer_query (stream->pad, query)) {
7601     /* not a problem, just debug a little */
7602     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7603   }
7604
7605   if (stream->allocator)
7606     gst_object_unref (stream->allocator);
7607
7608   if (gst_query_get_n_allocation_params (query) > 0) {
7609     /* try the allocator */
7610     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7611         &stream->params);
7612     stream->use_allocator = TRUE;
7613   } else {
7614     stream->allocator = NULL;
7615     gst_allocation_params_init (&stream->params);
7616     stream->use_allocator = FALSE;
7617   }
7618   gst_query_unref (query);
7619 #endif
7620 }
7621
7622 static gboolean
7623 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7624     QtDemuxStream * stream)
7625 {
7626   GstStructure *s;
7627   const gchar *selected_system;
7628
7629   g_return_val_if_fail (qtdemux != NULL, FALSE);
7630   g_return_val_if_fail (stream != NULL, FALSE);
7631   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7632
7633   if (stream->protection_scheme_type != FOURCC_cenc) {
7634     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7635     return FALSE;
7636   }
7637   if (qtdemux->protection_system_ids == NULL) {
7638     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7639         "cenc protection system information has been found");
7640     return FALSE;
7641   }
7642   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7643   selected_system = gst_protection_select_system ((const gchar **)
7644       qtdemux->protection_system_ids->pdata);
7645   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7646       qtdemux->protection_system_ids->len - 1);
7647   if (!selected_system) {
7648     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7649         "suitable decryptor element has been found");
7650     return FALSE;
7651   }
7652
7653   s = gst_caps_get_structure (stream->caps, 0);
7654   if (!gst_structure_has_name (s, "application/x-cenc")) {
7655     gst_structure_set (s,
7656         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7657         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7658         NULL);
7659     gst_structure_set_name (s, "application/x-cenc");
7660   }
7661   return TRUE;
7662 }
7663
7664 static gboolean
7665 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7666 {
7667   if (stream->subtype == FOURCC_vide) {
7668     /* fps is calculated base on the duration of the average framerate since
7669      * qt does not have a fixed framerate. */
7670     gboolean fps_available = TRUE;
7671
7672     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7673       /* still frame */
7674       stream->fps_n = 0;
7675       stream->fps_d = 1;
7676     } else {
7677       if (stream->duration == 0 || stream->n_samples < 2) {
7678         stream->fps_n = stream->timescale;
7679         stream->fps_d = 1;
7680         fps_available = FALSE;
7681       } else {
7682         GstClockTime avg_duration;
7683         guint64 duration;
7684         guint32 n_samples;
7685
7686         /* duration and n_samples can be updated for fragmented format
7687          * so, framerate of fragmented format is calculated using data in a moof */
7688         if (qtdemux->fragmented && stream->n_samples_moof > 0
7689             && stream->duration_moof > 0) {
7690           n_samples = stream->n_samples_moof;
7691           duration = stream->duration_moof;
7692         } else {
7693           n_samples = stream->n_samples;
7694           duration = stream->duration;
7695         }
7696
7697         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7698         /* stream->duration is guint64, timescale, n_samples are guint32 */
7699         avg_duration =
7700             gst_util_uint64_scale_round (duration -
7701             stream->first_duration, GST_SECOND,
7702             (guint64) (stream->timescale) * (n_samples - 1));
7703
7704         GST_LOG_OBJECT (qtdemux,
7705             "Calculating avg sample duration based on stream (or moof) duration %"
7706             G_GUINT64_FORMAT
7707             " minus first sample %u, leaving %d samples gives %"
7708             GST_TIME_FORMAT, duration, stream->first_duration,
7709             n_samples - 1, GST_TIME_ARGS (avg_duration));
7710
7711         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7712             &stream->fps_d);
7713
7714         GST_DEBUG_OBJECT (qtdemux,
7715             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7716             stream->timescale, stream->fps_n, stream->fps_d);
7717       }
7718     }
7719
7720     if (stream->caps) {
7721       stream->caps = gst_caps_make_writable (stream->caps);
7722
7723       gst_caps_set_simple (stream->caps,
7724           "width", G_TYPE_INT, stream->width,
7725           "height", G_TYPE_INT, stream->height, NULL);
7726
7727       /* set framerate if calculated framerate is reliable */
7728       if (fps_available) {
7729         gst_caps_set_simple (stream->caps,
7730             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7731       }
7732
7733       /* calculate pixel-aspect-ratio using display width and height */
7734       GST_DEBUG_OBJECT (qtdemux,
7735           "video size %dx%d, target display size %dx%d", stream->width,
7736           stream->height, stream->display_width, stream->display_height);
7737       /* qt file might have pasp atom */
7738       if (stream->par_w > 0 && stream->par_h > 0) {
7739         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7740         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7741             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7742       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7743           stream->width > 0 && stream->height > 0) {
7744         gint n, d;
7745
7746         /* calculate the pixel aspect ratio using the display and pixel w/h */
7747         n = stream->display_width * stream->height;
7748         d = stream->display_height * stream->width;
7749         if (n == d)
7750           n = d = 1;
7751         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7752         stream->par_w = n;
7753         stream->par_h = d;
7754         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7755             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7756       }
7757
7758       if (stream->interlace_mode > 0) {
7759         if (stream->interlace_mode == 1) {
7760           gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_STRING,
7761               "progressive", NULL);
7762         } else if (stream->interlace_mode == 2) {
7763           gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_STRING,
7764               "interleaved", NULL);
7765           if (stream->field_order == 9) {
7766             gst_caps_set_simple (stream->caps, "field-order", G_TYPE_STRING,
7767                 "top-field-first", NULL);
7768           } else if (stream->field_order == 14) {
7769             gst_caps_set_simple (stream->caps, "field-order", G_TYPE_STRING,
7770                 "bottom-field-first", NULL);
7771           }
7772         }
7773       }
7774
7775       /* Create incomplete colorimetry here if needed */
7776       if (stream->colorimetry.range ||
7777           stream->colorimetry.matrix ||
7778           stream->colorimetry.transfer || stream->colorimetry.primaries) {
7779         gchar *colorimetry =
7780             gst_video_colorimetry_to_string (&stream->colorimetry);
7781         gst_caps_set_simple (stream->caps, "colorimetry", G_TYPE_STRING,
7782             colorimetry, NULL);
7783         g_free (colorimetry);
7784       }
7785
7786       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7787         guint par_w = 1, par_h = 1;
7788
7789         if (stream->par_w > 0 && stream->par_h > 0) {
7790           par_w = stream->par_w;
7791           par_h = stream->par_h;
7792         }
7793
7794         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7795                 stream->width, stream->height, par_w, par_h)) {
7796           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7797         }
7798
7799         gst_caps_set_simple (stream->caps,
7800             "multiview-mode", G_TYPE_STRING,
7801             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7802             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7803             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7804       }
7805     }
7806   }
7807
7808   else if (stream->subtype == FOURCC_soun) {
7809     if (stream->caps) {
7810       stream->caps = gst_caps_make_writable (stream->caps);
7811       if (stream->rate > 0)
7812         gst_caps_set_simple (stream->caps,
7813             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7814       if (stream->n_channels > 0)
7815         gst_caps_set_simple (stream->caps,
7816             "channels", G_TYPE_INT, stream->n_channels, NULL);
7817       if (stream->n_channels > 2) {
7818         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7819          * correctly; this is just the minimum we can do - assume
7820          * we don't actually have any channel positions. */
7821         gst_caps_set_simple (stream->caps,
7822             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7823       }
7824     }
7825   }
7826
7827   if (stream->pad) {
7828     GstCaps *prev_caps = NULL;
7829
7830     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7831     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7832     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7833     gst_pad_set_active (stream->pad, TRUE);
7834
7835     gst_pad_use_fixed_caps (stream->pad);
7836
7837     if (stream->protected) {
7838       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7839         GST_ERROR_OBJECT (qtdemux,
7840             "Failed to configure protected stream caps.");
7841         return FALSE;
7842       }
7843     }
7844
7845     if (stream->new_stream) {
7846       gchar *stream_id;
7847       GstEvent *event;
7848       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7849
7850       event =
7851           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7852           0);
7853       if (event) {
7854         gst_event_parse_stream_flags (event, &stream_flags);
7855         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7856           qtdemux->have_group_id = TRUE;
7857         else
7858           qtdemux->have_group_id = FALSE;
7859         gst_event_unref (event);
7860       } else if (!qtdemux->have_group_id) {
7861         qtdemux->have_group_id = TRUE;
7862         qtdemux->group_id = gst_util_group_id_next ();
7863       }
7864
7865       stream->new_stream = FALSE;
7866       stream_id =
7867           gst_pad_create_stream_id_printf (stream->pad,
7868           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7869       event = gst_event_new_stream_start (stream_id);
7870       if (qtdemux->have_group_id)
7871         gst_event_set_group_id (event, qtdemux->group_id);
7872       if (stream->disabled)
7873         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7874       if (stream->sparse) {
7875         stream_flags |= GST_STREAM_FLAG_SPARSE;
7876       } else {
7877         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
7878       }
7879       gst_event_set_stream_flags (event, stream_flags);
7880       gst_pad_push_event (stream->pad, event);
7881       g_free (stream_id);
7882     }
7883
7884     prev_caps = gst_pad_get_current_caps (stream->pad);
7885
7886     if (stream->caps) {
7887       if (!prev_caps || !gst_caps_is_equal_fixed (prev_caps, stream->caps)) {
7888         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7889             stream->caps);
7890         gst_pad_set_caps (stream->pad, stream->caps);
7891       } else {
7892         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7893       }
7894     } else {
7895       GST_WARNING_OBJECT (qtdemux, "stream without caps");
7896     }
7897
7898     if (prev_caps)
7899       gst_caps_unref (prev_caps);
7900     stream->new_caps = FALSE;
7901   }
7902   return TRUE;
7903 }
7904
7905 static gboolean
7906 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7907     QtDemuxStream * stream, GstTagList * list)
7908 {
7909   gboolean ret = TRUE;
7910   /* consistent default for push based mode */
7911   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7912
7913   if (stream->subtype == FOURCC_vide) {
7914     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7915
7916     stream->pad =
7917         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7918     g_free (name);
7919
7920     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7921       gst_object_unref (stream->pad);
7922       stream->pad = NULL;
7923       ret = FALSE;
7924       goto done;
7925     }
7926
7927     qtdemux->n_video_streams++;
7928   } else if (stream->subtype == FOURCC_soun) {
7929     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7930
7931     stream->pad =
7932         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7933     g_free (name);
7934     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7935       gst_object_unref (stream->pad);
7936       stream->pad = NULL;
7937       ret = FALSE;
7938       goto done;
7939     }
7940     qtdemux->n_audio_streams++;
7941   } else if (stream->subtype == FOURCC_strm) {
7942     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7943   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7944       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7945     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7946
7947     stream->pad =
7948         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7949     g_free (name);
7950     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7951       gst_object_unref (stream->pad);
7952       stream->pad = NULL;
7953       ret = FALSE;
7954       goto done;
7955     }
7956     qtdemux->n_sub_streams++;
7957   } else if (stream->caps) {
7958     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7959
7960     stream->pad =
7961         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7962     g_free (name);
7963     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7964       gst_object_unref (stream->pad);
7965       stream->pad = NULL;
7966       ret = FALSE;
7967       goto done;
7968     }
7969     qtdemux->n_video_streams++;
7970   } else {
7971     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7972     goto done;
7973   }
7974
7975   if (stream->pad) {
7976     GList *l;
7977
7978     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7979         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7980     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7981     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7982
7983     if (stream->stream_tags)
7984       gst_tag_list_unref (stream->stream_tags);
7985     stream->stream_tags = list;
7986     list = NULL;
7987     /* global tags go on each pad anyway */
7988     stream->send_global_tags = TRUE;
7989     /* send upstream GST_EVENT_PROTECTION events that were received before
7990        this source pad was created */
7991     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7992       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7993   }
7994 done:
7995   if (list)
7996     gst_tag_list_unref (list);
7997   return ret;
7998 }
7999
8000 /* find next atom with @fourcc starting at @offset */
8001 static GstFlowReturn
8002 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8003     guint64 * length, guint32 fourcc)
8004 {
8005   GstFlowReturn ret;
8006   guint32 lfourcc;
8007   GstBuffer *buf;
8008
8009   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8010       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8011
8012   while (TRUE) {
8013     GstMapInfo map;
8014
8015     buf = NULL;
8016     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8017     if (G_UNLIKELY (ret != GST_FLOW_OK))
8018       goto locate_failed;
8019     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8020       /* likely EOF */
8021       ret = GST_FLOW_EOS;
8022       gst_buffer_unref (buf);
8023       goto locate_failed;
8024     }
8025     gst_buffer_map (buf, &map, GST_MAP_READ);
8026     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8027     gst_buffer_unmap (buf, &map);
8028     gst_buffer_unref (buf);
8029
8030     if (G_UNLIKELY (*length == 0)) {
8031       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8032       ret = GST_FLOW_ERROR;
8033       goto locate_failed;
8034     }
8035
8036     if (lfourcc == fourcc) {
8037       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8038           *offset);
8039       break;
8040     } else {
8041       GST_LOG_OBJECT (qtdemux,
8042           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8043           GST_FOURCC_ARGS (fourcc), *offset);
8044       *offset += *length;
8045     }
8046   }
8047
8048   return GST_FLOW_OK;
8049
8050 locate_failed:
8051   {
8052     /* might simply have had last one */
8053     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8054     return ret;
8055   }
8056 }
8057
8058 /* should only do something in pull mode */
8059 /* call with OBJECT lock */
8060 static GstFlowReturn
8061 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8062 {
8063   guint64 length, offset;
8064   GstBuffer *buf = NULL;
8065   GstFlowReturn ret = GST_FLOW_OK;
8066   GstFlowReturn res = GST_FLOW_OK;
8067   GstMapInfo map;
8068
8069   offset = qtdemux->moof_offset;
8070   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8071
8072   if (!offset) {
8073     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8074     return GST_FLOW_EOS;
8075   }
8076
8077   /* best not do pull etc with lock held */
8078   GST_OBJECT_UNLOCK (qtdemux);
8079
8080   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8081   if (ret != GST_FLOW_OK)
8082     goto flow_failed;
8083
8084   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8085   if (G_UNLIKELY (ret != GST_FLOW_OK))
8086     goto flow_failed;
8087   gst_buffer_map (buf, &map, GST_MAP_READ);
8088   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8089     gst_buffer_unmap (buf, &map);
8090     gst_buffer_unref (buf);
8091     buf = NULL;
8092     goto parse_failed;
8093   }
8094
8095   gst_buffer_unmap (buf, &map);
8096   gst_buffer_unref (buf);
8097   buf = NULL;
8098
8099   offset += length;
8100   /* look for next moof */
8101   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8102   if (G_UNLIKELY (ret != GST_FLOW_OK))
8103     goto flow_failed;
8104
8105 exit:
8106   GST_OBJECT_LOCK (qtdemux);
8107
8108   qtdemux->moof_offset = offset;
8109
8110   return res;
8111
8112 parse_failed:
8113   {
8114     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8115     offset = 0;
8116     res = GST_FLOW_ERROR;
8117     goto exit;
8118   }
8119 flow_failed:
8120   {
8121     /* maybe upstream temporarily flushing */
8122     if (ret != GST_FLOW_FLUSHING) {
8123       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8124       offset = 0;
8125     } else {
8126       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8127       /* resume at current position next time */
8128     }
8129     res = ret;
8130     goto exit;
8131   }
8132 }
8133
8134 /* initialise bytereaders for stbl sub-atoms */
8135 static gboolean
8136 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8137 {
8138   stream->stbl_index = -1;      /* no samples have yet been parsed */
8139   stream->sample_index = -1;
8140
8141   /* time-to-sample atom */
8142   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8143     goto corrupt_file;
8144
8145   /* copy atom data into a new buffer for later use */
8146   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8147
8148   /* skip version + flags */
8149   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8150       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8151     goto corrupt_file;
8152   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8153
8154   /* make sure there's enough data */
8155   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8156     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8157     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8158         stream->n_sample_times);
8159     if (!stream->n_sample_times)
8160       goto corrupt_file;
8161   }
8162
8163   /* sync sample atom */
8164   stream->stps_present = FALSE;
8165   if ((stream->stss_present =
8166           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8167               &stream->stss) ? TRUE : FALSE) == TRUE) {
8168     /* copy atom data into a new buffer for later use */
8169     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8170
8171     /* skip version + flags */
8172     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8173         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8174       goto corrupt_file;
8175
8176     if (stream->n_sample_syncs) {
8177       /* make sure there's enough data */
8178       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8179         goto corrupt_file;
8180     }
8181
8182     /* partial sync sample atom */
8183     if ((stream->stps_present =
8184             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8185                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8186       /* copy atom data into a new buffer for later use */
8187       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8188
8189       /* skip version + flags */
8190       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8191           !gst_byte_reader_get_uint32_be (&stream->stps,
8192               &stream->n_sample_partial_syncs))
8193         goto corrupt_file;
8194
8195       /* if there are no entries, the stss table contains the real
8196        * sync samples */
8197       if (stream->n_sample_partial_syncs) {
8198         /* make sure there's enough data */
8199         if (!qt_atom_parser_has_chunks (&stream->stps,
8200                 stream->n_sample_partial_syncs, 4))
8201           goto corrupt_file;
8202       }
8203     }
8204   }
8205
8206   /* sample size */
8207   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8208     goto no_samples;
8209
8210   /* copy atom data into a new buffer for later use */
8211   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8212
8213   /* skip version + flags */
8214   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8215       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8216     goto corrupt_file;
8217
8218   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8219     goto corrupt_file;
8220
8221   if (!stream->n_samples)
8222     goto no_samples;
8223
8224   /* sample-to-chunk atom */
8225   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8226     goto corrupt_file;
8227
8228   /* copy atom data into a new buffer for later use */
8229   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8230
8231   /* skip version + flags */
8232   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8233       !gst_byte_reader_get_uint32_be (&stream->stsc,
8234           &stream->n_samples_per_chunk))
8235     goto corrupt_file;
8236
8237   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8238       stream->n_samples_per_chunk);
8239
8240   /* make sure there's enough data */
8241   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8242           12))
8243     goto corrupt_file;
8244
8245
8246   /* chunk offset */
8247   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8248     stream->co_size = sizeof (guint32);
8249   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8250           &stream->stco))
8251     stream->co_size = sizeof (guint64);
8252   else
8253     goto corrupt_file;
8254
8255   /* copy atom data into a new buffer for later use */
8256   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8257
8258   /* skip version + flags */
8259   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8260     goto corrupt_file;
8261
8262   /* chunks_are_samples == TRUE means treat chunks as samples */
8263   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
8264   if (stream->chunks_are_samples) {
8265     /* treat chunks as samples */
8266     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8267       goto corrupt_file;
8268   } else {
8269     /* skip number of entries */
8270     if (!gst_byte_reader_skip (&stream->stco, 4))
8271       goto corrupt_file;
8272
8273     /* make sure there are enough data in the stsz atom */
8274     if (!stream->sample_size) {
8275       /* different sizes for each sample */
8276       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8277         goto corrupt_file;
8278     }
8279   }
8280
8281   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8282       stream->n_samples, (guint) sizeof (QtDemuxSample),
8283       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8284
8285   if (stream->n_samples >=
8286       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8287     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8288         "be larger than %uMB (broken file?)", stream->n_samples,
8289         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8290     return FALSE;
8291   }
8292
8293   g_assert (stream->samples == NULL);
8294   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8295   if (!stream->samples) {
8296     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8297         stream->n_samples);
8298     return FALSE;
8299   }
8300
8301   /* composition time-to-sample */
8302   if ((stream->ctts_present =
8303           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8304               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8305     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8306
8307     /* copy atom data into a new buffer for later use */
8308     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8309
8310     /* skip version + flags */
8311     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8312         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8313             &stream->n_composition_times))
8314       goto corrupt_file;
8315
8316     /* make sure there's enough data */
8317     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8318             4 + 4))
8319       goto corrupt_file;
8320
8321     /* This is optional, if missing we iterate the ctts */
8322     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8323       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8324           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8325         g_free ((gpointer) cslg.data);
8326         goto corrupt_file;
8327       }
8328     } else {
8329       gint32 cslg_least = 0;
8330       guint num_entries, pos;
8331       gint i;
8332
8333       pos = gst_byte_reader_get_pos (&stream->ctts);
8334       num_entries = stream->n_composition_times;
8335
8336       stream->cslg_shift = 0;
8337
8338       for (i = 0; i < num_entries; i++) {
8339         gint32 offset;
8340
8341         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8342         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8343
8344         if (offset < cslg_least)
8345           cslg_least = offset;
8346       }
8347
8348       if (cslg_least < 0)
8349         stream->cslg_shift = ABS (cslg_least);
8350       else
8351         stream->cslg_shift = 0;
8352
8353       /* reset the reader so we can generate sample table */
8354       gst_byte_reader_set_pos (&stream->ctts, pos);
8355     }
8356   } else {
8357     /* Ensure the cslg_shift value is consistent so we can use it
8358      * unconditionnally to produce TS and Segment */
8359     stream->cslg_shift = 0;
8360   }
8361
8362   return TRUE;
8363
8364 corrupt_file:
8365   {
8366     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8367         (_("This file is corrupt and cannot be played.")), (NULL));
8368     return FALSE;
8369   }
8370 no_samples:
8371   {
8372     gst_qtdemux_stbl_free (stream);
8373     if (!qtdemux->fragmented) {
8374       /* not quite good */
8375       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8376       return FALSE;
8377     } else {
8378       /* may pick up samples elsewhere */
8379       return TRUE;
8380     }
8381   }
8382 }
8383
8384 /* collect samples from the next sample to be parsed up to sample @n for @stream
8385  * by reading the info from @stbl
8386  *
8387  * This code can be executed from both the streaming thread and the seeking
8388  * thread so it takes the object lock to protect itself
8389  */
8390 static gboolean
8391 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8392 {
8393   gint i, j, k;
8394   QtDemuxSample *samples, *first, *cur, *last;
8395   guint32 n_samples_per_chunk;
8396   guint32 n_samples;
8397
8398   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8399       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8400       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8401
8402   n_samples = stream->n_samples;
8403
8404   if (n >= n_samples)
8405     goto out_of_samples;
8406
8407   GST_OBJECT_LOCK (qtdemux);
8408   if (n <= stream->stbl_index)
8409     goto already_parsed;
8410
8411   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8412
8413   if (!stream->stsz.data) {
8414     /* so we already parsed and passed all the moov samples;
8415      * onto fragmented ones */
8416     g_assert (qtdemux->fragmented);
8417     goto done;
8418   }
8419
8420   /* pointer to the sample table */
8421   samples = stream->samples;
8422
8423   /* starts from -1, moves to the next sample index to parse */
8424   stream->stbl_index++;
8425
8426   /* keep track of the first and last sample to fill */
8427   first = &samples[stream->stbl_index];
8428   last = &samples[n];
8429
8430   if (!stream->chunks_are_samples) {
8431     /* set the sample sizes */
8432     if (stream->sample_size == 0) {
8433       /* different sizes for each sample */
8434       for (cur = first; cur <= last; cur++) {
8435         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8436         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8437             (guint) (cur - samples), cur->size);
8438       }
8439     } else {
8440       /* samples have the same size */
8441       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8442       for (cur = first; cur <= last; cur++)
8443         cur->size = stream->sample_size;
8444     }
8445   }
8446
8447   n_samples_per_chunk = stream->n_samples_per_chunk;
8448   cur = first;
8449
8450   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8451     guint32 last_chunk;
8452
8453     if (stream->stsc_chunk_index >= stream->last_chunk
8454         || stream->stsc_chunk_index < stream->first_chunk) {
8455       stream->first_chunk =
8456           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8457       stream->samples_per_chunk =
8458           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8459       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8460
8461       /* chunk numbers are counted from 1 it seems */
8462       if (G_UNLIKELY (stream->first_chunk == 0))
8463         goto corrupt_file;
8464
8465       --stream->first_chunk;
8466
8467       /* the last chunk of each entry is calculated by taking the first chunk
8468        * of the next entry; except if there is no next, where we fake it with
8469        * INT_MAX */
8470       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8471         stream->last_chunk = G_MAXUINT32;
8472       } else {
8473         stream->last_chunk =
8474             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8475         if (G_UNLIKELY (stream->last_chunk == 0))
8476           goto corrupt_file;
8477
8478         --stream->last_chunk;
8479       }
8480
8481       GST_LOG_OBJECT (qtdemux,
8482           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8483           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8484
8485       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8486         goto corrupt_file;
8487
8488       if (stream->last_chunk != G_MAXUINT32) {
8489         if (!qt_atom_parser_peek_sub (&stream->stco,
8490                 stream->first_chunk * stream->co_size,
8491                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8492                 &stream->co_chunk))
8493           goto corrupt_file;
8494
8495       } else {
8496         stream->co_chunk = stream->stco;
8497         if (!gst_byte_reader_skip (&stream->co_chunk,
8498                 stream->first_chunk * stream->co_size))
8499           goto corrupt_file;
8500       }
8501
8502       stream->stsc_chunk_index = stream->first_chunk;
8503     }
8504
8505     last_chunk = stream->last_chunk;
8506
8507     if (stream->chunks_are_samples) {
8508       cur = &samples[stream->stsc_chunk_index];
8509
8510       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8511         if (j > n) {
8512           /* save state */
8513           stream->stsc_chunk_index = j;
8514           goto done;
8515         }
8516
8517         cur->offset =
8518             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8519             stream->co_size);
8520
8521         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8522             "%" G_GUINT64_FORMAT, j, cur->offset);
8523
8524         if (stream->samples_per_frame > 0 && stream->bytes_per_frame > 0) {
8525           cur->size =
8526               (stream->samples_per_chunk * stream->n_channels) /
8527               stream->samples_per_frame * stream->bytes_per_frame;
8528         } else {
8529           cur->size = stream->samples_per_chunk;
8530         }
8531
8532         GST_DEBUG_OBJECT (qtdemux,
8533             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8534             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8535                     stream->stco_sample_index)), cur->size);
8536
8537         cur->timestamp = stream->stco_sample_index;
8538         cur->duration = stream->samples_per_chunk;
8539         cur->keyframe = TRUE;
8540         cur++;
8541
8542         stream->stco_sample_index += stream->samples_per_chunk;
8543       }
8544       stream->stsc_chunk_index = j;
8545     } else {
8546       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8547         guint32 samples_per_chunk;
8548         guint64 chunk_offset;
8549
8550         if (!stream->stsc_sample_index
8551             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8552                 &stream->chunk_offset))
8553           goto corrupt_file;
8554
8555         samples_per_chunk = stream->samples_per_chunk;
8556         chunk_offset = stream->chunk_offset;
8557
8558         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8559           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8560               G_GUINT64_FORMAT " and size %d",
8561               (guint) (cur - samples), chunk_offset, cur->size);
8562
8563           cur->offset = chunk_offset;
8564           chunk_offset += cur->size;
8565           cur++;
8566
8567           if (G_UNLIKELY (cur > last)) {
8568             /* save state */
8569             stream->stsc_sample_index = k + 1;
8570             stream->chunk_offset = chunk_offset;
8571             stream->stsc_chunk_index = j;
8572             goto done2;
8573           }
8574         }
8575         stream->stsc_sample_index = 0;
8576       }
8577       stream->stsc_chunk_index = j;
8578     }
8579     stream->stsc_index++;
8580   }
8581
8582   if (stream->chunks_are_samples)
8583     goto ctts;
8584 done2:
8585   {
8586     guint32 n_sample_times;
8587
8588     n_sample_times = stream->n_sample_times;
8589     cur = first;
8590
8591     for (i = stream->stts_index; i < n_sample_times; i++) {
8592       guint32 stts_samples;
8593       gint32 stts_duration;
8594       gint64 stts_time;
8595
8596       if (stream->stts_sample_index >= stream->stts_samples
8597           || !stream->stts_sample_index) {
8598
8599         stream->stts_samples =
8600             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8601         stream->stts_duration =
8602             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8603
8604         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8605             i, stream->stts_samples, stream->stts_duration);
8606
8607         stream->stts_sample_index = 0;
8608       }
8609
8610       stts_samples = stream->stts_samples;
8611       stts_duration = stream->stts_duration;
8612       stts_time = stream->stts_time;
8613
8614       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8615         GST_DEBUG_OBJECT (qtdemux,
8616             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8617             (guint) (cur - samples), j,
8618             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8619
8620         cur->timestamp = stts_time;
8621         cur->duration = stts_duration;
8622
8623         /* avoid 32-bit wrap-around,
8624          * but still mind possible 'negative' duration */
8625         stts_time += (gint64) stts_duration;
8626         cur++;
8627
8628         if (G_UNLIKELY (cur > last)) {
8629           /* save values */
8630           stream->stts_time = stts_time;
8631           stream->stts_sample_index = j + 1;
8632           if (stream->stts_sample_index >= stream->stts_samples)
8633             stream->stts_index++;
8634           goto done3;
8635         }
8636       }
8637       stream->stts_sample_index = 0;
8638       stream->stts_time = stts_time;
8639       stream->stts_index++;
8640     }
8641     /* fill up empty timestamps with the last timestamp, this can happen when
8642      * the last samples do not decode and so we don't have timestamps for them.
8643      * We however look at the last timestamp to estimate the track length so we
8644      * need something in here. */
8645     for (; cur < last; cur++) {
8646       GST_DEBUG_OBJECT (qtdemux,
8647           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8648           (guint) (cur - samples),
8649           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8650       cur->timestamp = stream->stts_time;
8651       cur->duration = -1;
8652     }
8653   }
8654 done3:
8655   {
8656     /* sample sync, can be NULL */
8657     if (stream->stss_present == TRUE) {
8658       guint32 n_sample_syncs;
8659
8660       n_sample_syncs = stream->n_sample_syncs;
8661
8662       if (!n_sample_syncs) {
8663         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8664         stream->all_keyframe = TRUE;
8665       } else {
8666         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8667           /* note that the first sample is index 1, not 0 */
8668           guint32 index;
8669
8670           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8671
8672           if (G_LIKELY (index > 0 && index <= n_samples)) {
8673             index -= 1;
8674             samples[index].keyframe = TRUE;
8675             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8676             /* and exit if we have enough samples */
8677             if (G_UNLIKELY (index >= n)) {
8678               i++;
8679               break;
8680             }
8681           }
8682         }
8683         /* save state */
8684         stream->stss_index = i;
8685       }
8686
8687       /* stps marks partial sync frames like open GOP I-Frames */
8688       if (stream->stps_present == TRUE) {
8689         guint32 n_sample_partial_syncs;
8690
8691         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8692
8693         /* if there are no entries, the stss table contains the real
8694          * sync samples */
8695         if (n_sample_partial_syncs) {
8696           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8697             /* note that the first sample is index 1, not 0 */
8698             guint32 index;
8699
8700             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8701
8702             if (G_LIKELY (index > 0 && index <= n_samples)) {
8703               index -= 1;
8704               samples[index].keyframe = TRUE;
8705               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8706               /* and exit if we have enough samples */
8707               if (G_UNLIKELY (index >= n)) {
8708                 i++;
8709                 break;
8710               }
8711             }
8712           }
8713           /* save state */
8714           stream->stps_index = i;
8715         }
8716       }
8717     } else {
8718       /* no stss, all samples are keyframes */
8719       stream->all_keyframe = TRUE;
8720       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8721     }
8722   }
8723
8724 ctts:
8725   /* composition time to sample */
8726   if (stream->ctts_present == TRUE) {
8727     guint32 n_composition_times;
8728     guint32 ctts_count;
8729     gint32 ctts_soffset;
8730
8731     /* Fill in the pts_offsets */
8732     cur = first;
8733     n_composition_times = stream->n_composition_times;
8734
8735     for (i = stream->ctts_index; i < n_composition_times; i++) {
8736       if (stream->ctts_sample_index >= stream->ctts_count
8737           || !stream->ctts_sample_index) {
8738         stream->ctts_count =
8739             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8740         stream->ctts_soffset =
8741             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8742         stream->ctts_sample_index = 0;
8743       }
8744
8745       ctts_count = stream->ctts_count;
8746       ctts_soffset = stream->ctts_soffset;
8747
8748       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8749         cur->pts_offset = ctts_soffset;
8750         cur++;
8751
8752         if (G_UNLIKELY (cur > last)) {
8753           /* save state */
8754           stream->ctts_sample_index = j + 1;
8755           goto done;
8756         }
8757       }
8758       stream->ctts_sample_index = 0;
8759       stream->ctts_index++;
8760     }
8761   }
8762 done:
8763   stream->stbl_index = n;
8764   /* if index has been completely parsed, free data that is no-longer needed */
8765   if (n + 1 == stream->n_samples) {
8766     gst_qtdemux_stbl_free (stream);
8767     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8768     if (qtdemux->pullbased) {
8769       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8770       while (n + 1 == stream->n_samples)
8771         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8772           break;
8773     }
8774   }
8775   GST_OBJECT_UNLOCK (qtdemux);
8776
8777   return TRUE;
8778
8779   /* SUCCESS */
8780 already_parsed:
8781   {
8782     GST_LOG_OBJECT (qtdemux,
8783         "Tried to parse up to sample %u but this sample has already been parsed",
8784         n);
8785     /* if fragmented, there may be more */
8786     if (qtdemux->fragmented && n == stream->stbl_index)
8787       goto done;
8788     GST_OBJECT_UNLOCK (qtdemux);
8789     return TRUE;
8790   }
8791   /* ERRORS */
8792 out_of_samples:
8793   {
8794     GST_LOG_OBJECT (qtdemux,
8795         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8796         stream->n_samples);
8797     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8798         (_("This file is corrupt and cannot be played.")), (NULL));
8799     return FALSE;
8800   }
8801 corrupt_file:
8802   {
8803     GST_OBJECT_UNLOCK (qtdemux);
8804     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8805         (_("This file is corrupt and cannot be played.")), (NULL));
8806     return FALSE;
8807   }
8808 }
8809
8810 /* collect all segment info for @stream.
8811  */
8812 static gboolean
8813 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8814     GNode * trak)
8815 {
8816   GNode *edts;
8817   /* accept edts if they contain gaps at start and there is only
8818    * one media segment */
8819   gboolean allow_pushbased_edts = TRUE;
8820   gint media_segments_count = 0;
8821
8822   /* parse and prepare segment info from the edit list */
8823   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8824   stream->n_segments = 0;
8825   stream->segments = NULL;
8826   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8827     GNode *elst;
8828     gint n_segments;
8829     gint i, count, entry_size;
8830     guint64 time;
8831     GstClockTime stime;
8832     const guint8 *buffer;
8833     guint8 version;
8834     guint32 size;
8835
8836     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8837     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8838       goto done;
8839
8840     buffer = elst->data;
8841
8842     size = QT_UINT32 (buffer);
8843     /* version, flags, n_segments */
8844     if (size < 16) {
8845       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8846       goto done;
8847     }
8848     version = QT_UINT8 (buffer + 8);
8849     entry_size = (version == 1) ? 20 : 12;
8850
8851     n_segments = QT_UINT32 (buffer + 12);
8852
8853     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
8854       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8855       goto done;
8856     }
8857
8858     /* we might allocate a bit too much, at least allocate 1 segment */
8859     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8860
8861     /* segments always start from 0 */
8862     time = 0;
8863     stime = 0;
8864     count = 0;
8865     buffer += 16;
8866     for (i = 0; i < n_segments; i++) {
8867       guint64 duration;
8868       guint64 media_time;
8869       gboolean time_valid = TRUE;
8870       QtDemuxSegment *segment;
8871       guint32 rate_int;
8872       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8873
8874       if (version == 1) {
8875         media_time = QT_UINT64 (buffer + 8);
8876         duration = QT_UINT64 (buffer);
8877         if (media_time == G_MAXUINT64)
8878           time_valid = FALSE;
8879       } else {
8880         media_time = QT_UINT32 (buffer + 4);
8881         duration = QT_UINT32 (buffer);
8882         if (media_time == G_MAXUINT32)
8883           time_valid = FALSE;
8884       }
8885
8886       if (time_valid)
8887         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8888
8889       segment = &stream->segments[count++];
8890
8891       /* time and duration expressed in global timescale */
8892       segment->time = stime;
8893       /* add non scaled values so we don't cause roundoff errors */
8894       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8895         time += duration;
8896         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8897         segment->duration = stime - segment->time;
8898       } else {
8899         /* zero duration does not imply media_start == media_stop
8900          * but, only specify media_start.*/
8901         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8902         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8903             && stime >= media_start) {
8904           segment->duration = stime - media_start;
8905         } else {
8906           segment->duration = GST_CLOCK_TIME_NONE;
8907         }
8908       }
8909       segment->stop_time = stime;
8910
8911       segment->trak_media_start = media_time;
8912       /* media_time expressed in stream timescale */
8913       if (time_valid) {
8914         segment->media_start = media_start;
8915         segment->media_stop = segment->media_start + segment->duration;
8916         media_segments_count++;
8917       } else {
8918         segment->media_start = GST_CLOCK_TIME_NONE;
8919         segment->media_stop = GST_CLOCK_TIME_NONE;
8920       }
8921       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
8922
8923       if (rate_int <= 1) {
8924         /* 0 is not allowed, some programs write 1 instead of the floating point
8925          * value */
8926         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8927             rate_int);
8928         segment->rate = 1;
8929       } else {
8930         segment->rate = rate_int / 65536.0;
8931       }
8932
8933       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8934           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8935           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8936           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8937           i, GST_TIME_ARGS (segment->time),
8938           GST_TIME_ARGS (segment->duration),
8939           GST_TIME_ARGS (segment->media_start), media_time,
8940           GST_TIME_ARGS (segment->media_stop),
8941           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8942           stream->timescale);
8943       if (segment->stop_time > qtdemux->segment.stop) {
8944         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8945             " extends to %" GST_TIME_FORMAT
8946             " past the end of the file duration %" GST_TIME_FORMAT
8947             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8948             GST_TIME_ARGS (qtdemux->segment.stop));
8949         qtdemux->segment.stop = segment->stop_time;
8950       }
8951
8952       buffer += entry_size;
8953     }
8954     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8955     stream->n_segments = count;
8956     if (media_segments_count != 1)
8957       allow_pushbased_edts = FALSE;
8958   }
8959 done:
8960
8961   /* push based does not handle segments, so act accordingly here,
8962    * and warn if applicable */
8963   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8964     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8965     /* remove and use default one below, we stream like it anyway */
8966     g_free (stream->segments);
8967     stream->segments = NULL;
8968     stream->n_segments = 0;
8969   }
8970
8971   /* no segments, create one to play the complete trak */
8972   if (stream->n_segments == 0) {
8973     GstClockTime stream_duration =
8974         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8975
8976     if (stream->segments == NULL)
8977       stream->segments = g_new (QtDemuxSegment, 1);
8978
8979     /* represent unknown our way */
8980     if (stream_duration == 0)
8981       stream_duration = GST_CLOCK_TIME_NONE;
8982
8983     stream->segments[0].time = 0;
8984     stream->segments[0].stop_time = stream_duration;
8985     stream->segments[0].duration = stream_duration;
8986     stream->segments[0].media_start = 0;
8987     stream->segments[0].media_stop = stream_duration;
8988     stream->segments[0].rate = 1.0;
8989     stream->segments[0].trak_media_start = 0;
8990
8991     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8992         GST_TIME_ARGS (stream_duration));
8993     stream->n_segments = 1;
8994     stream->dummy_segment = TRUE;
8995   }
8996   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8997
8998   return TRUE;
8999 }
9000
9001 /*
9002  * Parses the stsd atom of a svq3 trak looking for
9003  * the SMI and gama atoms.
9004  */
9005 static void
9006 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
9007     guint8 ** gamma, GstBuffer ** seqh)
9008 {
9009   guint8 *_gamma = NULL;
9010   GstBuffer *_seqh = NULL;
9011   guint8 *stsd_data = stsd->data;
9012   guint32 length = QT_UINT32 (stsd_data);
9013   guint16 version;
9014
9015   if (length < 32) {
9016     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9017     goto end;
9018   }
9019
9020   stsd_data += 32;
9021   length -= 32;
9022   version = QT_UINT16 (stsd_data);
9023   if (version == 3) {
9024     if (length >= 70) {
9025       length -= 70;
9026       stsd_data += 70;
9027       while (length > 8) {
9028         guint32 fourcc, size;
9029         guint8 *data;
9030         size = QT_UINT32 (stsd_data);
9031         fourcc = QT_FOURCC (stsd_data + 4);
9032         data = stsd_data + 8;
9033
9034         if (size == 0) {
9035           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9036               "svq3 atom parsing");
9037           goto end;
9038         }
9039
9040         switch (fourcc) {
9041           case FOURCC_gama:{
9042             if (size == 12) {
9043               _gamma = data;
9044             } else {
9045               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9046                   " for gama atom, expected 12", size);
9047             }
9048             break;
9049           }
9050           case FOURCC_SMI_:{
9051             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9052               guint32 seqh_size;
9053               if (_seqh != NULL) {
9054                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9055                     " found, ignoring");
9056               } else {
9057                 seqh_size = QT_UINT32 (data + 4);
9058                 if (seqh_size > 0) {
9059                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9060                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9061                 }
9062               }
9063             }
9064             break;
9065           }
9066           default:{
9067             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9068                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9069           }
9070         }
9071
9072         if (size <= length) {
9073           length -= size;
9074           stsd_data += size;
9075         }
9076       }
9077     } else {
9078       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9079     }
9080   } else {
9081     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9082         G_GUINT16_FORMAT, version);
9083     goto end;
9084   }
9085
9086 end:
9087   if (gamma) {
9088     *gamma = _gamma;
9089   }
9090   if (seqh) {
9091     *seqh = _seqh;
9092   } else if (_seqh) {
9093     gst_buffer_unref (_seqh);
9094   }
9095 }
9096
9097 static gchar *
9098 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9099 {
9100   GNode *dinf;
9101   GstByteReader dref;
9102   gchar *uri = NULL;
9103
9104   /*
9105    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9106    * atom that might contain a 'data' atom with the rtsp uri.
9107    * This case was reported in bug #597497, some info about
9108    * the hndl atom can be found in TN1195
9109    */
9110   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9111   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9112
9113   if (dinf) {
9114     guint32 dref_num_entries = 0;
9115     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9116         gst_byte_reader_skip (&dref, 4) &&
9117         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9118       gint i;
9119
9120       /* search dref entries for hndl atom */
9121       for (i = 0; i < dref_num_entries; i++) {
9122         guint32 size = 0, type;
9123         guint8 string_len = 0;
9124         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9125             qt_atom_parser_get_fourcc (&dref, &type)) {
9126           if (type == FOURCC_hndl) {
9127             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9128
9129             /* skip data reference handle bytes and the
9130              * following pascal string and some extra 4
9131              * bytes I have no idea what are */
9132             if (!gst_byte_reader_skip (&dref, 4) ||
9133                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9134                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9135               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9136               break;
9137             }
9138
9139             /* iterate over the atoms to find the data atom */
9140             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9141               guint32 atom_size;
9142               guint32 atom_type;
9143
9144               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9145                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9146                 if (atom_type == FOURCC_data) {
9147                   const guint8 *uri_aux = NULL;
9148
9149                   /* found the data atom that might contain the rtsp uri */
9150                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9151                       "hndl atom, interpreting it as an URI");
9152                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9153                           &uri_aux)) {
9154                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9155                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9156                     else
9157                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9158                           "didn't contain a rtsp address");
9159                   } else {
9160                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9161                         "atom contents");
9162                   }
9163                   break;
9164                 }
9165                 /* skipping to the next entry */
9166                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9167                   break;
9168               } else {
9169                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9170                     "atom header");
9171                 break;
9172               }
9173             }
9174             break;
9175           }
9176           /* skip to the next entry */
9177           if (!gst_byte_reader_skip (&dref, size - 8))
9178             break;
9179         } else {
9180           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9181         }
9182       }
9183       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9184     }
9185   }
9186   return uri;
9187 }
9188
9189 #define AMR_NB_ALL_MODES        0x81ff
9190 #define AMR_WB_ALL_MODES        0x83ff
9191 static guint
9192 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9193 {
9194   /* The 'damr' atom is of the form:
9195    *
9196    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9197    *    32 b       8 b          16 b           8 b                 8 b
9198    *
9199    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9200    * represents the highest mode used in the stream (and thus the maximum
9201    * bitrate), with a couple of special cases as seen below.
9202    */
9203
9204   /* Map of frame type ID -> bitrate */
9205   static const guint nb_bitrates[] = {
9206     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9207   };
9208   static const guint wb_bitrates[] = {
9209     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9210   };
9211   GstMapInfo map;
9212   gsize max_mode;
9213   guint16 mode_set;
9214
9215   gst_buffer_map (buf, &map, GST_MAP_READ);
9216
9217   if (map.size != 0x11) {
9218     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9219     goto bad_data;
9220   }
9221
9222   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9223     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9224         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9225     goto bad_data;
9226   }
9227
9228   mode_set = QT_UINT16 (map.data + 13);
9229
9230   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9231     max_mode = 7 + (wb ? 1 : 0);
9232   else
9233     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9234     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9235
9236   if (max_mode == -1) {
9237     GST_DEBUG ("No mode indication was found (mode set) = %x",
9238         (guint) mode_set);
9239     goto bad_data;
9240   }
9241
9242   gst_buffer_unmap (buf, &map);
9243   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9244
9245 bad_data:
9246   gst_buffer_unmap (buf, &map);
9247   return 0;
9248 }
9249
9250 static gboolean
9251 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9252     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9253 {
9254   /*
9255    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9256    * [0 1 2]
9257    * [3 4 5]
9258    * [6 7 8]
9259    */
9260
9261   if (gst_byte_reader_get_remaining (reader) < 36)
9262     return FALSE;
9263
9264   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9265   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9266   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9267   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9268   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9269   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9270   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9271   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9272   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9273
9274   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9275   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9276       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9277       matrix[2] & 0xFF);
9278   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9279       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9280       matrix[5] & 0xFF);
9281   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9282       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9283       matrix[8] & 0xFF);
9284
9285   return TRUE;
9286 }
9287
9288 static void
9289 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9290     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9291 {
9292
9293 /* [a b c]
9294  * [d e f]
9295  * [g h i]
9296  *
9297  * This macro will only compare value abdegh, it expects cfi to have already
9298  * been checked
9299  */
9300 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9301                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9302
9303   /* only handle the cases where the last column has standard values */
9304   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9305     const gchar *rotation_tag = NULL;
9306
9307     /* no rotation needed */
9308     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9309       /* NOP */
9310     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9311       rotation_tag = "rotate-90";
9312     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9313       rotation_tag = "rotate-180";
9314     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9315       rotation_tag = "rotate-270";
9316     } else {
9317       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9318     }
9319
9320     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9321         rotation_tag);
9322     if (rotation_tag != NULL) {
9323       if (*taglist == NULL)
9324         *taglist = gst_tag_list_new_empty ();
9325       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9326           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9327     }
9328   } else {
9329     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9330   }
9331 }
9332
9333 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9334  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9335  * Common Encryption (cenc), the function will also parse the tenc box (defined
9336  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9337  * (typically an enc[v|a|t|s] sample entry); the function will set
9338  * @original_fmt to the fourcc of the original unencrypted stream format.
9339  * Returns TRUE if successful; FALSE otherwise. */
9340 static gboolean
9341 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9342     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9343 {
9344   GNode *sinf;
9345   GNode *frma;
9346   GNode *schm;
9347   GNode *schi;
9348
9349   g_return_val_if_fail (qtdemux != NULL, FALSE);
9350   g_return_val_if_fail (stream != NULL, FALSE);
9351   g_return_val_if_fail (container != NULL, FALSE);
9352   g_return_val_if_fail (original_fmt != NULL, FALSE);
9353
9354   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9355   if (G_UNLIKELY (!sinf)) {
9356     if (stream->protection_scheme_type == FOURCC_cenc) {
9357       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9358           "mandatory for Common Encryption");
9359       return FALSE;
9360     }
9361     return TRUE;
9362   }
9363
9364   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9365   if (G_UNLIKELY (!frma)) {
9366     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9367     return FALSE;
9368   }
9369
9370   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9371   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9372       GST_FOURCC_ARGS (*original_fmt));
9373
9374   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9375   if (!schm) {
9376     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9377     return FALSE;
9378   }
9379   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9380   stream->protection_scheme_version =
9381       QT_UINT32 ((const guint8 *) schm->data + 16);
9382
9383   GST_DEBUG_OBJECT (qtdemux,
9384       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9385       "protection_scheme_version: %#010x",
9386       GST_FOURCC_ARGS (stream->protection_scheme_type),
9387       stream->protection_scheme_version);
9388
9389   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9390   if (!schi) {
9391     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9392     return FALSE;
9393   }
9394   if (stream->protection_scheme_type == FOURCC_cenc) {
9395     QtDemuxCencSampleSetInfo *info;
9396     GNode *tenc;
9397     const guint8 *tenc_data;
9398     guint32 isEncrypted;
9399     guint8 iv_size;
9400     const guint8 *default_kid;
9401     GstBuffer *kid_buf;
9402
9403     if (G_UNLIKELY (!stream->protection_scheme_info))
9404       stream->protection_scheme_info =
9405           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9406
9407     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9408
9409     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9410     if (!tenc) {
9411       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9412           "which is mandatory for Common Encryption");
9413       return FALSE;
9414     }
9415     tenc_data = (const guint8 *) tenc->data + 12;
9416     isEncrypted = QT_UINT24 (tenc_data);
9417     iv_size = QT_UINT8 (tenc_data + 3);
9418     default_kid = (tenc_data + 4);
9419     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9420     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9421     if (info->default_properties)
9422       gst_structure_free (info->default_properties);
9423     info->default_properties =
9424         gst_structure_new ("application/x-cenc",
9425         "iv_size", G_TYPE_UINT, iv_size,
9426         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9427         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9428     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9429         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9430     gst_buffer_unref (kid_buf);
9431   }
9432   return TRUE;
9433 }
9434
9435 /* parse the traks.
9436  * With each track we associate a new QtDemuxStream that contains all the info
9437  * about the trak.
9438  * traks that do not decode to something (like strm traks) will not have a pad.
9439  */
9440 static gboolean
9441 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9442 {
9443   GstByteReader tkhd;
9444   int offset;
9445   GNode *mdia;
9446   GNode *mdhd;
9447   GNode *hdlr;
9448   GNode *minf;
9449   GNode *stbl;
9450   GNode *stsd;
9451   GNode *mp4a;
9452   GNode *mp4v;
9453   GNode *wave;
9454   GNode *esds;
9455   GNode *pasp;
9456   GNode *colr;
9457   GNode *tref;
9458   GNode *udta;
9459   GNode *svmi;
9460   GNode *fiel;
9461
9462   QtDemuxStream *stream = NULL;
9463   gboolean new_stream = FALSE;
9464   gchar *codec = NULL;
9465   const guint8 *stsd_data;
9466   guint16 lang_code;            /* quicktime lang code or packed iso code */
9467   guint32 version;
9468   guint32 tkhd_flags = 0;
9469   guint8 tkhd_version = 0;
9470   guint32 fourcc;
9471   guint value_size, stsd_len, len;
9472   guint32 track_id;
9473   guint32 dummy;
9474
9475   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9476
9477   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9478       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9479       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9480     goto corrupt_file;
9481
9482   /* pick between 64 or 32 bits */
9483   value_size = tkhd_version == 1 ? 8 : 4;
9484   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9485       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9486     goto corrupt_file;
9487
9488   if (!qtdemux->got_moov) {
9489     if (qtdemux_find_stream (qtdemux, track_id))
9490       goto existing_stream;
9491     stream = _create_stream ();
9492     stream->track_id = track_id;
9493     new_stream = TRUE;
9494   } else {
9495     stream = qtdemux_find_stream (qtdemux, track_id);
9496     if (!stream) {
9497       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9498       goto skip_track;
9499     }
9500
9501     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
9502
9503     /* flush samples data from this track from previous moov */
9504     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9505     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9506   }
9507   /* need defaults for fragments */
9508   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9509
9510   if ((tkhd_flags & 1) == 0)
9511     stream->disabled = TRUE;
9512
9513   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9514       tkhd_version, tkhd_flags, stream->track_id);
9515
9516   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9517     goto corrupt_file;
9518
9519   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9520     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9521     if (qtdemux->major_brand != FOURCC_mjp2 ||
9522         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9523       goto corrupt_file;
9524   }
9525
9526   len = QT_UINT32 ((guint8 *) mdhd->data);
9527   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9528   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9529   if (version == 0x01000000) {
9530     if (len < 38)
9531       goto corrupt_file;
9532     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9533     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9534     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9535   } else {
9536     if (len < 30)
9537       goto corrupt_file;
9538     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9539     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9540     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9541   }
9542
9543   if (lang_code < 0x400) {
9544     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9545   } else if (lang_code == 0x7fff) {
9546     stream->lang_id[0] = 0;     /* unspecified */
9547   } else {
9548     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9549     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9550     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9551     stream->lang_id[3] = 0;
9552   }
9553
9554   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9555       stream->timescale);
9556   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9557       stream->duration);
9558   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9559       lang_code, stream->lang_id);
9560
9561   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9562     goto corrupt_file;
9563
9564   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9565     /* chapters track reference */
9566     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9567     if (chap) {
9568       gsize length = GST_READ_UINT32_BE (chap->data);
9569       if (qtdemux->chapters_track_id)
9570         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9571
9572       if (length >= 12) {
9573         qtdemux->chapters_track_id =
9574             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9575       }
9576     }
9577   }
9578
9579   /* fragmented files may have bogus duration in moov */
9580   if (!qtdemux->fragmented &&
9581       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9582     guint64 tdur1, tdur2;
9583
9584     /* don't overflow */
9585     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9586     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9587
9588     /* HACK:
9589      * some of those trailers, nowadays, have prologue images that are
9590      * themselves video tracks as well. I haven't really found a way to
9591      * identify those yet, except for just looking at their duration. */
9592     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9593       GST_WARNING_OBJECT (qtdemux,
9594           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9595           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9596           "found, assuming preview image or something; skipping track",
9597           stream->duration, stream->timescale, qtdemux->duration,
9598           qtdemux->timescale);
9599       if (new_stream)
9600         gst_qtdemux_stream_free (qtdemux, stream);
9601       return TRUE;
9602     }
9603   }
9604
9605   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9606     goto corrupt_file;
9607
9608   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9609       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9610
9611   len = QT_UINT32 ((guint8 *) hdlr->data);
9612   if (len >= 20)
9613     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9614   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9615       GST_FOURCC_ARGS (stream->subtype));
9616
9617   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9618     goto corrupt_file;
9619
9620   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9621     goto corrupt_file;
9622
9623   /*parse svmi header if existing */
9624   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9625   if (svmi) {
9626     len = QT_UINT32 ((guint8 *) svmi->data);
9627     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9628     if (!version) {
9629       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9630       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9631       guint8 frame_type, frame_layout;
9632
9633       /* MPEG-A stereo video */
9634       if (qtdemux->major_brand == FOURCC_ss02)
9635         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9636
9637       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9638       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9639       switch (frame_type) {
9640         case 0:
9641           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9642           break;
9643         case 1:
9644           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9645           break;
9646         case 2:
9647           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9648           break;
9649         case 3:
9650           /* mode 3 is primary/secondary view sequence, ie
9651            * left/right views in separate tracks. See section 7.2
9652            * of ISO/IEC 23000-11:2009 */
9653           GST_FIXME_OBJECT (qtdemux,
9654               "Implement stereo video in separate streams");
9655       }
9656
9657       if ((frame_layout & 0x1) == 0)
9658         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9659
9660       GST_LOG_OBJECT (qtdemux,
9661           "StereoVideo: composition type: %u, is_left_first: %u",
9662           frame_type, frame_layout);
9663       stream->multiview_mode = mode;
9664       stream->multiview_flags = flags;
9665     }
9666   }
9667
9668   /* parse stsd */
9669   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9670     goto corrupt_file;
9671   stsd_data = (const guint8 *) stsd->data;
9672
9673   /* stsd should at least have one entry */
9674   stsd_len = QT_UINT32 (stsd_data);
9675   if (stsd_len < 24) {
9676     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9677     if (stream->subtype == FOURCC_vivo) {
9678       if (new_stream)
9679         gst_qtdemux_stream_free (qtdemux, stream);
9680       return TRUE;
9681     } else {
9682       goto corrupt_file;
9683     }
9684   }
9685
9686   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9687
9688   /* and that entry should fit within stsd */
9689   len = QT_UINT32 (stsd_data + 16);
9690   if (len > stsd_len + 16)
9691     goto corrupt_file;
9692
9693   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9694   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9695       GST_FOURCC_ARGS (stream->fourcc));
9696   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9697
9698   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9699     goto error_encrypted;
9700
9701   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9702     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9703     stream->protected = TRUE;
9704     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9705       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9706   }
9707
9708   if (stream->subtype == FOURCC_vide) {
9709     guint32 w = 0, h = 0;
9710     gboolean gray;
9711     gint depth, palette_size, palette_count;
9712     guint32 matrix[9];
9713     guint32 *palette_data = NULL;
9714
9715     stream->sampled = TRUE;
9716
9717     /* version 1 uses some 64-bit ints */
9718     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9719       goto corrupt_file;
9720
9721     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9722       goto corrupt_file;
9723
9724     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9725         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9726       goto corrupt_file;
9727
9728     stream->display_width = w >> 16;
9729     stream->display_height = h >> 16;
9730
9731     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9732         &stream->stream_tags);
9733
9734     offset = 16;
9735     if (len < 86)
9736       goto corrupt_file;
9737
9738     stream->width = QT_UINT16 (stsd_data + offset + 32);
9739     stream->height = QT_UINT16 (stsd_data + offset + 34);
9740     stream->fps_n = 0;          /* this is filled in later */
9741     stream->fps_d = 0;          /* this is filled in later */
9742     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9743     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9744
9745     /* if color_table_id is 0, ctab atom must follow; however some files
9746      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9747      * if color table is not present we'll correct the value */
9748     if (stream->color_table_id == 0 &&
9749         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9750       stream->color_table_id = -1;
9751     }
9752
9753     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9754         stream->width, stream->height, stream->bits_per_sample,
9755         stream->color_table_id);
9756
9757     depth = stream->bits_per_sample;
9758
9759     /* more than 32 bits means grayscale */
9760     gray = (depth > 32);
9761     /* low 32 bits specify the depth  */
9762     depth &= 0x1F;
9763
9764     /* different number of palette entries is determined by depth. */
9765     palette_count = 0;
9766     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9767       palette_count = (1 << depth);
9768     palette_size = palette_count * 4;
9769
9770     if (stream->color_table_id) {
9771       switch (palette_count) {
9772         case 0:
9773           break;
9774         case 2:
9775           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9776           break;
9777         case 4:
9778           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9779           break;
9780         case 16:
9781           if (gray)
9782             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9783           else
9784             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9785           break;
9786         case 256:
9787           if (gray)
9788             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9789           else
9790             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9791           break;
9792         default:
9793           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9794               (_("The video in this file might not play correctly.")),
9795               ("unsupported palette depth %d", depth));
9796           break;
9797       }
9798     } else {
9799       gint i, j, start, end;
9800
9801       if (len < 94)
9802         goto corrupt_file;
9803
9804       /* read table */
9805       start = QT_UINT32 (stsd_data + offset + 86);
9806       palette_count = QT_UINT16 (stsd_data + offset + 90);
9807       end = QT_UINT16 (stsd_data + offset + 92);
9808
9809       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9810           start, end, palette_count);
9811
9812       if (end > 255)
9813         end = 255;
9814       if (start > end)
9815         start = end;
9816
9817       if (len < 94 + (end - start) * 8)
9818         goto corrupt_file;
9819
9820       /* palette is always the same size */
9821       palette_data = g_malloc0 (256 * 4);
9822       palette_size = 256 * 4;
9823
9824       for (j = 0, i = start; i <= end; j++, i++) {
9825         guint32 a, r, g, b;
9826
9827         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9828         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9829         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9830         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9831
9832         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9833             (g & 0xff00) | (b >> 8);
9834       }
9835     }
9836
9837     if (stream->caps)
9838       gst_caps_unref (stream->caps);
9839
9840     stream->caps =
9841         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9842     if (G_UNLIKELY (!stream->caps)) {
9843       g_free (palette_data);
9844       goto unknown_stream;
9845     }
9846
9847     if (codec) {
9848       gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
9849           GST_TAG_VIDEO_CODEC, codec, NULL);
9850       g_free (codec);
9851       codec = NULL;
9852     }
9853
9854
9855     if (palette_data) {
9856       GstStructure *s;
9857
9858       if (stream->rgb8_palette)
9859         gst_memory_unref (stream->rgb8_palette);
9860       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9861           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9862
9863       s = gst_caps_get_structure (stream->caps, 0);
9864
9865       /* non-raw video has a palette_data property. raw video has the palette as
9866        * an extra plane that we append to the output buffers before we push
9867        * them*/
9868       if (!gst_structure_has_name (s, "video/x-raw")) {
9869         GstBuffer *palette;
9870
9871         palette = gst_buffer_new ();
9872         gst_buffer_append_memory (palette, stream->rgb8_palette);
9873         stream->rgb8_palette = NULL;
9874
9875         gst_caps_set_simple (stream->caps, "palette_data",
9876             GST_TYPE_BUFFER, palette, NULL);
9877         gst_buffer_unref (palette);
9878       }
9879     } else if (palette_count != 0) {
9880       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9881           (NULL), ("Unsupported palette depth %d", depth));
9882     }
9883
9884     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9885         QT_UINT16 (stsd_data + offset + 48));
9886
9887     esds = NULL;
9888     pasp = NULL;
9889     colr = NULL;
9890     fiel = NULL;
9891     /* pick 'the' stsd child */
9892     mp4v = qtdemux_tree_get_child_by_index (stsd, 0);
9893     if (!stream->protected) {
9894       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
9895         mp4v = NULL;
9896       }
9897     } else {
9898       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
9899         mp4v = NULL;
9900       }
9901     }
9902
9903     if (mp4v) {
9904       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9905       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9906       colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
9907       fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
9908     }
9909
9910     if (pasp) {
9911       const guint8 *pasp_data = (const guint8 *) pasp->data;
9912       gint len = QT_UINT32 (pasp_data);
9913
9914       if (len == 16) {
9915         stream->par_w = QT_UINT32 (pasp_data + 8);
9916         stream->par_h = QT_UINT32 (pasp_data + 12);
9917       } else {
9918         stream->par_w = 0;
9919         stream->par_h = 0;
9920       }
9921     } else {
9922       stream->par_w = 0;
9923       stream->par_h = 0;
9924     }
9925
9926     if (fiel) {
9927       const guint8 *fiel_data = (const guint8 *) fiel->data;
9928       gint len = QT_UINT32 (fiel_data);
9929
9930       if (len == 10) {
9931         stream->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
9932         stream->field_order = GST_READ_UINT8 (fiel_data + 9);
9933       }
9934     }
9935
9936     if (colr) {
9937       const guint8 *colr_data = (const guint8 *) colr->data;
9938       gint len = QT_UINT32 (colr_data);
9939
9940       if (len == 19 || len == 18) {
9941         guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
9942
9943         if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
9944           guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
9945           guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
9946           guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
9947           gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
9948
9949           switch (primaries) {
9950             case 1:
9951               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
9952               break;
9953             case 5:
9954               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
9955               break;
9956             case 6:
9957               stream->colorimetry.primaries =
9958                   GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
9959               break;
9960             case 9:
9961               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT2020;
9962               break;
9963             default:
9964               break;
9965           }
9966
9967           switch (transfer_function) {
9968             case 1:
9969               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
9970               break;
9971             case 7:
9972               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE240M;
9973               break;
9974             default:
9975               break;
9976           }
9977
9978           switch (matrix) {
9979             case 1:
9980               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
9981               break;
9982             case 6:
9983               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
9984               break;
9985             case 7:
9986               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_SMPTE240M;
9987               break;
9988             case 9:
9989               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT2020;
9990               break;
9991             default:
9992               break;
9993           }
9994
9995           stream->colorimetry.range =
9996               full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
9997               GST_VIDEO_COLOR_RANGE_16_235;
9998         } else {
9999           GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10000         }
10001       } else {
10002         GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10003       }
10004     }
10005
10006     if (esds) {
10007       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->stream_tags);
10008     } else {
10009       switch (fourcc) {
10010         case FOURCC_H264:
10011         case FOURCC_avc1:
10012         case FOURCC_avc3:
10013         {
10014           gint len = QT_UINT32 (stsd_data) - 0x66;
10015           const guint8 *avc_data = stsd_data + 0x66;
10016
10017           /* find avcC */
10018           while (len >= 0x8) {
10019             gint size;
10020
10021             if (QT_UINT32 (avc_data) <= len)
10022               size = QT_UINT32 (avc_data) - 0x8;
10023             else
10024               size = len - 0x8;
10025
10026             if (size < 1)
10027               /* No real data, so break out */
10028               break;
10029
10030             switch (QT_FOURCC (avc_data + 0x4)) {
10031               case FOURCC_avcC:
10032               {
10033                 /* parse, if found */
10034                 GstBuffer *buf;
10035
10036                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10037
10038                 /* First 4 bytes are the length of the atom, the next 4 bytes
10039                  * are the fourcc, the next 1 byte is the version, and the
10040                  * subsequent bytes are profile_tier_level structure like data. */
10041                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
10042                     avc_data + 8 + 1, size - 1);
10043                 buf = gst_buffer_new_and_alloc (size);
10044                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10045                 gst_caps_set_simple (stream->caps,
10046                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10047                 gst_buffer_unref (buf);
10048
10049                 break;
10050               }
10051               case FOURCC_strf:
10052               {
10053                 GstBuffer *buf;
10054
10055                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10056
10057                 /* First 4 bytes are the length of the atom, the next 4 bytes
10058                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10059                  * next 1 byte is the version, and the
10060                  * subsequent bytes are sequence parameter set like data. */
10061
10062                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
10063                 if (size > 1) {
10064                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
10065                       avc_data + 8 + 40 + 1, size - 1);
10066
10067                   buf = gst_buffer_new_and_alloc (size);
10068                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10069                   gst_caps_set_simple (stream->caps,
10070                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10071                   gst_buffer_unref (buf);
10072                 }
10073                 break;
10074               }
10075               case FOURCC_btrt:
10076               {
10077                 guint avg_bitrate, max_bitrate;
10078
10079                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10080                 if (size < 12)
10081                   break;
10082
10083                 max_bitrate = QT_UINT32 (avc_data + 0xc);
10084                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
10085
10086                 if (!max_bitrate && !avg_bitrate)
10087                   break;
10088
10089                 /* Some muxers seem to swap the average and maximum bitrates
10090                  * (I'm looking at you, YouTube), so we swap for sanity. */
10091                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10092                   guint temp = avg_bitrate;
10093
10094                   avg_bitrate = max_bitrate;
10095                   max_bitrate = temp;
10096                 }
10097
10098                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10099                   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10100                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
10101                 }
10102                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10103                   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10104                       GST_TAG_BITRATE, avg_bitrate, NULL);
10105                 }
10106
10107                 break;
10108               }
10109
10110               default:
10111                 break;
10112             }
10113
10114             len -= size + 8;
10115             avc_data += size + 8;
10116           }
10117
10118           break;
10119         }
10120         case FOURCC_H265:
10121         case FOURCC_hvc1:
10122         case FOURCC_hev1:
10123         {
10124           gint len = QT_UINT32 (stsd_data) - 0x66;
10125           const guint8 *hevc_data = stsd_data + 0x66;
10126
10127           /* find hevc */
10128           while (len >= 0x8) {
10129             gint size;
10130
10131             if (QT_UINT32 (hevc_data) <= len)
10132               size = QT_UINT32 (hevc_data) - 0x8;
10133             else
10134               size = len - 0x8;
10135
10136             if (size < 1)
10137               /* No real data, so break out */
10138               break;
10139
10140             switch (QT_FOURCC (hevc_data + 0x4)) {
10141               case FOURCC_hvcC:
10142               {
10143                 /* parse, if found */
10144                 GstBuffer *buf;
10145
10146                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10147
10148                 /* First 4 bytes are the length of the atom, the next 4 bytes
10149                  * are the fourcc, the next 1 byte is the version, and the
10150                  * subsequent bytes are sequence parameter set like data. */
10151                 gst_codec_utils_h265_caps_set_level_tier_and_profile
10152                     (stream->caps, hevc_data + 8 + 1, size - 1);
10153
10154                 buf = gst_buffer_new_and_alloc (size);
10155                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10156                 gst_caps_set_simple (stream->caps,
10157                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10158                 gst_buffer_unref (buf);
10159                 break;
10160               }
10161               default:
10162                 break;
10163             }
10164             len -= size + 8;
10165             hevc_data += size + 8;
10166           }
10167           break;
10168         }
10169         case FOURCC_mp4v:
10170         case FOURCC_MP4V:
10171         case FOURCC_fmp4:
10172         case FOURCC_FMP4:
10173         case FOURCC_xvid:
10174         case FOURCC_XVID:
10175         {
10176           GNode *glbl;
10177
10178           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10179               GST_FOURCC_ARGS (fourcc));
10180
10181           /* codec data might be in glbl extension atom */
10182           glbl = mp4v ?
10183               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10184           if (glbl) {
10185             guint8 *data;
10186             GstBuffer *buf;
10187             gint len;
10188
10189             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10190             data = glbl->data;
10191             len = QT_UINT32 (data);
10192             if (len > 0x8) {
10193               len -= 0x8;
10194               buf = gst_buffer_new_and_alloc (len);
10195               gst_buffer_fill (buf, 0, data + 8, len);
10196               gst_caps_set_simple (stream->caps,
10197                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10198               gst_buffer_unref (buf);
10199             }
10200           }
10201           break;
10202         }
10203         case FOURCC_mjp2:
10204         {
10205           /* see annex I of the jpeg2000 spec */
10206           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10207           const guint8 *data;
10208           const gchar *colorspace = NULL;
10209           gint ncomp = 0;
10210           guint32 ncomp_map = 0;
10211           gint32 *comp_map = NULL;
10212           guint32 nchan_def = 0;
10213           gint32 *chan_def = NULL;
10214
10215           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10216           /* some required atoms */
10217           mjp2 = qtdemux_tree_get_child_by_index (stsd, 0);
10218           if (!mjp2)
10219             break;
10220           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10221           if (!jp2h)
10222             break;
10223
10224           /* number of components; redundant with info in codestream, but useful
10225              to a muxer */
10226           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10227           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10228             break;
10229           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10230
10231           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10232           if (!colr)
10233             break;
10234           GST_DEBUG_OBJECT (qtdemux, "found colr");
10235           /* extract colour space info */
10236           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10237             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10238               case 16:
10239                 colorspace = "sRGB";
10240                 break;
10241               case 17:
10242                 colorspace = "GRAY";
10243                 break;
10244               case 18:
10245                 colorspace = "sYUV";
10246                 break;
10247               default:
10248                 colorspace = NULL;
10249                 break;
10250             }
10251           }
10252           if (!colorspace)
10253             /* colr is required, and only values 16, 17, and 18 are specified,
10254                so error if we have no colorspace */
10255             break;
10256
10257           /* extract component mapping */
10258           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10259           if (cmap) {
10260             guint32 cmap_len = 0;
10261             int i;
10262             cmap_len = QT_UINT32 (cmap->data);
10263             if (cmap_len >= 8) {
10264               /* normal box, subtract off header */
10265               cmap_len -= 8;
10266               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10267               if (cmap_len % 4 == 0) {
10268                 ncomp_map = (cmap_len / 4);
10269                 comp_map = g_new0 (gint32, ncomp_map);
10270                 for (i = 0; i < ncomp_map; i++) {
10271                   guint16 cmp;
10272                   guint8 mtyp, pcol;
10273                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10274                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10275                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10276                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10277                 }
10278               }
10279             }
10280           }
10281           /* extract channel definitions */
10282           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10283           if (cdef) {
10284             guint32 cdef_len = 0;
10285             int i;
10286             cdef_len = QT_UINT32 (cdef->data);
10287             if (cdef_len >= 10) {
10288               /* normal box, subtract off header and len */
10289               cdef_len -= 10;
10290               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10291               if (cdef_len % 6 == 0) {
10292                 nchan_def = (cdef_len / 6);
10293                 chan_def = g_new0 (gint32, nchan_def);
10294                 for (i = 0; i < nchan_def; i++)
10295                   chan_def[i] = -1;
10296                 for (i = 0; i < nchan_def; i++) {
10297                   guint16 cn, typ, asoc;
10298                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10299                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10300                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10301                   if (cn < nchan_def) {
10302                     switch (typ) {
10303                       case 0:
10304                         chan_def[cn] = asoc;
10305                         break;
10306                       case 1:
10307                         chan_def[cn] = 0;       /* alpha */
10308                         break;
10309                       default:
10310                         chan_def[cn] = -typ;
10311                     }
10312                   }
10313                 }
10314               }
10315             }
10316           }
10317
10318           gst_caps_set_simple (stream->caps,
10319               "num-components", G_TYPE_INT, ncomp, NULL);
10320           gst_caps_set_simple (stream->caps,
10321               "colorspace", G_TYPE_STRING, colorspace, NULL);
10322
10323           if (comp_map) {
10324             GValue arr = { 0, };
10325             GValue elt = { 0, };
10326             int i;
10327             g_value_init (&arr, GST_TYPE_ARRAY);
10328             g_value_init (&elt, G_TYPE_INT);
10329             for (i = 0; i < ncomp_map; i++) {
10330               g_value_set_int (&elt, comp_map[i]);
10331               gst_value_array_append_value (&arr, &elt);
10332             }
10333             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10334                 "component-map", &arr);
10335             g_value_unset (&elt);
10336             g_value_unset (&arr);
10337             g_free (comp_map);
10338           }
10339
10340           if (chan_def) {
10341             GValue arr = { 0, };
10342             GValue elt = { 0, };
10343             int i;
10344             g_value_init (&arr, GST_TYPE_ARRAY);
10345             g_value_init (&elt, G_TYPE_INT);
10346             for (i = 0; i < nchan_def; i++) {
10347               g_value_set_int (&elt, chan_def[i]);
10348               gst_value_array_append_value (&arr, &elt);
10349             }
10350             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10351                 "channel-definitions", &arr);
10352             g_value_unset (&elt);
10353             g_value_unset (&arr);
10354             g_free (chan_def);
10355           }
10356
10357           /* some optional atoms */
10358           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10359           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10360
10361           /* indicate possible fields in caps */
10362           if (field) {
10363             data = (guint8 *) field->data + 8;
10364             if (*data != 1)
10365               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
10366                   (gint) * data, NULL);
10367           }
10368           /* add codec_data if provided */
10369           if (prefix) {
10370             GstBuffer *buf;
10371             gint len;
10372
10373             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10374             data = prefix->data;
10375             len = QT_UINT32 (data);
10376             if (len > 0x8) {
10377               len -= 0x8;
10378               buf = gst_buffer_new_and_alloc (len);
10379               gst_buffer_fill (buf, 0, data + 8, len);
10380               gst_caps_set_simple (stream->caps,
10381                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10382               gst_buffer_unref (buf);
10383             }
10384           }
10385           break;
10386         }
10387         case FOURCC_jpeg:
10388         {
10389           /* https://developer.apple.com/standards/qtff-2001.pdf,
10390            * page 92, "Video Sample Description", under table 3.1 */
10391           GstByteReader br;
10392
10393           const gint compressor_offset = 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10394           const gint min_size = compressor_offset + 32 + 2 + 2;
10395           GNode *jpeg;
10396           guint32 len;
10397           guint16 color_table_id = 0;
10398           gboolean ok;
10399
10400           GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10401
10402           /* recover information on interlaced/progressive */
10403           jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10404           if (!jpeg)
10405             break;
10406
10407           len = QT_UINT32 (jpeg->data);
10408           GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10409               min_size);
10410           if (len >= min_size) {
10411             gst_byte_reader_init (&br, jpeg->data, len);
10412
10413             gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10414             gst_byte_reader_get_uint16_le (&br, &color_table_id);
10415             if (color_table_id != 0) {
10416               /* the spec says there can be concatenated chunks in the data, and we want
10417                * to find one called field. Walk through them. */
10418               gint offset = min_size;
10419               while (offset + 8 < len) {
10420                 guint32 size = 0, tag;
10421                 ok = gst_byte_reader_get_uint32_le (&br, &size);
10422                 ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10423                 if (!ok || size < 8) {
10424                   GST_WARNING_OBJECT (qtdemux,
10425                       "Failed to walk optional chunk list");
10426                   break;
10427                 }
10428                 GST_DEBUG_OBJECT (qtdemux,
10429                     "Found optional %4.4s chunk, size %u", (const char *) &tag,
10430                     size);
10431                 if (tag == FOURCC_fiel) {
10432                   guint8 n_fields, ordering;
10433                   gst_byte_reader_get_uint8 (&br, &n_fields);
10434                   gst_byte_reader_get_uint8 (&br, &ordering);
10435                   if (n_fields == 1 || n_fields == 2) {
10436                     GST_DEBUG_OBJECT (qtdemux,
10437                         "Found fiel tag with %u fields, ordering %u", n_fields,
10438                         ordering);
10439                     if (n_fields == 2)
10440                       gst_caps_set_simple (stream->caps, "interlace-mode",
10441                           G_TYPE_STRING, "interleaved", NULL);
10442                   } else {
10443                     GST_WARNING_OBJECT (qtdemux,
10444                         "Found fiel tag with invalid fields (%u)", n_fields);
10445                   }
10446                 }
10447                 offset += size;
10448               }
10449             } else {
10450               GST_DEBUG_OBJECT (qtdemux,
10451                   "Color table ID is 0, not trying to get interlacedness");
10452             }
10453           } else {
10454             GST_WARNING_OBJECT (qtdemux,
10455                 "Length of jpeg chunk is too small, not trying to get interlacedness");
10456           }
10457
10458           break;
10459         }
10460         case FOURCC_SVQ3:
10461         case FOURCC_VP31:
10462         {
10463           GstBuffer *buf;
10464           GstBuffer *seqh = NULL;
10465           guint8 *gamma_data = NULL;
10466           gint len = QT_UINT32 (stsd_data);
10467
10468           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
10469           if (gamma_data) {
10470             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
10471                 QT_FP32 (gamma_data), NULL);
10472           }
10473           if (seqh) {
10474             /* sorry for the bad name, but we don't know what this is, other
10475              * than its own fourcc */
10476             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
10477                 NULL);
10478             gst_buffer_unref (seqh);
10479           }
10480
10481           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10482           buf = gst_buffer_new_and_alloc (len);
10483           gst_buffer_fill (buf, 0, stsd_data, len);
10484           gst_caps_set_simple (stream->caps,
10485               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10486           gst_buffer_unref (buf);
10487           break;
10488         }
10489         case FOURCC_rle_:
10490         case FOURCC_WRLE:
10491         {
10492           gst_caps_set_simple (stream->caps,
10493               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
10494           break;
10495         }
10496         case FOURCC_XiTh:
10497         {
10498           GNode *xith, *xdxt;
10499
10500           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10501           xith = qtdemux_tree_get_child_by_index (stsd, 0);
10502           if (!xith)
10503             break;
10504
10505           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10506           if (!xdxt)
10507             break;
10508
10509           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10510           /* collect the headers and store them in a stream list so that we can
10511            * send them out first */
10512           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10513           break;
10514         }
10515         case FOURCC_ovc1:
10516         {
10517           GNode *ovc1;
10518           guint8 *ovc1_data;
10519           guint ovc1_len;
10520           GstBuffer *buf;
10521
10522           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10523           ovc1 = qtdemux_tree_get_child_by_index (stsd, 0);
10524           if (!ovc1)
10525             break;
10526           ovc1_data = ovc1->data;
10527           ovc1_len = QT_UINT32 (ovc1_data);
10528           if (ovc1_len <= 198) {
10529             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10530             break;
10531           }
10532           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10533           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10534           gst_caps_set_simple (stream->caps,
10535               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10536           gst_buffer_unref (buf);
10537           break;
10538         }
10539         case FOURCC_vc_1:
10540         {
10541           gint len = QT_UINT32 (stsd_data) - 0x66;
10542           const guint8 *vc1_data = stsd_data + 0x66;
10543
10544           /* find dvc1 */
10545           while (len >= 8) {
10546             gint size;
10547
10548             if (QT_UINT32 (vc1_data) <= len)
10549               size = QT_UINT32 (vc1_data) - 8;
10550             else
10551               size = len - 8;
10552
10553             if (size < 1)
10554               /* No real data, so break out */
10555               break;
10556
10557             switch (QT_FOURCC (vc1_data + 0x4)) {
10558               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10559               {
10560                 GstBuffer *buf;
10561
10562                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10563                 buf = gst_buffer_new_and_alloc (size);
10564                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
10565                 gst_caps_set_simple (stream->caps,
10566                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10567                 gst_buffer_unref (buf);
10568                 break;
10569               }
10570               default:
10571                 break;
10572             }
10573             len -= size + 8;
10574             vc1_data += size + 8;
10575           }
10576           break;
10577         }
10578         default:
10579           break;
10580       }
10581     }
10582
10583     GST_INFO_OBJECT (qtdemux,
10584         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10585         GST_FOURCC_ARGS (fourcc), stream->caps);
10586
10587   } else if (stream->subtype == FOURCC_soun) {
10588     int version, samplesize;
10589     guint16 compression_id;
10590     gboolean amrwb = FALSE;
10591
10592     offset = 32;
10593     /* sample description entry (16) + sound sample description v0 (20) */
10594     if (len < 36)
10595       goto corrupt_file;
10596
10597     version = QT_UINT32 (stsd_data + offset);
10598     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10599     samplesize = QT_UINT16 (stsd_data + offset + 10);
10600     compression_id = QT_UINT16 (stsd_data + offset + 12);
10601     stream->rate = QT_FP32 (stsd_data + offset + 16);
10602
10603     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10604     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10605         QT_UINT32 (stsd_data + offset + 4));
10606     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10607     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10608     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10609     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10610         QT_UINT16 (stsd_data + offset + 14));
10611     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10612
10613     if (compression_id == 0xfffe)
10614       stream->sampled = TRUE;
10615
10616     /* first assume uncompressed audio */
10617     stream->bytes_per_sample = samplesize / 8;
10618     stream->samples_per_frame = stream->n_channels;
10619     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10620     stream->samples_per_packet = stream->samples_per_frame;
10621     stream->bytes_per_packet = stream->bytes_per_sample;
10622
10623     offset = 52;
10624     switch (fourcc) {
10625         /* Yes, these have to be hard-coded */
10626       case FOURCC_MAC6:
10627       {
10628         stream->samples_per_packet = 6;
10629         stream->bytes_per_packet = 1;
10630         stream->bytes_per_frame = 1 * stream->n_channels;
10631         stream->bytes_per_sample = 1;
10632         stream->samples_per_frame = 6 * stream->n_channels;
10633         break;
10634       }
10635       case FOURCC_MAC3:
10636       {
10637         stream->samples_per_packet = 3;
10638         stream->bytes_per_packet = 1;
10639         stream->bytes_per_frame = 1 * stream->n_channels;
10640         stream->bytes_per_sample = 1;
10641         stream->samples_per_frame = 3 * stream->n_channels;
10642         break;
10643       }
10644       case FOURCC_ima4:
10645       {
10646         stream->samples_per_packet = 64;
10647         stream->bytes_per_packet = 34;
10648         stream->bytes_per_frame = 34 * stream->n_channels;
10649         stream->bytes_per_sample = 2;
10650         stream->samples_per_frame = 64 * stream->n_channels;
10651         break;
10652       }
10653       case FOURCC_ulaw:
10654       case FOURCC_alaw:
10655       {
10656         stream->samples_per_packet = 1;
10657         stream->bytes_per_packet = 1;
10658         stream->bytes_per_frame = 1 * stream->n_channels;
10659         stream->bytes_per_sample = 1;
10660         stream->samples_per_frame = 1 * stream->n_channels;
10661         break;
10662       }
10663       case FOURCC_agsm:
10664       {
10665         stream->samples_per_packet = 160;
10666         stream->bytes_per_packet = 33;
10667         stream->bytes_per_frame = 33 * stream->n_channels;
10668         stream->bytes_per_sample = 2;
10669         stream->samples_per_frame = 160 * stream->n_channels;
10670         break;
10671       }
10672       default:
10673         break;
10674     }
10675
10676     if (version == 0x00010000) {
10677       /* sample description entry (16) + sound sample description v1 (20+16) */
10678       if (len < 52)
10679         goto corrupt_file;
10680
10681       switch (fourcc) {
10682         case FOURCC_twos:
10683         case FOURCC_sowt:
10684         case FOURCC_raw_:
10685           break;
10686         default:
10687         {
10688           /* only parse extra decoding config for non-pcm audio */
10689           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10690           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10691           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10692           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10693
10694           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10695               stream->samples_per_packet);
10696           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10697               stream->bytes_per_packet);
10698           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10699               stream->bytes_per_frame);
10700           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10701               stream->bytes_per_sample);
10702
10703           if (!stream->sampled && stream->bytes_per_packet) {
10704             stream->samples_per_frame = (stream->bytes_per_frame /
10705                 stream->bytes_per_packet) * stream->samples_per_packet;
10706             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10707                 stream->samples_per_frame);
10708           }
10709           break;
10710         }
10711       }
10712     } else if (version == 0x00020000) {
10713       union
10714       {
10715         gdouble fp;
10716         guint64 val;
10717       } qtfp;
10718
10719       /* sample description entry (16) + sound sample description v2 (56) */
10720       if (len < 72)
10721         goto corrupt_file;
10722
10723       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10724       stream->rate = qtfp.fp;
10725       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10726
10727       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10728       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10729       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10730       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10731           QT_UINT32 (stsd_data + offset + 20));
10732       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10733           QT_UINT32 (stsd_data + offset + 24));
10734       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10735           QT_UINT32 (stsd_data + offset + 28));
10736       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10737           QT_UINT32 (stsd_data + offset + 32));
10738     } else if (version != 0x00000) {
10739       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10740     }
10741
10742     if (stream->caps)
10743       gst_caps_unref (stream->caps);
10744
10745     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10746         stsd_data + 32, len - 16, &codec);
10747
10748     switch (fourcc) {
10749       case FOURCC_in24:
10750       {
10751         GNode *enda;
10752         GNode *in24;
10753
10754         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10755
10756         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10757         if (!enda) {
10758           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10759           if (wave)
10760             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10761         }
10762         if (enda) {
10763           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10764           gst_caps_set_simple (stream->caps,
10765               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10766         }
10767         break;
10768       }
10769       case FOURCC_owma:
10770       {
10771         const guint8 *owma_data;
10772         const gchar *codec_name = NULL;
10773         guint owma_len;
10774         GstBuffer *buf;
10775         gint version = 1;
10776         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10777         /* FIXME this should also be gst_riff_strf_auds,
10778          * but the latter one is actually missing bits-per-sample :( */
10779         typedef struct
10780         {
10781           gint16 wFormatTag;
10782           gint16 nChannels;
10783           gint32 nSamplesPerSec;
10784           gint32 nAvgBytesPerSec;
10785           gint16 nBlockAlign;
10786           gint16 wBitsPerSample;
10787           gint16 cbSize;
10788         } WAVEFORMATEX;
10789         WAVEFORMATEX *wfex;
10790
10791         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10792         owma_data = stsd_entry_data;
10793         owma_len = QT_UINT32 (owma_data);
10794         if (owma_len <= 54) {
10795           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10796           break;
10797         }
10798         wfex = (WAVEFORMATEX *) (owma_data + 36);
10799         buf = gst_buffer_new_and_alloc (owma_len - 54);
10800         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10801         if (wfex->wFormatTag == 0x0161) {
10802           codec_name = "Windows Media Audio";
10803           version = 2;
10804         } else if (wfex->wFormatTag == 0x0162) {
10805           codec_name = "Windows Media Audio 9 Pro";
10806           version = 3;
10807         } else if (wfex->wFormatTag == 0x0163) {
10808           codec_name = "Windows Media Audio 9 Lossless";
10809           /* is that correct? gstffmpegcodecmap.c is missing it, but
10810            * fluendo codec seems to support it */
10811           version = 4;
10812         }
10813
10814         gst_caps_set_simple (stream->caps,
10815             "codec_data", GST_TYPE_BUFFER, buf,
10816             "wmaversion", G_TYPE_INT, version,
10817             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10818             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10819             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10820             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10821             NULL);
10822         gst_buffer_unref (buf);
10823
10824         if (codec_name) {
10825           g_free (codec);
10826           codec = g_strdup (codec_name);
10827         }
10828         break;
10829       }
10830       case FOURCC_wma_:
10831       {
10832         gint len = QT_UINT32 (stsd_data) - offset;
10833         const guint8 *wfex_data = stsd_data + offset;
10834         const gchar *codec_name = NULL;
10835         gint version = 1;
10836         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10837         /* FIXME this should also be gst_riff_strf_auds,
10838          * but the latter one is actually missing bits-per-sample :( */
10839         typedef struct
10840         {
10841           gint16 wFormatTag;
10842           gint16 nChannels;
10843           gint32 nSamplesPerSec;
10844           gint32 nAvgBytesPerSec;
10845           gint16 nBlockAlign;
10846           gint16 wBitsPerSample;
10847           gint16 cbSize;
10848         } WAVEFORMATEX;
10849         WAVEFORMATEX wfex;
10850
10851         /* FIXME: unify with similar wavformatex parsing code above */
10852         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10853
10854         /* find wfex */
10855         while (len >= 8) {
10856           gint size;
10857
10858           if (QT_UINT32 (wfex_data) <= len)
10859             size = QT_UINT32 (wfex_data) - 8;
10860           else
10861             size = len - 8;
10862
10863           if (size < 1)
10864             /* No real data, so break out */
10865             break;
10866
10867           switch (QT_FOURCC (wfex_data + 4)) {
10868             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10869             {
10870               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10871
10872               if (size < 8 + 18)
10873                 break;
10874
10875               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10876               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10877               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10878               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10879               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10880               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10881               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10882
10883               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10884               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10885                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10886                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10887                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10888                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10889
10890               if (wfex.wFormatTag == 0x0161) {
10891                 codec_name = "Windows Media Audio";
10892                 version = 2;
10893               } else if (wfex.wFormatTag == 0x0162) {
10894                 codec_name = "Windows Media Audio 9 Pro";
10895                 version = 3;
10896               } else if (wfex.wFormatTag == 0x0163) {
10897                 codec_name = "Windows Media Audio 9 Lossless";
10898                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10899                  * fluendo codec seems to support it */
10900                 version = 4;
10901               }
10902
10903               gst_caps_set_simple (stream->caps,
10904                   "wmaversion", G_TYPE_INT, version,
10905                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10906                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10907                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10908                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10909
10910               if (size > wfex.cbSize) {
10911                 GstBuffer *buf;
10912
10913                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10914                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10915                     size - wfex.cbSize);
10916                 gst_caps_set_simple (stream->caps,
10917                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10918                 gst_buffer_unref (buf);
10919               } else {
10920                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10921               }
10922
10923               if (codec_name) {
10924                 g_free (codec);
10925                 codec = g_strdup (codec_name);
10926               }
10927               break;
10928             }
10929             default:
10930               break;
10931           }
10932           len -= size + 8;
10933           wfex_data += size + 8;
10934         }
10935         break;
10936       }
10937       case FOURCC_opus:
10938       {
10939         const guint8 *opus_data;
10940         guint8 *channel_mapping = NULL;
10941         guint32 rate;
10942         guint8 channels;
10943         guint8 channel_mapping_family;
10944         guint8 stream_count;
10945         guint8 coupled_count;
10946         guint8 i;
10947
10948         opus_data = stsd_entry_data;
10949
10950         channels = GST_READ_UINT8 (opus_data + 45);
10951         rate = GST_READ_UINT32_LE (opus_data + 48);
10952         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10953         stream_count = GST_READ_UINT8 (opus_data + 55);
10954         coupled_count = GST_READ_UINT8 (opus_data + 56);
10955
10956         if (channels > 0) {
10957           channel_mapping = g_malloc (channels * sizeof (guint8));
10958           for (i = 0; i < channels; i++)
10959             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10960         }
10961
10962         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10963             channel_mapping_family, stream_count, coupled_count,
10964             channel_mapping);
10965         break;
10966       }
10967       default:
10968         break;
10969     }
10970
10971     if (codec) {
10972       GstStructure *s;
10973       gint bitrate = 0;
10974
10975       gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10976           GST_TAG_AUDIO_CODEC, codec, NULL);
10977       g_free (codec);
10978       codec = NULL;
10979
10980       /* some bitrate info may have ended up in caps */
10981       s = gst_caps_get_structure (stream->caps, 0);
10982       gst_structure_get_int (s, "bitrate", &bitrate);
10983       if (bitrate > 0)
10984         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10985             GST_TAG_BITRATE, bitrate, NULL);
10986     }
10987
10988     mp4a = qtdemux_tree_get_child_by_index (stsd, 0);
10989     if (!stream->protected) {
10990     } else {
10991       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10992         mp4v = NULL;
10993       }
10994     }
10995     if (stream->protected && fourcc == FOURCC_mp4a) {
10996       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
10997         mp4a = NULL;
10998       }
10999     } else {
11000       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11001         mp4a = NULL;
11002       }
11003     }
11004
11005     wave = NULL;
11006     esds = NULL;
11007     if (mp4a) {
11008       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11009       if (wave)
11010         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11011       if (!esds)
11012         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11013     }
11014
11015
11016     /* If the fourcc's bottom 16 bits gives 'sm', then the top
11017        16 bits is a byte-swapped wave-style codec identifier,
11018        and we can find a WAVE header internally to a 'wave' atom here.
11019        This can more clearly be thought of as 'ms' as the top 16 bits, and a
11020        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11021        is big-endian).
11022      */
11023     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11024       if (len < offset + 20) {
11025         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11026       } else {
11027         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
11028         const guint8 *data = stsd_data + offset + 16;
11029         GNode *wavenode;
11030         GNode *waveheadernode;
11031
11032         wavenode = g_node_new ((guint8 *) data);
11033         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11034           const guint8 *waveheader;
11035           guint32 headerlen;
11036
11037           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11038           if (waveheadernode) {
11039             waveheader = (const guint8 *) waveheadernode->data;
11040             headerlen = QT_UINT32 (waveheader);
11041
11042             if (headerlen > 8) {
11043               gst_riff_strf_auds *header = NULL;
11044               GstBuffer *headerbuf;
11045               GstBuffer *extra;
11046
11047               waveheader += 8;
11048               headerlen -= 8;
11049
11050               headerbuf = gst_buffer_new_and_alloc (headerlen);
11051               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11052
11053               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11054                       headerbuf, &header, &extra)) {
11055                 gst_caps_unref (stream->caps);
11056                 /* FIXME: Need to do something with the channel reorder map */
11057                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
11058                     header, extra, NULL, NULL, NULL);
11059
11060                 if (extra)
11061                   gst_buffer_unref (extra);
11062                 g_free (header);
11063               }
11064             }
11065           } else
11066             GST_DEBUG ("Didn't find waveheadernode for this codec");
11067         }
11068         g_node_destroy (wavenode);
11069       }
11070     } else if (esds) {
11071       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->stream_tags);
11072     } else {
11073       switch (fourcc) {
11074 #if 0
11075           /* FIXME: what is in the chunk? */
11076         case FOURCC_QDMC:
11077         {
11078           gint len = QT_UINT32 (stsd_data);
11079
11080           /* seems to be always = 116 = 0x74 */
11081           break;
11082         }
11083 #endif
11084         case FOURCC_QDM2:
11085         {
11086           gint len = QT_UINT32 (stsd_data);
11087
11088           if (len > 0x4C) {
11089             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
11090
11091             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
11092             gst_caps_set_simple (stream->caps,
11093                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11094             gst_buffer_unref (buf);
11095           }
11096           gst_caps_set_simple (stream->caps,
11097               "samplesize", G_TYPE_INT, samplesize, NULL);
11098           break;
11099         }
11100         case FOURCC_alac:
11101         {
11102           GNode *alac, *wave = NULL;
11103
11104           /* apparently, m4a has this atom appended directly in the stsd entry,
11105            * while mov has it in a wave atom */
11106           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11107           if (alac) {
11108             /* alac now refers to stsd entry atom */
11109             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11110             if (wave)
11111               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11112             else
11113               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11114           }
11115           if (alac) {
11116             const guint8 *alac_data = alac->data;
11117             gint len = QT_UINT32 (alac->data);
11118             GstBuffer *buf;
11119
11120             if (len < 36) {
11121               GST_DEBUG_OBJECT (qtdemux,
11122                   "discarding alac atom with unexpected len %d", len);
11123             } else {
11124               /* codec-data contains alac atom size and prefix,
11125                * ffmpeg likes it that way, not quite gst-ish though ...*/
11126               buf = gst_buffer_new_and_alloc (len);
11127               gst_buffer_fill (buf, 0, alac->data, len);
11128               gst_caps_set_simple (stream->caps,
11129                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11130               gst_buffer_unref (buf);
11131
11132               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
11133               stream->n_channels = QT_UINT8 (alac_data + 21);
11134               stream->rate = QT_UINT32 (alac_data + 32);
11135             }
11136           }
11137           gst_caps_set_simple (stream->caps,
11138               "samplesize", G_TYPE_INT, samplesize, NULL);
11139           break;
11140         }
11141         case FOURCC_fLaC:
11142         {
11143           /* The codingname of the sample entry is 'fLaC' */
11144           GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11145
11146           if (flac) {
11147             /* The 'dfLa' box is added to the sample entry to convey
11148                initializing information for the decoder. */
11149             const GNode *dfla =
11150                 qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11151
11152             if (dfla) {
11153               const guint32 len = QT_UINT32 (dfla->data);
11154
11155               /* Must contain at least dfLa box header (12),
11156                * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11157               if (len < 50) {
11158                 GST_DEBUG_OBJECT (qtdemux,
11159                     "discarding dfla atom with unexpected len %d", len);
11160               } else {
11161                 /* skip dfLa header to get the METADATA_BLOCKs */
11162                 const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11163                 const guint32 metadata_blocks_len = len - 12;
11164
11165                 gchar *stream_marker = g_strdup ("fLaC");
11166                 GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11167                     strlen (stream_marker));
11168
11169                 guint32 index = 0;
11170                 guint32 remainder = 0;
11171                 guint32 block_size = 0;
11172                 gboolean is_last = FALSE;
11173
11174                 GValue array = G_VALUE_INIT;
11175                 GValue value = G_VALUE_INIT;
11176
11177                 g_value_init (&array, GST_TYPE_ARRAY);
11178                 g_value_init (&value, GST_TYPE_BUFFER);
11179
11180                 gst_value_set_buffer (&value, block);
11181                 gst_value_array_append_value (&array, &value);
11182                 g_value_reset (&value);
11183
11184                 gst_buffer_unref (block);
11185
11186                 /* check there's at least one METADATA_BLOCK_HEADER's worth
11187                  * of data, and we haven't already finished parsing */
11188                 while (!is_last && ((index + 3) < metadata_blocks_len)) {
11189                   remainder = metadata_blocks_len - index;
11190
11191                   /* add the METADATA_BLOCK_HEADER size to the signalled size */
11192                   block_size = 4 +
11193                       (metadata_blocks[index + 1] << 16) +
11194                       (metadata_blocks[index + 2] << 8) +
11195                       metadata_blocks[index + 3];
11196
11197                   /* be careful not to read off end of box */
11198                   if (block_size > remainder) {
11199                     break;
11200                   }
11201
11202                   is_last = metadata_blocks[index] >> 7;
11203
11204                   block = gst_buffer_new_and_alloc (block_size);
11205
11206                   gst_buffer_fill (block, 0, &metadata_blocks[index],
11207                       block_size);
11208
11209                   gst_value_set_buffer (&value, block);
11210                   gst_value_array_append_value (&array, &value);
11211                   g_value_reset (&value);
11212
11213                   gst_buffer_unref (block);
11214
11215                   index += block_size;
11216                 }
11217
11218                 /* only append the metadata if we successfully read all of it */
11219                 if (is_last) {
11220                   gst_structure_set_value (gst_caps_get_structure (stream->caps,
11221                           0), "streamheader", &array);
11222                 } else {
11223                   GST_WARNING_OBJECT (qtdemux,
11224                       "discarding all METADATA_BLOCKs due to invalid "
11225                       "block_size %d at idx %d, rem %d", block_size, index,
11226                       remainder);
11227                 }
11228
11229                 g_value_unset (&value);
11230                 g_value_unset (&array);
11231
11232                 /* The sample rate obtained from the stsd may not be accurate
11233                  * since it cannot represent rates greater than 65535Hz, so
11234                  * override that value with the sample rate from the
11235                  * METADATA_BLOCK_STREAMINFO block */
11236                 stream->rate =
11237                     (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11238               }
11239             }
11240           }
11241           break;
11242         }
11243         case FOURCC_sawb:
11244           /* Fallthrough! */
11245           amrwb = TRUE;
11246         case FOURCC_samr:
11247         {
11248           gint len = QT_UINT32 (stsd_data);
11249
11250           if (len > 0x34) {
11251             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
11252             guint bitrate;
11253
11254             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
11255
11256             /* If we have enough data, let's try to get the 'damr' atom. See
11257              * the 3GPP container spec (26.244) for more details. */
11258             if ((len - 0x34) > 8 &&
11259                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11260               gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11261                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11262             }
11263
11264             gst_caps_set_simple (stream->caps,
11265                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11266             gst_buffer_unref (buf);
11267           }
11268           break;
11269         }
11270         case FOURCC_mp4a:
11271         {
11272           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11273           gint len = QT_UINT32 (stsd_data);
11274
11275           if (len >= 50) {
11276             guint16 sound_version = QT_UINT16 (stsd_data + 32);
11277
11278             if (sound_version == 1) {
11279               guint16 channels = QT_UINT16 (stsd_data + 40);
11280               guint32 time_scale = QT_UINT32 (stsd_data + 46);
11281               guint8 codec_data[2];
11282               GstBuffer *buf;
11283               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11284
11285               gint sample_rate_index =
11286                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11287
11288               /* build AAC codec data */
11289               codec_data[0] = profile << 3;
11290               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11291               codec_data[1] = (sample_rate_index & 0x01) << 7;
11292               codec_data[1] |= (channels & 0xF) << 3;
11293
11294               buf = gst_buffer_new_and_alloc (2);
11295               gst_buffer_fill (buf, 0, codec_data, 2);
11296               gst_caps_set_simple (stream->caps,
11297                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11298               gst_buffer_unref (buf);
11299             }
11300           }
11301           break;
11302         }
11303         default:
11304           GST_INFO_OBJECT (qtdemux,
11305               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11306           break;
11307       }
11308     }
11309     GST_INFO_OBJECT (qtdemux,
11310         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11311         GST_FOURCC_ARGS (fourcc), stream->caps);
11312
11313   } else if (stream->subtype == FOURCC_strm) {
11314     if (fourcc == FOURCC_rtsp) {
11315       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11316     } else {
11317       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11318           GST_FOURCC_ARGS (fourcc));
11319       goto unknown_stream;
11320     }
11321     stream->sampled = TRUE;
11322   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11323       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11324
11325     stream->sampled = TRUE;
11326     stream->sparse = TRUE;
11327
11328     stream->caps =
11329         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
11330     if (codec) {
11331       gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11332           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11333       g_free (codec);
11334       codec = NULL;
11335     }
11336
11337     /* hunt for sort-of codec data */
11338     switch (fourcc) {
11339       case FOURCC_mp4s:
11340       {
11341         GNode *mp4s = NULL;
11342         GNode *esds = NULL;
11343
11344         /* look for palette in a stsd->mp4s->esds sub-atom */
11345         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11346         if (mp4s)
11347           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11348         if (esds == NULL) {
11349           /* Invalid STSD */
11350           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11351           break;
11352         }
11353
11354         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->stream_tags);
11355         break;
11356       }
11357       default:
11358         GST_INFO_OBJECT (qtdemux,
11359             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11360         break;
11361     }
11362     GST_INFO_OBJECT (qtdemux,
11363         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11364         GST_FOURCC_ARGS (fourcc), stream->caps);
11365   } else {
11366     /* everything in 1 sample */
11367     stream->sampled = TRUE;
11368
11369     stream->caps =
11370         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
11371
11372     if (stream->caps == NULL)
11373       goto unknown_stream;
11374
11375     if (codec) {
11376       gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11377           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11378       g_free (codec);
11379       codec = NULL;
11380     }
11381   }
11382
11383   /* promote to sampled format */
11384   if (stream->fourcc == FOURCC_samr) {
11385     /* force mono 8000 Hz for AMR */
11386     stream->sampled = TRUE;
11387     stream->n_channels = 1;
11388     stream->rate = 8000;
11389   } else if (stream->fourcc == FOURCC_sawb) {
11390     /* force mono 16000 Hz for AMR-WB */
11391     stream->sampled = TRUE;
11392     stream->n_channels = 1;
11393     stream->rate = 16000;
11394   } else if (stream->fourcc == FOURCC_mp4a) {
11395     stream->sampled = TRUE;
11396   }
11397
11398   /* collect sample information */
11399   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11400     goto samples_failed;
11401
11402   if (qtdemux->fragmented) {
11403     guint64 offset;
11404
11405     /* need all moov samples as basis; probably not many if any at all */
11406     /* prevent moof parsing taking of at this time */
11407     offset = qtdemux->moof_offset;
11408     qtdemux->moof_offset = 0;
11409     if (stream->n_samples &&
11410         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11411       qtdemux->moof_offset = offset;
11412       goto samples_failed;
11413     }
11414     qtdemux->moof_offset = 0;
11415     /* movie duration more reliable in this case (e.g. mehd) */
11416     if (qtdemux->segment.duration &&
11417         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11418       stream->duration =
11419           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11420   }
11421
11422   /* configure segments */
11423   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11424     goto segments_failed;
11425
11426   /* add some language tag, if useful */
11427   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11428       strcmp (stream->lang_id, "und")) {
11429     const gchar *lang_code;
11430
11431     /* convert ISO 639-2 code to ISO 639-1 */
11432     lang_code = gst_tag_get_language_code (stream->lang_id);
11433     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11434         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11435   }
11436
11437   /* Check for UDTA tags */
11438   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11439     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11440   }
11441
11442   /* now we are ready to add the stream */
11443   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11444     goto too_many_streams;
11445
11446   if (!qtdemux->got_moov) {
11447     qtdemux->streams[qtdemux->n_streams] = stream;
11448     qtdemux->n_streams++;
11449     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11450   }
11451
11452   return TRUE;
11453
11454 /* ERRORS */
11455 skip_track:
11456   {
11457     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11458     if (new_stream)
11459       gst_qtdemux_stream_free (qtdemux, stream);
11460     return TRUE;
11461   }
11462 corrupt_file:
11463   {
11464     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11465         (_("This file is corrupt and cannot be played.")), (NULL));
11466     if (new_stream)
11467       gst_qtdemux_stream_free (qtdemux, stream);
11468     return FALSE;
11469   }
11470 error_encrypted:
11471   {
11472     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11473     if (new_stream)
11474       gst_qtdemux_stream_free (qtdemux, stream);
11475     return FALSE;
11476   }
11477 samples_failed:
11478 segments_failed:
11479   {
11480     /* we posted an error already */
11481     /* free stbl sub-atoms */
11482     gst_qtdemux_stbl_free (stream);
11483     if (new_stream)
11484       gst_qtdemux_stream_free (qtdemux, stream);
11485     return FALSE;
11486   }
11487 existing_stream:
11488   {
11489     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11490         track_id);
11491     if (new_stream)
11492       gst_qtdemux_stream_free (qtdemux, stream);
11493     return TRUE;
11494   }
11495 unknown_stream:
11496   {
11497     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11498         GST_FOURCC_ARGS (stream->subtype));
11499     if (new_stream)
11500       gst_qtdemux_stream_free (qtdemux, stream);
11501     return TRUE;
11502   }
11503 too_many_streams:
11504   {
11505     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11506         (_("This file contains too many streams. Only playing first %d"),
11507             GST_QTDEMUX_MAX_STREAMS), (NULL));
11508     return TRUE;
11509   }
11510 }
11511
11512 /* If we can estimate the overall bitrate, and don't have information about the
11513  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11514  * the overall bitrate minus the sum of the bitrates of all other streams. This
11515  * should be useful for the common case where we have one audio and one video
11516  * stream and can estimate the bitrate of one, but not the other. */
11517 static void
11518 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11519 {
11520   QtDemuxStream *stream = NULL;
11521   gint64 size, sys_bitrate, sum_bitrate = 0;
11522   GstClockTime duration;
11523   gint i;
11524   guint bitrate;
11525
11526   if (qtdemux->fragmented)
11527     return;
11528
11529   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11530
11531   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11532       || size <= 0) {
11533     GST_DEBUG_OBJECT (qtdemux,
11534         "Size in bytes of the stream not known - bailing");
11535     return;
11536   }
11537
11538   /* Subtract the header size */
11539   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11540       size, qtdemux->header_size);
11541
11542   if (size < qtdemux->header_size)
11543     return;
11544
11545   size = size - qtdemux->header_size;
11546
11547   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11548     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11549     return;
11550   }
11551
11552   for (i = 0; i < qtdemux->n_streams; i++) {
11553     switch (qtdemux->streams[i]->subtype) {
11554       case FOURCC_soun:
11555       case FOURCC_vide:
11556         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11557             qtdemux->streams[i]->caps);
11558         /* retrieve bitrate, prefer avg then max */
11559         bitrate = 0;
11560         if (qtdemux->streams[i]->stream_tags) {
11561           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11562               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11563           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11564           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11565               GST_TAG_NOMINAL_BITRATE, &bitrate);
11566           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11567           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11568               GST_TAG_BITRATE, &bitrate);
11569           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11570         }
11571         if (bitrate)
11572           sum_bitrate += bitrate;
11573         else {
11574           if (stream) {
11575             GST_DEBUG_OBJECT (qtdemux,
11576                 ">1 stream with unknown bitrate - bailing");
11577             return;
11578           } else
11579             stream = qtdemux->streams[i];
11580         }
11581
11582       default:
11583         /* For other subtypes, we assume no significant impact on bitrate */
11584         break;
11585     }
11586   }
11587
11588   if (!stream) {
11589     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11590     return;
11591   }
11592
11593   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11594
11595   if (sys_bitrate < sum_bitrate) {
11596     /* This can happen, since sum_bitrate might be derived from maximum
11597      * bitrates and not average bitrates */
11598     GST_DEBUG_OBJECT (qtdemux,
11599         "System bitrate less than sum bitrate - bailing");
11600     return;
11601   }
11602
11603   bitrate = sys_bitrate - sum_bitrate;
11604   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11605       ", Stream bitrate = %u", sys_bitrate, bitrate);
11606
11607   if (!stream->stream_tags)
11608     stream->stream_tags = gst_tag_list_new_empty ();
11609   else
11610     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11611
11612   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11613       GST_TAG_BITRATE, bitrate, NULL);
11614 }
11615
11616 static GstFlowReturn
11617 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11618 {
11619   gint i;
11620   GstFlowReturn ret = GST_FLOW_OK;
11621
11622   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11623
11624   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11625     QtDemuxStream *stream = qtdemux->streams[i];
11626     guint32 sample_num = 0;
11627
11628     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11629         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11630
11631     if (qtdemux->fragmented) {
11632       /* need all moov samples first */
11633       GST_OBJECT_LOCK (qtdemux);
11634       while (stream->n_samples == 0)
11635         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11636           break;
11637       GST_OBJECT_UNLOCK (qtdemux);
11638     } else {
11639       /* discard any stray moof */
11640       qtdemux->moof_offset = 0;
11641     }
11642
11643     /* prepare braking */
11644     if (ret != GST_FLOW_ERROR)
11645       ret = GST_FLOW_OK;
11646
11647     /* in pull mode, we should have parsed some sample info by now;
11648      * and quite some code will not handle no samples.
11649      * in push mode, we'll just have to deal with it */
11650     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11651       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11652       gst_qtdemux_remove_stream (qtdemux, i);
11653       i--;
11654       continue;
11655     }
11656
11657     /* parse the initial sample for use in setting the frame rate cap */
11658     while (sample_num == 0 && sample_num < stream->n_samples) {
11659       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11660         break;
11661       ++sample_num;
11662     }
11663     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11664       stream->first_duration = stream->samples[0].duration;
11665       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11666           stream->track_id, stream->first_duration);
11667     }
11668   }
11669
11670   return ret;
11671 }
11672
11673 static GstFlowReturn
11674 qtdemux_expose_streams (GstQTDemux * qtdemux)
11675 {
11676   gint i;
11677   GSList *oldpads = NULL;
11678   GSList *iter;
11679
11680   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11681
11682   for (i = 0; i < qtdemux->n_streams; i++) {
11683     QtDemuxStream *stream = qtdemux->streams[i];
11684     GstPad *oldpad = stream->pad;
11685     GstTagList *list;
11686
11687     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11688         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11689
11690     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11691         stream->track_id == qtdemux->chapters_track_id) {
11692       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11693          so that it doesn't look like a subtitle track */
11694       gst_qtdemux_remove_stream (qtdemux, i);
11695       i--;
11696       continue;
11697     }
11698
11699     /* now we have all info and can expose */
11700     list = stream->stream_tags;
11701     stream->stream_tags = NULL;
11702     if (oldpad)
11703       oldpads = g_slist_prepend (oldpads, oldpad);
11704     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11705       return GST_FLOW_ERROR;
11706   }
11707
11708   gst_qtdemux_guess_bitrate (qtdemux);
11709
11710   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11711
11712   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11713     GstPad *oldpad = iter->data;
11714     GstEvent *event;
11715
11716     event = gst_event_new_eos ();
11717     if (qtdemux->segment_seqnum)
11718       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11719
11720     gst_pad_push_event (oldpad, event);
11721     gst_pad_set_active (oldpad, FALSE);
11722     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11723     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11724     gst_object_unref (oldpad);
11725   }
11726
11727   /* check if we should post a redirect in case there is a single trak
11728    * and it is a redirecting trak */
11729   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11730     GstMessage *m;
11731
11732     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11733         "an external content");
11734     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11735         gst_structure_new ("redirect",
11736             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11737             NULL));
11738     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11739     qtdemux->posted_redirect = TRUE;
11740   }
11741
11742   for (i = 0; i < qtdemux->n_streams; i++) {
11743     QtDemuxStream *stream = qtdemux->streams[i];
11744
11745     qtdemux_do_allocation (qtdemux, stream);
11746   }
11747
11748   qtdemux->exposed = TRUE;
11749   return GST_FLOW_OK;
11750 }
11751
11752 /* check if major or compatible brand is 3GP */
11753 static inline gboolean
11754 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11755 {
11756   if (major) {
11757     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11758         FOURCC_3g__);
11759   } else if (qtdemux->comp_brands != NULL) {
11760     GstMapInfo map;
11761     guint8 *data;
11762     gsize size;
11763     gboolean res = FALSE;
11764
11765     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11766     data = map.data;
11767     size = map.size;
11768     while (size >= 4) {
11769       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11770           FOURCC_3g__);
11771       data += 4;
11772       size -= 4;
11773     }
11774     gst_buffer_unmap (qtdemux->comp_brands, &map);
11775     return res;
11776   } else {
11777     return FALSE;
11778   }
11779 }
11780
11781 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11782 static inline gboolean
11783 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11784 {
11785   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11786       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11787       || fourcc == FOURCC_albm;
11788 }
11789
11790 static void
11791 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11792     const char *tag, const char *dummy, GNode * node)
11793 {
11794   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11795   int offset;
11796   char *name;
11797   gchar *data;
11798   gdouble longitude, latitude, altitude;
11799   gint len;
11800
11801   len = QT_UINT32 (node->data);
11802   if (len <= 14)
11803     goto short_read;
11804
11805   data = node->data;
11806   offset = 14;
11807
11808   /* TODO: language code skipped */
11809
11810   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11811
11812   if (!name) {
11813     /* do not alarm in trivial case, but bail out otherwise */
11814     if (*(data + offset) != 0) {
11815       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11816           "giving up", tag);
11817     }
11818   } else {
11819     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11820         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11821     offset += strlen (name);
11822     g_free (name);
11823   }
11824
11825   if (len < offset + 2 + 4 + 4 + 4)
11826     goto short_read;
11827
11828   /* +1 +1 = skip null-terminator and location role byte */
11829   offset += 1 + 1;
11830   /* table in spec says unsigned, semantics say negative has meaning ... */
11831   longitude = QT_SFP32 (data + offset);
11832
11833   offset += 4;
11834   latitude = QT_SFP32 (data + offset);
11835
11836   offset += 4;
11837   altitude = QT_SFP32 (data + offset);
11838
11839   /* one invalid means all are invalid */
11840   if (longitude >= -180.0 && longitude <= 180.0 &&
11841       latitude >= -90.0 && latitude <= 90.0) {
11842     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11843         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11844         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11845         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11846   }
11847
11848   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11849
11850   return;
11851
11852   /* ERRORS */
11853 short_read:
11854   {
11855     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11856     return;
11857   }
11858 }
11859
11860
11861 static void
11862 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11863     const char *tag, const char *dummy, GNode * node)
11864 {
11865   guint16 y;
11866   GDate *date;
11867   gint len;
11868
11869   len = QT_UINT32 (node->data);
11870   if (len < 14)
11871     return;
11872
11873   y = QT_UINT16 ((guint8 *) node->data + 12);
11874   if (y == 0) {
11875     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11876     return;
11877   }
11878   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11879
11880   date = g_date_new_dmy (1, 1, y);
11881   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11882   g_date_free (date);
11883 }
11884
11885 static void
11886 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11887     const char *tag, const char *dummy, GNode * node)
11888 {
11889   int offset;
11890   char *tag_str = NULL;
11891   guint8 *entity;
11892   guint16 table;
11893   gint len;
11894
11895   len = QT_UINT32 (node->data);
11896   if (len <= 20)
11897     goto short_read;
11898
11899   offset = 12;
11900   entity = (guint8 *) node->data + offset;
11901   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11902     GST_DEBUG_OBJECT (qtdemux,
11903         "classification info: %c%c%c%c invalid classification entity",
11904         entity[0], entity[1], entity[2], entity[3]);
11905     return;
11906   }
11907
11908   offset += 4;
11909   table = QT_UINT16 ((guint8 *) node->data + offset);
11910
11911   /* Language code skipped */
11912
11913   offset += 4;
11914
11915   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11916    * XXXX: classification entity, fixed length 4 chars.
11917    * Y[YYYY]: classification table, max 5 chars.
11918    */
11919   tag_str = g_strdup_printf ("----://%u/%s",
11920       table, (char *) node->data + offset);
11921
11922   /* memcpy To be sure we're preserving byte order */
11923   memcpy (tag_str, entity, 4);
11924   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11925
11926   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11927
11928   g_free (tag_str);
11929
11930   return;
11931
11932   /* ERRORS */
11933 short_read:
11934   {
11935     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11936     return;
11937   }
11938 }
11939
11940 static gboolean
11941 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11942     const char *tag, const char *dummy, GNode * node)
11943 {
11944   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11945   GNode *data;
11946   char *s;
11947   int len;
11948   guint32 type;
11949   int offset;
11950   gboolean ret = TRUE;
11951   const gchar *charset = NULL;
11952
11953   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11954   if (data) {
11955     len = QT_UINT32 (data->data);
11956     type = QT_UINT32 ((guint8 *) data->data + 8);
11957     if (type == 0x00000001 && len > 16) {
11958       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11959           env_vars);
11960       if (s) {
11961         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11962         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11963         g_free (s);
11964       } else {
11965         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11966       }
11967     }
11968   } else {
11969     len = QT_UINT32 (node->data);
11970     type = QT_UINT32 ((guint8 *) node->data + 4);
11971     if ((type >> 24) == 0xa9 && len > 8 + 4) {
11972       gint str_len;
11973       gint lang_code;
11974
11975       /* Type starts with the (C) symbol, so the next data is a list
11976        * of (string size(16), language code(16), string) */
11977
11978       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11979       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11980
11981       /* the string + fourcc + size + 2 16bit fields,
11982        * means that there are more tags in this atom */
11983       if (len > str_len + 8 + 4) {
11984         /* TODO how to represent the same tag in different languages? */
11985         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11986             "text alternatives, reading only first one");
11987       }
11988
11989       offset = 12;
11990       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
11991       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11992
11993       if (lang_code < 0x800) {  /* MAC encoded string */
11994         charset = "mac";
11995       }
11996     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11997             QT_FOURCC ((guint8 *) node->data + 4))) {
11998       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11999
12000       /* we go for 3GP style encoding if major brands claims so,
12001        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12002       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12003           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12004               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12005         offset = 14;
12006         /* 16-bit Language code is ignored here as well */
12007         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12008       } else {
12009         goto normal;
12010       }
12011     } else {
12012     normal:
12013       offset = 8;
12014       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12015       ret = FALSE;              /* may have to fallback */
12016     }
12017     if (charset) {
12018       GError *err = NULL;
12019
12020       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12021           charset, NULL, NULL, &err);
12022       if (err) {
12023         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12024             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12025             err->message);
12026         g_error_free (err);
12027       }
12028     } else {
12029       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12030           len - offset, env_vars);
12031     }
12032     if (s) {
12033       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12034       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12035       g_free (s);
12036       ret = TRUE;
12037     } else {
12038       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12039     }
12040   }
12041   return ret;
12042 }
12043
12044 static void
12045 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12046     const char *tag, const char *dummy, GNode * node)
12047 {
12048   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12049 }
12050
12051 static void
12052 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12053     const char *tag, const char *dummy, GNode * node)
12054 {
12055   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12056   guint8 *data;
12057   char *s, *t, *k = NULL;
12058   int len;
12059   int offset;
12060   int count;
12061
12062   /* first try normal string tag if major brand not 3GP */
12063   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12064     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12065       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12066        * let's try it 3gpp way after minor safety check */
12067       data = node->data;
12068       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12069         return;
12070     } else
12071       return;
12072   }
12073
12074   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12075
12076   data = node->data;
12077
12078   len = QT_UINT32 (data);
12079   if (len < 15)
12080     goto short_read;
12081
12082   count = QT_UINT8 (data + 14);
12083   offset = 15;
12084   for (; count; count--) {
12085     gint slen;
12086
12087     if (offset + 1 > len)
12088       goto short_read;
12089     slen = QT_UINT8 (data + offset);
12090     offset += 1;
12091     if (offset + slen > len)
12092       goto short_read;
12093     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12094         slen, env_vars);
12095     if (s) {
12096       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12097       if (k) {
12098         t = g_strjoin (",", k, s, NULL);
12099         g_free (s);
12100         g_free (k);
12101         k = t;
12102       } else {
12103         k = s;
12104       }
12105     } else {
12106       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12107     }
12108     offset += slen;
12109   }
12110
12111 done:
12112   if (k) {
12113     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12114     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12115   }
12116   g_free (k);
12117
12118   return;
12119
12120   /* ERRORS */
12121 short_read:
12122   {
12123     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12124     goto done;
12125   }
12126 }
12127
12128 static void
12129 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12130     const char *tag1, const char *tag2, GNode * node)
12131 {
12132   GNode *data;
12133   int len;
12134   int type;
12135   int n1, n2;
12136
12137   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12138   if (data) {
12139     len = QT_UINT32 (data->data);
12140     type = QT_UINT32 ((guint8 *) data->data + 8);
12141     if (type == 0x00000000 && len >= 22) {
12142       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12143       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12144       if (n1 > 0) {
12145         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12146         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12147       }
12148       if (n2 > 0) {
12149         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12150         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12151       }
12152     }
12153   }
12154 }
12155
12156 static void
12157 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12158     const char *tag1, const char *dummy, GNode * node)
12159 {
12160   GNode *data;
12161   int len;
12162   int type;
12163   int n1;
12164
12165   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12166   if (data) {
12167     len = QT_UINT32 (data->data);
12168     type = QT_UINT32 ((guint8 *) data->data + 8);
12169     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12170     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12171     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12172       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12173       if (n1) {
12174         /* do not add bpm=0 */
12175         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12176         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12177             NULL);
12178       }
12179     }
12180   }
12181 }
12182
12183 static void
12184 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12185     const char *tag1, const char *dummy, GNode * node)
12186 {
12187   GNode *data;
12188   int len;
12189   int type;
12190   guint32 num;
12191
12192   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12193   if (data) {
12194     len = QT_UINT32 (data->data);
12195     type = QT_UINT32 ((guint8 *) data->data + 8);
12196     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12197     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12198     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12199       num = QT_UINT32 ((guint8 *) data->data + 16);
12200       if (num) {
12201         /* do not add num=0 */
12202         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12203         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12204       }
12205     }
12206   }
12207 }
12208
12209 static void
12210 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12211     const char *tag1, const char *dummy, GNode * node)
12212 {
12213   GNode *data;
12214   int len;
12215   int type;
12216   GstSample *sample;
12217
12218   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12219   if (data) {
12220     len = QT_UINT32 (data->data);
12221     type = QT_UINT32 ((guint8 *) data->data + 8);
12222     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12223     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12224       GstTagImageType image_type;
12225
12226       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12227         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12228       else
12229         image_type = GST_TAG_IMAGE_TYPE_NONE;
12230
12231       if ((sample =
12232               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12233                   len - 16, image_type))) {
12234         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12235         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12236         gst_sample_unref (sample);
12237       }
12238     }
12239   }
12240 }
12241
12242 static void
12243 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12244     const char *tag, const char *dummy, GNode * node)
12245 {
12246   GNode *data;
12247   char *s;
12248   int len;
12249   int type;
12250
12251   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12252   if (data) {
12253     len = QT_UINT32 (data->data);
12254     type = QT_UINT32 ((guint8 *) data->data + 8);
12255     if (type == 0x00000001 && len > 16) {
12256       guint y, m = 1, d = 1;
12257       gint ret;
12258
12259       s = g_strndup ((char *) data->data + 16, len - 16);
12260       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12261       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12262       if (ret >= 1 && y > 1500 && y < 3000) {
12263         GDate *date;
12264
12265         date = g_date_new_dmy (d, m, y);
12266         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12267         g_date_free (date);
12268       } else {
12269         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12270       }
12271       g_free (s);
12272     }
12273   }
12274 }
12275
12276 static void
12277 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12278     const char *tag, const char *dummy, GNode * node)
12279 {
12280   GNode *data;
12281
12282   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12283
12284   /* re-route to normal string tag if major brand says so
12285    * or no data atom and compatible brand suggests so */
12286   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12287       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12288     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12289     return;
12290   }
12291
12292   if (data) {
12293     guint len, type, n;
12294
12295     len = QT_UINT32 (data->data);
12296     type = QT_UINT32 ((guint8 *) data->data + 8);
12297     if (type == 0x00000000 && len >= 18) {
12298       n = QT_UINT16 ((guint8 *) data->data + 16);
12299       if (n > 0) {
12300         const gchar *genre;
12301
12302         genre = gst_tag_id3_genre_get (n - 1);
12303         if (genre != NULL) {
12304           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12305           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12306         }
12307       }
12308     }
12309   }
12310 }
12311
12312 static void
12313 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12314     const gchar * tag, guint8 * data, guint32 datasize)
12315 {
12316   gdouble value;
12317   gchar *datacopy;
12318
12319   /* make a copy to have \0 at the end */
12320   datacopy = g_strndup ((gchar *) data, datasize);
12321
12322   /* convert the str to double */
12323   if (sscanf (datacopy, "%lf", &value) == 1) {
12324     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12325     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12326   } else {
12327     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12328         datacopy);
12329   }
12330   g_free (datacopy);
12331 }
12332
12333
12334 static void
12335 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12336     const char *tag, const char *tag_bis, GNode * node)
12337 {
12338   GNode *mean;
12339   GNode *name;
12340   GNode *data;
12341   guint32 meansize;
12342   guint32 namesize;
12343   guint32 datatype;
12344   guint32 datasize;
12345   const gchar *meanstr;
12346   const gchar *namestr;
12347
12348   /* checking the whole ---- atom size for consistency */
12349   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12350     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12351     return;
12352   }
12353
12354   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12355   if (!mean) {
12356     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12357     return;
12358   }
12359
12360   meansize = QT_UINT32 (mean->data);
12361   if (meansize <= 12) {
12362     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12363     return;
12364   }
12365   meanstr = ((gchar *) mean->data) + 12;
12366   meansize -= 12;
12367
12368   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12369   if (!name) {
12370     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12371     return;
12372   }
12373
12374   namesize = QT_UINT32 (name->data);
12375   if (namesize <= 12) {
12376     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12377     return;
12378   }
12379   namestr = ((gchar *) name->data) + 12;
12380   namesize -= 12;
12381
12382   /*
12383    * Data atom is:
12384    * uint32 - size
12385    * uint32 - name
12386    * uint8  - version
12387    * uint24 - data type
12388    * uint32 - all 0
12389    * rest   - the data
12390    */
12391   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12392   if (!data) {
12393     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12394     return;
12395   }
12396   datasize = QT_UINT32 (data->data);
12397   if (datasize <= 16) {
12398     GST_WARNING_OBJECT (demux, "Data atom too small");
12399     return;
12400   }
12401   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12402
12403   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12404       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12405     static const struct
12406     {
12407       const gchar name[28];
12408       const gchar tag[28];
12409     } tags[] = {
12410       {
12411       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12412       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12413       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12414       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12415       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12416       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12417       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12418       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12419     };
12420     int i;
12421
12422     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12423       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12424         switch (gst_tag_get_type (tags[i].tag)) {
12425           case G_TYPE_DOUBLE:
12426             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12427                 ((guint8 *) data->data) + 16, datasize - 16);
12428             break;
12429           case G_TYPE_STRING:
12430             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12431             break;
12432           default:
12433             /* not reached */
12434             break;
12435         }
12436         break;
12437       }
12438     }
12439     if (i == G_N_ELEMENTS (tags))
12440       goto unknown_tag;
12441   } else {
12442     goto unknown_tag;
12443   }
12444
12445   return;
12446
12447 /* errors */
12448 unknown_tag:
12449 #ifndef GST_DISABLE_GST_DEBUG
12450   {
12451     gchar *namestr_dbg;
12452     gchar *meanstr_dbg;
12453
12454     meanstr_dbg = g_strndup (meanstr, meansize);
12455     namestr_dbg = g_strndup (namestr, namesize);
12456
12457     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12458         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12459
12460     g_free (namestr_dbg);
12461     g_free (meanstr_dbg);
12462   }
12463 #endif
12464   return;
12465 }
12466
12467 static void
12468 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12469     const char *tag_bis, GNode * node)
12470 {
12471   guint8 *data;
12472   GstBuffer *buf;
12473   guint len;
12474   GstTagList *id32_taglist = NULL;
12475
12476   GST_LOG_OBJECT (demux, "parsing ID32");
12477
12478   data = node->data;
12479   len = GST_READ_UINT32_BE (data);
12480
12481   /* need at least full box and language tag */
12482   if (len < 12 + 2)
12483     return;
12484
12485   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12486   gst_buffer_fill (buf, 0, data + 14, len - 14);
12487
12488   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12489   if (id32_taglist) {
12490     GST_LOG_OBJECT (demux, "parsing ok");
12491     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12492     gst_tag_list_unref (id32_taglist);
12493   } else {
12494     GST_LOG_OBJECT (demux, "parsing failed");
12495   }
12496
12497   gst_buffer_unref (buf);
12498 }
12499
12500 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12501     const char *tag, const char *tag_bis, GNode * node);
12502
12503 /* unmapped tags
12504 FOURCC_pcst -> if media is a podcast -> bool
12505 FOURCC_cpil -> if media is part of a compilation -> bool
12506 FOURCC_pgap -> if media is part of a gapless context -> bool
12507 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12508 */
12509
12510 static const struct
12511 {
12512   guint32 fourcc;
12513   const gchar *gst_tag;
12514   const gchar *gst_tag_bis;
12515   const GstQTDemuxAddTagFunc func;
12516 } add_funcs[] = {
12517   {
12518   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12519   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12520   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12521   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12522   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12523   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12524   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12525   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12526   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12527   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12528   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12529   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12530   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12531   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12532   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12533   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12534   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12535   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12536   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12537   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12538   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12539   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12540   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12541         qtdemux_tag_add_num}, {
12542   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12543         qtdemux_tag_add_num}, {
12544   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12545   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12546   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12547   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12548   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12549   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12550   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12551   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12552   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12553   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12554   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12555   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12556   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12557   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12558   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12559   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12560   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12561   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12562         qtdemux_tag_add_classification}, {
12563   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12564   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12565   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12566
12567     /* This is a special case, some tags are stored in this
12568      * 'reverse dns naming', according to:
12569      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12570      * bug #614471
12571      */
12572   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12573     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12574   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12575 };
12576
12577 struct _GstQtDemuxTagList
12578 {
12579   GstQTDemux *demux;
12580   GstTagList *taglist;
12581 };
12582 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12583
12584 static void
12585 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12586 {
12587   gint len;
12588   guint8 *data;
12589   GstBuffer *buf;
12590   gchar *media_type;
12591   const gchar *style;
12592   GstSample *sample;
12593   GstStructure *s;
12594   guint i;
12595   guint8 ndata[4];
12596   GstQTDemux *demux = qtdemuxtaglist->demux;
12597   GstTagList *taglist = qtdemuxtaglist->taglist;
12598
12599   data = node->data;
12600   len = QT_UINT32 (data);
12601   buf = gst_buffer_new_and_alloc (len);
12602   gst_buffer_fill (buf, 0, data, len);
12603
12604   /* heuristic to determine style of tag */
12605   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12606       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12607     style = "itunes";
12608   else if (demux->major_brand == FOURCC_qt__)
12609     style = "quicktime";
12610   /* fall back to assuming iso/3gp tag style */
12611   else
12612     style = "iso";
12613
12614   /* santize the name for the caps. */
12615   for (i = 0; i < 4; i++) {
12616     guint8 d = data[4 + i];
12617     if (g_ascii_isalnum (d))
12618       ndata[i] = g_ascii_tolower (d);
12619     else
12620       ndata[i] = '_';
12621   }
12622
12623   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12624       ndata[0], ndata[1], ndata[2], ndata[3]);
12625   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12626
12627   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12628   sample = gst_sample_new (buf, NULL, NULL, s);
12629   gst_buffer_unref (buf);
12630   g_free (media_type);
12631
12632   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12633       len, s);
12634
12635   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12636       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12637
12638   gst_sample_unref (sample);
12639 }
12640
12641 static void
12642 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12643 {
12644   GNode *meta;
12645   GNode *ilst;
12646   GNode *xmp_;
12647   GNode *node;
12648   gint i;
12649   GstQtDemuxTagList demuxtaglist;
12650
12651   demuxtaglist.demux = qtdemux;
12652   demuxtaglist.taglist = taglist;
12653
12654   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12655   if (meta != NULL) {
12656     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12657     if (ilst == NULL) {
12658       GST_LOG_OBJECT (qtdemux, "no ilst");
12659       return;
12660     }
12661   } else {
12662     ilst = udta;
12663     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12664   }
12665
12666   i = 0;
12667   while (i < G_N_ELEMENTS (add_funcs)) {
12668     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12669     if (node) {
12670       gint len;
12671
12672       len = QT_UINT32 (node->data);
12673       if (len < 12) {
12674         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12675             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12676       } else {
12677         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12678             add_funcs[i].gst_tag_bis, node);
12679       }
12680       g_node_destroy (node);
12681     } else {
12682       i++;
12683     }
12684   }
12685
12686   /* parsed nodes have been removed, pass along remainder as blob */
12687   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12688       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12689
12690   /* parse up XMP_ node if existing */
12691   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12692   if (xmp_ != NULL) {
12693     GstBuffer *buf;
12694     GstTagList *xmptaglist;
12695
12696     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12697         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12698     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12699     gst_buffer_unref (buf);
12700
12701     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12702   } else {
12703     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12704   }
12705 }
12706
12707 typedef struct
12708 {
12709   GstStructure *structure;      /* helper for sort function */
12710   gchar *location;
12711   guint min_req_bitrate;
12712   guint min_req_qt_version;
12713 } GstQtReference;
12714
12715 static gint
12716 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12717 {
12718   GstQtReference *ref_a = (GstQtReference *) a;
12719   GstQtReference *ref_b = (GstQtReference *) b;
12720
12721   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12722     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12723
12724   /* known bitrates go before unknown; higher bitrates go first */
12725   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12726 }
12727
12728 /* sort the redirects and post a message for the application.
12729  */
12730 static void
12731 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12732 {
12733   GstQtReference *best;
12734   GstStructure *s;
12735   GstMessage *msg;
12736   GValue list_val = { 0, };
12737   GList *l;
12738
12739   g_assert (references != NULL);
12740
12741   references = g_list_sort (references, qtdemux_redirects_sort_func);
12742
12743   best = (GstQtReference *) references->data;
12744
12745   g_value_init (&list_val, GST_TYPE_LIST);
12746
12747   for (l = references; l != NULL; l = l->next) {
12748     GstQtReference *ref = (GstQtReference *) l->data;
12749     GValue struct_val = { 0, };
12750
12751     ref->structure = gst_structure_new ("redirect",
12752         "new-location", G_TYPE_STRING, ref->location, NULL);
12753
12754     if (ref->min_req_bitrate > 0) {
12755       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12756           ref->min_req_bitrate, NULL);
12757     }
12758
12759     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12760     g_value_set_boxed (&struct_val, ref->structure);
12761     gst_value_list_append_value (&list_val, &struct_val);
12762     g_value_unset (&struct_val);
12763     /* don't free anything here yet, since we need best->structure below */
12764   }
12765
12766   g_assert (best != NULL);
12767   s = gst_structure_copy (best->structure);
12768
12769   if (g_list_length (references) > 1) {
12770     gst_structure_set_value (s, "locations", &list_val);
12771   }
12772
12773   g_value_unset (&list_val);
12774
12775   for (l = references; l != NULL; l = l->next) {
12776     GstQtReference *ref = (GstQtReference *) l->data;
12777
12778     gst_structure_free (ref->structure);
12779     g_free (ref->location);
12780     g_free (ref);
12781   }
12782   g_list_free (references);
12783
12784   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12785   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12786   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12787   qtdemux->posted_redirect = TRUE;
12788 }
12789
12790 /* look for redirect nodes, collect all redirect information and
12791  * process it.
12792  */
12793 static gboolean
12794 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12795 {
12796   GNode *rmra, *rmda, *rdrf;
12797
12798   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12799   if (rmra) {
12800     GList *redirects = NULL;
12801
12802     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12803     while (rmda) {
12804       GstQtReference ref = { NULL, NULL, 0, 0 };
12805       GNode *rmdr, *rmvc;
12806
12807       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12808         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12809         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12810             ref.min_req_bitrate);
12811       }
12812
12813       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12814         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12815         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12816
12817 #ifndef GST_DISABLE_GST_DEBUG
12818         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12819 #endif
12820         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12821
12822         GST_LOG_OBJECT (qtdemux,
12823             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12824             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12825             bitmask, check_type);
12826         if (package == FOURCC_qtim && check_type == 0) {
12827           ref.min_req_qt_version = version;
12828         }
12829       }
12830
12831       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12832       if (rdrf) {
12833         guint32 ref_type;
12834         guint8 *ref_data;
12835         guint ref_len;
12836
12837         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12838         if (ref_len > 20) {
12839           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12840           ref_data = (guint8 *) rdrf->data + 20;
12841           if (ref_type == FOURCC_alis) {
12842             guint record_len, record_version, fn_len;
12843
12844             if (ref_len > 70) {
12845               /* MacOSX alias record, google for alias-layout.txt */
12846               record_len = QT_UINT16 (ref_data + 4);
12847               record_version = QT_UINT16 (ref_data + 4 + 2);
12848               fn_len = QT_UINT8 (ref_data + 50);
12849               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12850                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12851               }
12852             } else {
12853               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12854                   ref_len);
12855             }
12856           } else if (ref_type == FOURCC_url_) {
12857             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12858           } else {
12859             GST_DEBUG_OBJECT (qtdemux,
12860                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12861                 GST_FOURCC_ARGS (ref_type));
12862           }
12863           if (ref.location != NULL) {
12864             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12865             redirects =
12866                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12867           } else {
12868             GST_WARNING_OBJECT (qtdemux,
12869                 "Failed to extract redirect location from rdrf atom");
12870           }
12871         } else {
12872           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12873         }
12874       }
12875
12876       /* look for others */
12877       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12878     }
12879
12880     if (redirects != NULL) {
12881       qtdemux_process_redirects (qtdemux, redirects);
12882     }
12883   }
12884   return TRUE;
12885 }
12886
12887 static GstTagList *
12888 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12889 {
12890   const gchar *fmt;
12891
12892   if (tags == NULL) {
12893     tags = gst_tag_list_new_empty ();
12894     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12895   }
12896
12897   if (qtdemux->major_brand == FOURCC_mjp2)
12898     fmt = "Motion JPEG 2000";
12899   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12900     fmt = "3GP";
12901   else if (qtdemux->major_brand == FOURCC_qt__)
12902     fmt = "Quicktime";
12903   else if (qtdemux->fragmented)
12904     fmt = "ISO fMP4";
12905   else
12906     fmt = "ISO MP4/M4A";
12907
12908   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12909       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12910
12911   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12912       fmt, NULL);
12913
12914   return tags;
12915 }
12916
12917 /* we have read the complete moov node now.
12918  * This function parses all of the relevant info, creates the traks and
12919  * prepares all data structures for playback
12920  */
12921 static gboolean
12922 qtdemux_parse_tree (GstQTDemux * qtdemux)
12923 {
12924   GNode *mvhd;
12925   GNode *trak;
12926   GNode *udta;
12927   GNode *mvex;
12928   GstClockTime duration;
12929   GNode *pssh;
12930   guint64 creation_time;
12931   GstDateTime *datetime = NULL;
12932   gint version;
12933
12934   /* make sure we have a usable taglist */
12935   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12936
12937   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12938   if (mvhd == NULL) {
12939     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12940     return qtdemux_parse_redirects (qtdemux);
12941   }
12942
12943   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12944   if (version == 1) {
12945     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12946     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12947     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12948   } else if (version == 0) {
12949     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12950     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12951     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12952   } else {
12953     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12954     return FALSE;
12955   }
12956
12957   /* Moving qt creation time (secs since 1904) to unix time */
12958   if (creation_time != 0) {
12959     /* Try to use epoch first as it should be faster and more commonly found */
12960     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12961       GTimeVal now;
12962
12963       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12964       /* some data cleansing sanity */
12965       g_get_current_time (&now);
12966       if (now.tv_sec + 24 * 3600 < creation_time) {
12967         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12968       } else {
12969         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12970       }
12971     } else {
12972       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12973       GDateTime *dt, *dt_local;
12974
12975       dt = g_date_time_add_seconds (base_dt, creation_time);
12976       dt_local = g_date_time_to_local (dt);
12977       datetime = gst_date_time_new_from_g_date_time (dt_local);
12978
12979       g_date_time_unref (base_dt);
12980       g_date_time_unref (dt);
12981     }
12982   }
12983   if (datetime) {
12984     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12985     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12986         datetime, NULL);
12987     gst_date_time_unref (datetime);
12988   }
12989
12990   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12991   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12992
12993   /* check for fragmented file and get some (default) data */
12994   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12995   if (mvex) {
12996     GNode *mehd;
12997     GstByteReader mehd_data;
12998
12999     /* let track parsing or anyone know weird stuff might happen ... */
13000     qtdemux->fragmented = TRUE;
13001
13002     /* compensate for total duration */
13003     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13004     if (mehd)
13005       qtdemux_parse_mehd (qtdemux, &mehd_data);
13006   }
13007
13008   /* set duration in the segment info */
13009   gst_qtdemux_get_duration (qtdemux, &duration);
13010   if (duration) {
13011     qtdemux->segment.duration = duration;
13012     /* also do not exceed duration; stop is set that way post seek anyway,
13013      * and segment activation falls back to duration,
13014      * whereas loop only checks stop, so let's align this here as well */
13015     qtdemux->segment.stop = duration;
13016   }
13017
13018   /* parse all traks */
13019   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13020   while (trak) {
13021     qtdemux_parse_trak (qtdemux, trak);
13022     /* iterate all siblings */
13023     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13024   }
13025
13026   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13027
13028   /* find tags */
13029   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13030   if (udta) {
13031     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13032   } else {
13033     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13034   }
13035
13036   /* maybe also some tags in meta box */
13037   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13038   if (udta) {
13039     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13040     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13041   } else {
13042     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13043   }
13044
13045   /* parse any protection system info */
13046   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13047   while (pssh) {
13048     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13049     qtdemux_parse_pssh (qtdemux, pssh);
13050     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13051   }
13052
13053   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13054
13055   return TRUE;
13056 }
13057
13058 /* taken from ffmpeg */
13059 static int
13060 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13061 {
13062   int count = 4;
13063   int len = 0;
13064
13065   while (count--) {
13066     int c;
13067
13068     if (ptr >= end)
13069       return -1;
13070
13071     c = *ptr++;
13072     len = (len << 7) | (c & 0x7f);
13073     if (!(c & 0x80))
13074       break;
13075   }
13076   *end_out = ptr;
13077   return len;
13078 }
13079
13080 /* this can change the codec originally present in @list */
13081 static void
13082 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13083     GNode * esds, GstTagList * list)
13084 {
13085   int len = QT_UINT32 (esds->data);
13086   guint8 *ptr = esds->data;
13087   guint8 *end = ptr + len;
13088   int tag;
13089   guint8 *data_ptr = NULL;
13090   int data_len = 0;
13091   guint8 object_type_id = 0;
13092   const char *codec_name = NULL;
13093   GstCaps *caps = NULL;
13094
13095   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13096   ptr += 8;
13097   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13098   ptr += 4;
13099   while (ptr + 1 < end) {
13100     tag = QT_UINT8 (ptr);
13101     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13102     ptr++;
13103     len = read_descr_size (ptr, end, &ptr);
13104     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13105
13106     /* Check the stated amount of data is available for reading */
13107     if (len < 0 || ptr + len > end)
13108       break;
13109
13110     switch (tag) {
13111       case ES_DESCRIPTOR_TAG:
13112         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13113         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13114         ptr += 3;
13115         break;
13116       case DECODER_CONFIG_DESC_TAG:{
13117         guint max_bitrate, avg_bitrate;
13118
13119         object_type_id = QT_UINT8 (ptr);
13120         max_bitrate = QT_UINT32 (ptr + 5);
13121         avg_bitrate = QT_UINT32 (ptr + 9);
13122         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13123         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13124         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13125         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13126         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13127         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13128           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13129               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13130         }
13131         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13132           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13133               avg_bitrate, NULL);
13134         }
13135         ptr += 13;
13136         break;
13137       }
13138       case DECODER_SPECIFIC_INFO_TAG:
13139         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13140         if (object_type_id == 0xe0 && len == 0x40) {
13141           guint8 *data;
13142           GstStructure *s;
13143           guint32 clut[16];
13144           gint i;
13145
13146           GST_DEBUG_OBJECT (qtdemux,
13147               "Have VOBSUB palette. Creating palette event");
13148           /* move to decConfigDescr data and read palette */
13149           data = ptr;
13150           for (i = 0; i < 16; i++) {
13151             clut[i] = QT_UINT32 (data);
13152             data += 4;
13153           }
13154
13155           s = gst_structure_new ("application/x-gst-dvd", "event",
13156               G_TYPE_STRING, "dvd-spu-clut-change",
13157               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13158               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13159               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13160               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13161               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13162               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13163               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13164               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13165               NULL);
13166
13167           /* store event and trigger custom processing */
13168           stream->pending_event =
13169               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13170         } else {
13171           /* Generic codec_data handler puts it on the caps */
13172           data_ptr = ptr;
13173           data_len = len;
13174         }
13175
13176         ptr += len;
13177         break;
13178       case SL_CONFIG_DESC_TAG:
13179         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13180         ptr += 1;
13181         break;
13182       default:
13183         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13184             tag);
13185         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13186         ptr += len;
13187         break;
13188     }
13189   }
13190
13191   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13192    * in use, and should also be used to override some other parameters for some
13193    * codecs. */
13194   switch (object_type_id) {
13195     case 0x20:                 /* MPEG-4 */
13196       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13197        * profile_and_level_indication */
13198       if (data_ptr != NULL && data_len >= 5 &&
13199           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13200         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
13201             data_ptr + 4, data_len - 4);
13202       }
13203       break;                    /* Nothing special needed here */
13204     case 0x21:                 /* H.264 */
13205       codec_name = "H.264 / AVC";
13206       caps = gst_caps_new_simple ("video/x-h264",
13207           "stream-format", G_TYPE_STRING, "avc",
13208           "alignment", G_TYPE_STRING, "au", NULL);
13209       break;
13210     case 0x40:                 /* AAC (any) */
13211     case 0x66:                 /* AAC Main */
13212     case 0x67:                 /* AAC LC */
13213     case 0x68:                 /* AAC SSR */
13214       /* Override channels and rate based on the codec_data, as it's often
13215        * wrong. */
13216       /* Only do so for basic setup without HE-AAC extension */
13217       if (data_ptr && data_len == 2) {
13218         guint channels, rate;
13219
13220         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13221         if (channels > 0)
13222           stream->n_channels = channels;
13223
13224         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13225         if (rate > 0)
13226           stream->rate = rate;
13227       }
13228
13229       /* Set level and profile if possible */
13230       if (data_ptr != NULL && data_len >= 2) {
13231         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
13232             data_ptr, data_len);
13233       } else {
13234         const gchar *profile_str = NULL;
13235         GstBuffer *buffer;
13236         GstMapInfo map;
13237         guint8 *codec_data;
13238         gint rate_idx, profile;
13239
13240         /* No codec_data, let's invent something.
13241          * FIXME: This is wrong for SBR! */
13242
13243         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13244
13245         buffer = gst_buffer_new_and_alloc (2);
13246         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13247         codec_data = map.data;
13248
13249         rate_idx =
13250             gst_codec_utils_aac_get_index_from_sample_rate (stream->rate);
13251
13252         switch (object_type_id) {
13253           case 0x66:
13254             profile_str = "main";
13255             profile = 0;
13256             break;
13257           case 0x67:
13258             profile_str = "lc";
13259             profile = 1;
13260             break;
13261           case 0x68:
13262             profile_str = "ssr";
13263             profile = 2;
13264             break;
13265           default:
13266             profile = 3;
13267             break;
13268         }
13269
13270         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13271         codec_data[1] = ((rate_idx & 0x1) << 7) | (stream->n_channels << 3);
13272
13273         gst_buffer_unmap (buffer, &map);
13274         gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
13275             buffer, NULL);
13276         gst_buffer_unref (buffer);
13277
13278         if (profile_str) {
13279           gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
13280               profile_str, NULL);
13281         }
13282       }
13283       break;
13284     case 0x60:                 /* MPEG-2, various profiles */
13285     case 0x61:
13286     case 0x62:
13287     case 0x63:
13288     case 0x64:
13289     case 0x65:
13290       codec_name = "MPEG-2 video";
13291       caps = gst_caps_new_simple ("video/mpeg",
13292           "mpegversion", G_TYPE_INT, 2,
13293           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13294       break;
13295     case 0x69:                 /* MPEG-2 BC audio */
13296     case 0x6B:                 /* MPEG-1 audio */
13297       caps = gst_caps_new_simple ("audio/mpeg",
13298           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13299       codec_name = "MPEG-1 audio";
13300       break;
13301     case 0x6A:                 /* MPEG-1 */
13302       codec_name = "MPEG-1 video";
13303       caps = gst_caps_new_simple ("video/mpeg",
13304           "mpegversion", G_TYPE_INT, 1,
13305           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13306       break;
13307     case 0x6C:                 /* MJPEG */
13308       caps =
13309           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13310           NULL);
13311       codec_name = "Motion-JPEG";
13312       break;
13313     case 0x6D:                 /* PNG */
13314       caps =
13315           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13316           NULL);
13317       codec_name = "PNG still images";
13318       break;
13319     case 0x6E:                 /* JPEG2000 */
13320       codec_name = "JPEG-2000";
13321       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13322       break;
13323     case 0xA4:                 /* Dirac */
13324       codec_name = "Dirac";
13325       caps = gst_caps_new_empty_simple ("video/x-dirac");
13326       break;
13327     case 0xA5:                 /* AC3 */
13328       codec_name = "AC-3 audio";
13329       caps = gst_caps_new_simple ("audio/x-ac3",
13330           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13331       break;
13332     case 0xA9:                 /* AC3 */
13333       codec_name = "DTS audio";
13334       caps = gst_caps_new_simple ("audio/x-dts",
13335           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13336       break;
13337     case 0xE1:                 /* QCELP */
13338       /* QCELP, the codec_data is a riff tag (little endian) with
13339        * 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). */
13340       caps = gst_caps_new_empty_simple ("audio/qcelp");
13341       codec_name = "QCELP";
13342       break;
13343     default:
13344       break;
13345   }
13346
13347   /* If we have a replacement caps, then change our caps for this stream */
13348   if (caps) {
13349     gst_caps_unref (stream->caps);
13350     stream->caps = caps;
13351   }
13352
13353   if (codec_name && list)
13354     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13355         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13356
13357   /* Add the codec_data attribute to caps, if we have it */
13358   if (data_ptr) {
13359     GstBuffer *buffer;
13360
13361     buffer = gst_buffer_new_and_alloc (data_len);
13362     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13363
13364     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13365     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13366
13367     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
13368         buffer, NULL);
13369     gst_buffer_unref (buffer);
13370   }
13371
13372 }
13373
13374 static inline GstCaps *
13375 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13376 {
13377   GstCaps *caps;
13378   guint i;
13379   char *s, fourstr[5];
13380
13381   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13382   for (i = 0; i < 4; i++) {
13383     if (!g_ascii_isalnum (fourstr[i]))
13384       fourstr[i] = '_';
13385   }
13386   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13387   caps = gst_caps_new_empty_simple (s);
13388   g_free (s);
13389   return caps;
13390 }
13391
13392 #define _codec(name) \
13393   do { \
13394     if (codec_name) { \
13395       *codec_name = g_strdup (name); \
13396     } \
13397   } while (0)
13398
13399 static GstCaps *
13400 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13401     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13402 {
13403   GstCaps *caps = NULL;
13404   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13405
13406   switch (fourcc) {
13407     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
13408       _codec ("PNG still images");
13409       caps = gst_caps_new_empty_simple ("image/png");
13410       break;
13411     case FOURCC_jpeg:
13412       _codec ("JPEG still images");
13413       caps =
13414           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13415           NULL);
13416       break;
13417     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13418     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13419     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13420     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13421       _codec ("Motion-JPEG");
13422       caps =
13423           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13424           NULL);
13425       break;
13426     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13427       _codec ("Motion-JPEG format B");
13428       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13429       break;
13430     case FOURCC_mjp2:
13431       _codec ("JPEG-2000");
13432       /* override to what it should be according to spec, avoid palette_data */
13433       stream->bits_per_sample = 24;
13434       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13435       break;
13436     case FOURCC_SVQ3:
13437       _codec ("Sorensen video v.3");
13438       caps = gst_caps_new_simple ("video/x-svq",
13439           "svqversion", G_TYPE_INT, 3, NULL);
13440       break;
13441     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13442     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13443       _codec ("Sorensen video v.1");
13444       caps = gst_caps_new_simple ("video/x-svq",
13445           "svqversion", G_TYPE_INT, 1, NULL);
13446       break;
13447     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13448       caps = gst_caps_new_empty_simple ("video/x-raw");
13449       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13450       _codec ("Windows Raw RGB");
13451       stream->alignment = 32;
13452       break;
13453     case FOURCC_raw_:
13454     {
13455       guint16 bps;
13456
13457       bps = QT_UINT16 (stsd_data + 98);
13458       switch (bps) {
13459         case 15:
13460           format = GST_VIDEO_FORMAT_RGB15;
13461           break;
13462         case 16:
13463           format = GST_VIDEO_FORMAT_RGB16;
13464           break;
13465         case 24:
13466           format = GST_VIDEO_FORMAT_RGB;
13467           break;
13468         case 32:
13469           format = GST_VIDEO_FORMAT_ARGB;
13470           break;
13471         default:
13472           /* unknown */
13473           break;
13474       }
13475       break;
13476     }
13477     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13478       format = GST_VIDEO_FORMAT_I420;
13479       break;
13480     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13481     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13482       format = GST_VIDEO_FORMAT_I420;
13483       break;
13484     case FOURCC_2vuy:
13485     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13486       format = GST_VIDEO_FORMAT_UYVY;
13487       break;
13488     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13489       format = GST_VIDEO_FORMAT_v308;
13490       break;
13491     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13492       format = GST_VIDEO_FORMAT_v216;
13493       break;
13494     case FOURCC_v210:
13495       format = GST_VIDEO_FORMAT_v210;
13496       break;
13497     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13498       format = GST_VIDEO_FORMAT_r210;
13499       break;
13500       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13501          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13502          format = GST_VIDEO_FORMAT_v410;
13503          break;
13504        */
13505       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13506        * but different order than AYUV
13507        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13508        format = GST_VIDEO_FORMAT_v408;
13509        break;
13510        */
13511     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13512     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13513       _codec ("MPEG-1 video");
13514       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13515           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13516       break;
13517     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13518     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13519     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13520     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13521     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13522     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13523     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13524     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13525     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13526     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13527     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13528     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13529     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13530     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13531     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13532     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13533     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13534     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13535     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13536     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13537     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13538     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13539     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13540     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13541     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13542     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13543     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13544     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13545     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13546     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13547     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13548     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13549     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13550     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13551     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13552     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13553     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13554     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13555     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13556     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13557     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13558     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13559     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13560     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13561     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13562     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13563     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13564       _codec ("MPEG-2 video");
13565       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13566           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13567       break;
13568     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13569       _codec ("GIF still images");
13570       caps = gst_caps_new_empty_simple ("image/gif");
13571       break;
13572     case FOURCC_h263:
13573     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13574     case FOURCC_s263:
13575     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13576       _codec ("H.263");
13577       /* ffmpeg uses the height/width props, don't know why */
13578       caps = gst_caps_new_simple ("video/x-h263",
13579           "variant", G_TYPE_STRING, "itu", NULL);
13580       break;
13581     case FOURCC_mp4v:
13582     case FOURCC_MP4V:
13583       _codec ("MPEG-4 video");
13584       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13585           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13586       break;
13587     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13588     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13589       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13590       caps = gst_caps_new_simple ("video/x-msmpeg",
13591           "msmpegversion", G_TYPE_INT, 43, NULL);
13592       break;
13593     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13594       _codec ("DivX 3");
13595       caps = gst_caps_new_simple ("video/x-divx",
13596           "divxversion", G_TYPE_INT, 3, NULL);
13597       break;
13598     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13599     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13600       _codec ("DivX 4");
13601       caps = gst_caps_new_simple ("video/x-divx",
13602           "divxversion", G_TYPE_INT, 4, NULL);
13603       break;
13604     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13605       _codec ("DivX 5");
13606       caps = gst_caps_new_simple ("video/x-divx",
13607           "divxversion", G_TYPE_INT, 5, NULL);
13608       break;
13609
13610     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13611       _codec ("FFV1");
13612       caps = gst_caps_new_simple ("video/x-ffv",
13613           "ffvversion", G_TYPE_INT, 1, NULL);
13614       break;
13615
13616     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13617     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13618     case FOURCC_XVID:
13619     case FOURCC_xvid:
13620     case FOURCC_FMP4:
13621     case FOURCC_fmp4:
13622     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13623       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13624           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13625       _codec ("MPEG-4");
13626       break;
13627
13628     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13629       _codec ("Cinepak");
13630       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13631       break;
13632     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13633       _codec ("Apple QuickDraw");
13634       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13635       break;
13636     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13637       _codec ("Apple video");
13638       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13639       break;
13640     case FOURCC_H264:
13641     case FOURCC_avc1:
13642       _codec ("H.264 / AVC");
13643       caps = gst_caps_new_simple ("video/x-h264",
13644           "stream-format", G_TYPE_STRING, "avc",
13645           "alignment", G_TYPE_STRING, "au", NULL);
13646       break;
13647     case FOURCC_avc3:
13648       _codec ("H.264 / AVC");
13649       caps = gst_caps_new_simple ("video/x-h264",
13650           "stream-format", G_TYPE_STRING, "avc3",
13651           "alignment", G_TYPE_STRING, "au", NULL);
13652       break;
13653     case FOURCC_H265:
13654     case FOURCC_hvc1:
13655       _codec ("H.265 / HEVC");
13656       caps = gst_caps_new_simple ("video/x-h265",
13657           "stream-format", G_TYPE_STRING, "hvc1",
13658           "alignment", G_TYPE_STRING, "au", NULL);
13659       break;
13660     case FOURCC_hev1:
13661       _codec ("H.265 / HEVC");
13662       caps = gst_caps_new_simple ("video/x-h265",
13663           "stream-format", G_TYPE_STRING, "hev1",
13664           "alignment", G_TYPE_STRING, "au", NULL);
13665       break;
13666     case FOURCC_rle_:
13667       _codec ("Run-length encoding");
13668       caps = gst_caps_new_simple ("video/x-rle",
13669           "layout", G_TYPE_STRING, "quicktime", NULL);
13670       break;
13671     case FOURCC_WRLE:
13672       _codec ("Run-length encoding");
13673       caps = gst_caps_new_simple ("video/x-rle",
13674           "layout", G_TYPE_STRING, "microsoft", NULL);
13675       break;
13676     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13677     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13678       _codec ("Indeo Video 3");
13679       caps = gst_caps_new_simple ("video/x-indeo",
13680           "indeoversion", G_TYPE_INT, 3, NULL);
13681       break;
13682     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13683     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13684       _codec ("Intel Video 4");
13685       caps = gst_caps_new_simple ("video/x-indeo",
13686           "indeoversion", G_TYPE_INT, 4, NULL);
13687       break;
13688     case FOURCC_dvcp:
13689     case FOURCC_dvc_:
13690     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13691     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13692     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13693     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13694     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13695     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13696       _codec ("DV Video");
13697       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13698           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13699       break;
13700     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13701     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13702       _codec ("DVCPro50 Video");
13703       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13704           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13705       break;
13706     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13707     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13708       _codec ("DVCProHD Video");
13709       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13710           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13711       break;
13712     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13713       _codec ("Apple Graphics (SMC)");
13714       caps = gst_caps_new_empty_simple ("video/x-smc");
13715       break;
13716     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13717       _codec ("VP3");
13718       caps = gst_caps_new_empty_simple ("video/x-vp3");
13719       break;
13720     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13721       _codec ("VP6 Flash");
13722       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13723       break;
13724     case FOURCC_XiTh:
13725       _codec ("Theora");
13726       caps = gst_caps_new_empty_simple ("video/x-theora");
13727       /* theora uses one byte of padding in the data stream because it does not
13728        * allow 0 sized packets while theora does */
13729       stream->padding = 1;
13730       break;
13731     case FOURCC_drac:
13732       _codec ("Dirac");
13733       caps = gst_caps_new_empty_simple ("video/x-dirac");
13734       break;
13735     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13736       _codec ("TIFF still images");
13737       caps = gst_caps_new_empty_simple ("image/tiff");
13738       break;
13739     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13740       _codec ("Apple Intermediate Codec");
13741       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13742       break;
13743     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13744       _codec ("AVID DNxHD");
13745       caps = gst_caps_from_string ("video/x-dnxhd");
13746       break;
13747     case FOURCC_VP80:
13748       _codec ("On2 VP8");
13749       caps = gst_caps_from_string ("video/x-vp8");
13750       break;
13751     case FOURCC_apcs:
13752       _codec ("Apple ProRes LT");
13753       caps =
13754           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13755           NULL);
13756       break;
13757     case FOURCC_apch:
13758       _codec ("Apple ProRes HQ");
13759       caps =
13760           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13761           NULL);
13762       break;
13763     case FOURCC_apcn:
13764       _codec ("Apple ProRes");
13765       caps =
13766           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13767           "standard", NULL);
13768       break;
13769     case FOURCC_apco:
13770       _codec ("Apple ProRes Proxy");
13771       caps =
13772           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13773           "proxy", NULL);
13774       break;
13775     case FOURCC_ap4h:
13776       _codec ("Apple ProRes 4444");
13777       caps =
13778           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13779           "4444", NULL);
13780       break;
13781     case FOURCC_ap4x:
13782       _codec ("Apple ProRes 4444 XQ");
13783       caps =
13784           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13785           "4444xq", NULL);
13786       break;
13787     case FOURCC_cfhd:
13788       _codec ("GoPro CineForm");
13789       caps = gst_caps_from_string ("video/x-cineform");
13790       break;
13791     case FOURCC_vc_1:
13792     case FOURCC_ovc1:
13793       _codec ("VC-1");
13794       caps = gst_caps_new_simple ("video/x-wmv",
13795           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13796       break;
13797     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13798     default:
13799     {
13800       caps = _get_unknown_codec_name ("video", fourcc);
13801       break;
13802     }
13803   }
13804
13805   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13806     GstVideoInfo info;
13807
13808     gst_video_info_init (&info);
13809     gst_video_info_set_format (&info, format, stream->width, stream->height);
13810
13811     caps = gst_video_info_to_caps (&info);
13812     *codec_name = gst_pb_utils_get_codec_description (caps);
13813
13814     /* enable clipping for raw video streams */
13815     stream->need_clip = TRUE;
13816     stream->alignment = 32;
13817   }
13818
13819   return caps;
13820 }
13821
13822 static guint
13823 round_up_pow2 (guint n)
13824 {
13825   n = n - 1;
13826   n = n | (n >> 1);
13827   n = n | (n >> 2);
13828   n = n | (n >> 4);
13829   n = n | (n >> 8);
13830   n = n | (n >> 16);
13831   return n + 1;
13832 }
13833
13834 static GstCaps *
13835 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13836     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13837 {
13838   GstCaps *caps;
13839   const GstStructure *s;
13840   const gchar *name;
13841   gint endian = 0;
13842   GstAudioFormat format = 0;
13843   gint depth;
13844
13845   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13846
13847   depth = stream->bytes_per_packet * 8;
13848
13849   switch (fourcc) {
13850     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13851     case FOURCC_raw_:
13852       /* 8-bit audio is unsigned */
13853       if (depth == 8)
13854         format = GST_AUDIO_FORMAT_U8;
13855       /* otherwise it's signed and big-endian just like 'twos' */
13856     case FOURCC_twos:
13857       endian = G_BIG_ENDIAN;
13858       /* fall-through */
13859     case FOURCC_sowt:
13860     {
13861       gchar *str;
13862
13863       if (!endian)
13864         endian = G_LITTLE_ENDIAN;
13865
13866       if (!format)
13867         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13868
13869       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13870       _codec (str);
13871       g_free (str);
13872
13873       caps = gst_caps_new_simple ("audio/x-raw",
13874           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13875           "layout", G_TYPE_STRING, "interleaved", NULL);
13876       stream->alignment = GST_ROUND_UP_8 (depth);
13877       stream->alignment = round_up_pow2 (stream->alignment);
13878       break;
13879     }
13880     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13881       _codec ("Raw 64-bit floating-point audio");
13882       caps = gst_caps_new_simple ("audio/x-raw",
13883           "format", G_TYPE_STRING, "F64BE",
13884           "layout", G_TYPE_STRING, "interleaved", NULL);
13885       stream->alignment = 8;
13886       break;
13887     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13888       _codec ("Raw 32-bit floating-point audio");
13889       caps = gst_caps_new_simple ("audio/x-raw",
13890           "format", G_TYPE_STRING, "F32BE",
13891           "layout", G_TYPE_STRING, "interleaved", NULL);
13892       stream->alignment = 4;
13893       break;
13894     case FOURCC_in24:
13895       _codec ("Raw 24-bit PCM audio");
13896       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13897        * endian later */
13898       caps = gst_caps_new_simple ("audio/x-raw",
13899           "format", G_TYPE_STRING, "S24BE",
13900           "layout", G_TYPE_STRING, "interleaved", NULL);
13901       stream->alignment = 4;
13902       break;
13903     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13904       _codec ("Raw 32-bit PCM audio");
13905       caps = gst_caps_new_simple ("audio/x-raw",
13906           "format", G_TYPE_STRING, "S32BE",
13907           "layout", G_TYPE_STRING, "interleaved", NULL);
13908       stream->alignment = 4;
13909       break;
13910     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
13911       _codec ("Raw 16-bit PCM audio");
13912       caps = gst_caps_new_simple ("audio/x-raw",
13913           "format", G_TYPE_STRING, "S16LE",
13914           "layout", G_TYPE_STRING, "interleaved", NULL);
13915       stream->alignment = 2;
13916       break;
13917     case FOURCC_ulaw:
13918       _codec ("Mu-law audio");
13919       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13920       break;
13921     case FOURCC_alaw:
13922       _codec ("A-law audio");
13923       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13924       break;
13925     case 0x0200736d:
13926     case 0x6d730002:
13927       _codec ("Microsoft ADPCM");
13928       /* Microsoft ADPCM-ACM code 2 */
13929       caps = gst_caps_new_simple ("audio/x-adpcm",
13930           "layout", G_TYPE_STRING, "microsoft", NULL);
13931       break;
13932     case 0x1100736d:
13933     case 0x6d730011:
13934       _codec ("DVI/IMA ADPCM");
13935       caps = gst_caps_new_simple ("audio/x-adpcm",
13936           "layout", G_TYPE_STRING, "dvi", NULL);
13937       break;
13938     case 0x1700736d:
13939     case 0x6d730017:
13940       _codec ("DVI/Intel IMA ADPCM");
13941       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13942       caps = gst_caps_new_simple ("audio/x-adpcm",
13943           "layout", G_TYPE_STRING, "quicktime", NULL);
13944       break;
13945     case 0x5500736d:
13946     case 0x6d730055:
13947       /* MPEG layer 3, CBR only (pre QT4.1) */
13948     case FOURCC__mp3:
13949       _codec ("MPEG-1 layer 3");
13950       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13951       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13952           "mpegversion", G_TYPE_INT, 1, NULL);
13953       break;
13954     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
13955       _codec ("MPEG-1 layer 2");
13956       /* MPEG layer 2 */
13957       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
13958           "mpegversion", G_TYPE_INT, 1, NULL);
13959       break;
13960     case 0x20736d:
13961     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13962       _codec ("EAC-3 audio");
13963       caps = gst_caps_new_simple ("audio/x-eac3",
13964           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13965       stream->sampled = TRUE;
13966       break;
13967     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13968     case FOURCC_ac_3:
13969       _codec ("AC-3 audio");
13970       caps = gst_caps_new_simple ("audio/x-ac3",
13971           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13972       stream->sampled = TRUE;
13973       break;
13974     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13975     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13976       _codec ("DTS audio");
13977       caps = gst_caps_new_simple ("audio/x-dts",
13978           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13979       stream->sampled = TRUE;
13980       break;
13981     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13982     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13983       _codec ("DTS-HD audio");
13984       caps = gst_caps_new_simple ("audio/x-dts",
13985           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13986       stream->sampled = TRUE;
13987       break;
13988     case FOURCC_MAC3:
13989       _codec ("MACE-3");
13990       caps = gst_caps_new_simple ("audio/x-mace",
13991           "maceversion", G_TYPE_INT, 3, NULL);
13992       break;
13993     case FOURCC_MAC6:
13994       _codec ("MACE-6");
13995       caps = gst_caps_new_simple ("audio/x-mace",
13996           "maceversion", G_TYPE_INT, 6, NULL);
13997       break;
13998     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13999       /* ogg/vorbis */
14000       caps = gst_caps_new_empty_simple ("application/ogg");
14001       break;
14002     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14003       _codec ("DV audio");
14004       caps = gst_caps_new_empty_simple ("audio/x-dv");
14005       break;
14006     case FOURCC_mp4a:
14007       _codec ("MPEG-4 AAC audio");
14008       caps = gst_caps_new_simple ("audio/mpeg",
14009           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14010           "stream-format", G_TYPE_STRING, "raw", NULL);
14011       break;
14012     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14013       _codec ("QDesign Music");
14014       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14015       break;
14016     case FOURCC_QDM2:
14017       _codec ("QDesign Music v.2");
14018       /* FIXME: QDesign music version 2 (no constant) */
14019       if (FALSE && data) {
14020         caps = gst_caps_new_simple ("audio/x-qdm2",
14021             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14022             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14023             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14024       } else {
14025         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14026       }
14027       break;
14028     case FOURCC_agsm:
14029       _codec ("GSM audio");
14030       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14031       break;
14032     case FOURCC_samr:
14033       _codec ("AMR audio");
14034       caps = gst_caps_new_empty_simple ("audio/AMR");
14035       break;
14036     case FOURCC_sawb:
14037       _codec ("AMR-WB audio");
14038       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14039       break;
14040     case FOURCC_ima4:
14041       _codec ("Quicktime IMA ADPCM");
14042       caps = gst_caps_new_simple ("audio/x-adpcm",
14043           "layout", G_TYPE_STRING, "quicktime", NULL);
14044       break;
14045     case FOURCC_alac:
14046       _codec ("Apple lossless audio");
14047       caps = gst_caps_new_empty_simple ("audio/x-alac");
14048       break;
14049     case FOURCC_fLaC:
14050       _codec ("Free Lossless Audio Codec");
14051       caps = gst_caps_new_simple ("audio/x-flac",
14052           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14053       break;
14054     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14055       _codec ("QualComm PureVoice");
14056       caps = gst_caps_from_string ("audio/qcelp");
14057       break;
14058     case FOURCC_wma_:
14059     case FOURCC_owma:
14060       _codec ("WMA");
14061       caps = gst_caps_new_empty_simple ("audio/x-wma");
14062       break;
14063     case FOURCC_opus:
14064       _codec ("Opus");
14065       caps = gst_caps_new_empty_simple ("audio/x-opus");
14066       break;
14067     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
14068     {
14069       guint32 flags = 0;
14070       guint32 depth = 0;
14071       guint32 width = 0;
14072       GstAudioFormat format;
14073       enum
14074       {
14075         FLAG_IS_FLOAT = 0x1,
14076         FLAG_IS_BIG_ENDIAN = 0x2,
14077         FLAG_IS_SIGNED = 0x4,
14078         FLAG_IS_PACKED = 0x8,
14079         FLAG_IS_ALIGNED_HIGH = 0x10,
14080         FLAG_IS_NON_INTERLEAVED = 0x20
14081       };
14082       _codec ("Raw LPCM audio");
14083
14084       if (data && len >= 56) {
14085         depth = QT_UINT32 (data + 40);
14086         flags = QT_UINT32 (data + 44);
14087         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
14088       }
14089       if ((flags & FLAG_IS_FLOAT) == 0) {
14090         if (depth == 0)
14091           depth = 16;
14092         if (width == 0)
14093           width = 16;
14094         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14095             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14096             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14097         caps = gst_caps_new_simple ("audio/x-raw",
14098             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14099             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14100             "non-interleaved" : "interleaved", NULL);
14101         stream->alignment = GST_ROUND_UP_8 (depth);
14102         stream->alignment = round_up_pow2 (stream->alignment);
14103       } else {
14104         if (width == 0)
14105           width = 32;
14106         if (width == 64) {
14107           if (flags & FLAG_IS_BIG_ENDIAN)
14108             format = GST_AUDIO_FORMAT_F64BE;
14109           else
14110             format = GST_AUDIO_FORMAT_F64LE;
14111         } else {
14112           if (flags & FLAG_IS_BIG_ENDIAN)
14113             format = GST_AUDIO_FORMAT_F32BE;
14114           else
14115             format = GST_AUDIO_FORMAT_F32LE;
14116         }
14117         caps = gst_caps_new_simple ("audio/x-raw",
14118             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14119             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14120             "non-interleaved" : "interleaved", NULL);
14121         stream->alignment = width / 8;
14122       }
14123       break;
14124     }
14125     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14126       /* ? */
14127     default:
14128     {
14129       caps = _get_unknown_codec_name ("audio", fourcc);
14130       break;
14131     }
14132   }
14133
14134   if (caps) {
14135     GstCaps *templ_caps =
14136         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14137     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14138     gst_caps_unref (caps);
14139     gst_caps_unref (templ_caps);
14140     caps = intersection;
14141   }
14142
14143   /* enable clipping for raw audio streams */
14144   s = gst_caps_get_structure (caps, 0);
14145   name = gst_structure_get_name (s);
14146   if (g_str_has_prefix (name, "audio/x-raw")) {
14147     stream->need_clip = TRUE;
14148     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
14149     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14150   }
14151   return caps;
14152 }
14153
14154 static GstCaps *
14155 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14156     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
14157 {
14158   GstCaps *caps;
14159
14160   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14161
14162   switch (fourcc) {
14163     case FOURCC_mp4s:
14164       _codec ("DVD subtitle");
14165       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14166       stream->need_process = TRUE;
14167       break;
14168     case FOURCC_text:
14169       _codec ("Quicktime timed text");
14170       goto text;
14171     case FOURCC_tx3g:
14172       _codec ("3GPP timed text");
14173     text:
14174       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14175           "utf8", NULL);
14176       /* actual text piece needs to be extracted */
14177       stream->need_process = TRUE;
14178       break;
14179     case FOURCC_stpp:
14180       _codec ("XML subtitles");
14181       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14182       break;
14183     default:
14184     {
14185       caps = _get_unknown_codec_name ("text", fourcc);
14186       break;
14187     }
14188   }
14189   return caps;
14190 }
14191
14192 static GstCaps *
14193 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14194     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
14195 {
14196   GstCaps *caps;
14197
14198   switch (fourcc) {
14199     case FOURCC_m1v:
14200       _codec ("MPEG 1 video");
14201       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14202           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14203       break;
14204     default:
14205       caps = NULL;
14206       break;
14207   }
14208   return caps;
14209 }
14210
14211 static void
14212 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14213     const gchar * system_id)
14214 {
14215   gint i;
14216
14217   if (!qtdemux->protection_system_ids)
14218     qtdemux->protection_system_ids =
14219         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14220   /* Check whether we already have an entry for this system ID. */
14221   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14222     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14223     if (g_ascii_strcasecmp (system_id, id) == 0) {
14224       return;
14225     }
14226   }
14227   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14228   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14229           -1));
14230 }